diff --git a/Code/Framework/AzToolsFramework/CMakeLists.txt b/Code/Framework/AzToolsFramework/CMakeLists.txt index 53dba8eb48..661cb43302 100644 --- a/Code/Framework/AzToolsFramework/CMakeLists.txt +++ b/Code/Framework/AzToolsFramework/CMakeLists.txt @@ -85,6 +85,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) AZ::AzManipulatorTestFramework.Static AZ::AzTest AZ::AzQtComponents + RUNTIME_DEPENDENCIES + 3rdParty::Qt::Test ) ly_add_googletest( NAME AZ::AzToolsFramework.Tests diff --git a/Code/Sandbox/Editor/CMakeLists.txt b/Code/Sandbox/Editor/CMakeLists.txt index e1fce97067..51620c6e37 100644 --- a/Code/Sandbox/Editor/CMakeLists.txt +++ b/Code/Sandbox/Editor/CMakeLists.txt @@ -104,7 +104,6 @@ ly_add_target( 3rdParty::Qt::Gui 3rdParty::Qt::Widgets 3rdParty::Qt::Concurrent - 3rdParty::Qt::WebEngineWidgets 3rdParty::tiff 3rdParty::squish-ccr 3rdParty::zlib diff --git a/Gems/QtForPython/Code/CMakeLists.txt b/Gems/QtForPython/Code/CMakeLists.txt index f0d82a1464..f8491a431c 100644 --- a/Gems/QtForPython/Code/CMakeLists.txt +++ b/Gems/QtForPython/Code/CMakeLists.txt @@ -23,7 +23,6 @@ endif() ly_add_target( NAME QtForPython.Editor.Static STATIC NAMESPACE Gem - find_package(Qt) FILES_CMAKE qtforpython_editor_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake PLATFORM_INCLUDE_FILES @@ -41,7 +40,7 @@ ly_add_target( Gem::EditorPythonBindings.Static RUNTIME_DEPENDENCIES 3rdParty::pyside2 - Qt5::Test + 3rdParty::Qt::Test ) ly_add_target( diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 3220271b42..fcc2ef4fe6 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -44,7 +44,7 @@ ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-linux ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-linux TARGETS googletest PACKAGE_HASH 7b7ad330f369450c316a4c4592d17fbb4c14c731c95bd8f37757203e8c2bbc1b) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-linux TARGETS GoogleBenchmark PACKAGE_HASH 4038878f337fc7e0274f0230f71851b385b2e0327c495fc3dd3d1c18a807928d) ly_associate_package(PACKAGE_NAME unwind-1.2.1-linux TARGETS unwind PACKAGE_HASH 3453265fb056e25432f611a61546a25f60388e315515ad39007b5925dd054a77) -ly_associate_package(PACKAGE_NAME qt-5.15.2-rev3-linux TARGETS Qt PACKAGE_HASH b7d9932647f4b138b3f0b124d70debd250d2a8a6dca52b04dcbe82c6369d48ca) +ly_associate_package(PACKAGE_NAME qt-5.15.2-rev4-linux TARGETS Qt PACKAGE_HASH 1122e0ec19b01cb02a11fcf34dbf884bc9049ba5ff04fb692bfb09d4e5ee1e6b) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-linux TARGETS libsamplerate PACKAGE_HASH 41643c31bc6b7d037f895f89d8d8d6369e906b92eff42b0fe05ee6a100f06261) ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev2-linux TARGETS OpenSSL PACKAGE_HASH b779426d1e9c5ddf71160d5ae2e639c3b956e0fb5e9fcaf9ce97c4526024e3bc) ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev2-linux TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 235606f98512c076a1ba84a8402ad24ac21945998abcea264e8e204678efc0ba) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index 3908d21ecf..b97209e8f7 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -46,5 +46,5 @@ ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-mac ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-mac TARGETS googletest PACKAGE_HASH cbf020d5ef976c5db8b6e894c6c63151ade85ed98e7c502729dd20172acae5a8) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-mac TARGETS GoogleBenchmark PACKAGE_HASH ad25de0146769c91e179953d845de2bec8ed4a691f973f47e3eb37639381f665) ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev1-mac TARGETS OpenSSL PACKAGE_HASH 28adc1c0616ac0482b2a9d7b4a3a3635a1020e87b163f8aba687c501cf35f96c) -ly_associate_package(PACKAGE_NAME qt-5.15.2-rev3-mac TARGETS Qt PACKAGE_HASH 4723ac43b19d4633c3fa4b9642f27c992d30cdc689f769f82869786f1c22a728) +ly_associate_package(PACKAGE_NAME qt-5.15.2-rev4-mac TARGETS Qt PACKAGE_HASH 08790d03a0e6ad808ad64cf25c3d75abd69a343f3d224fc39927e5c6e8738b98) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-mac TARGETS libsamplerate PACKAGE_HASH b912af40c0ac197af9c43d85004395ba92a6a859a24b7eacd920fed5854a97fe) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index e88e3143e8..279731765a 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -50,7 +50,7 @@ ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-windows ly_associate_package(PACKAGE_NAME d3dx12-headers-rev1-windows TARGETS d3dx12 PACKAGE_HASH 088c637159fba4a3e4c0cf08fb4921906fd4cca498939bd239db7c54b5b2f804) ly_associate_package(PACKAGE_NAME pyside2-qt-5.15.1-rev2-windows TARGETS pyside2 PACKAGE_HASH c90f3efcc7c10e79b22a33467855ad861f9dbd2e909df27a5cba9db9fa3edd0f) ly_associate_package(PACKAGE_NAME openimageio-2.1.16.0-rev2-windows TARGETS OpenImageIO PACKAGE_HASH 85a2a6cf35cbc4c967c56ca8074babf0955c5b490c90c6e6fd23c78db99fc282) -ly_associate_package(PACKAGE_NAME qt-5.15.2-rev2-windows TARGETS Qt PACKAGE_HASH 29966f22ec253dc9904e88ad48fe6b6a669302b2dc7049f2e2bbd4949e79e595) +ly_associate_package(PACKAGE_NAME qt-5.15.2-rev4-windows TARGETS Qt PACKAGE_HASH a4634caaf48192cad5c5f408504746e53d338856148285057274f6a0ccdc071d) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-windows TARGETS libsamplerate PACKAGE_HASH dcf3c11a96f212a52e2c9241abde5c364ee90b0f32fe6eeb6dcdca01d491829f) ly_associate_package(PACKAGE_NAME OpenMesh-8.1-rev1-windows TARGETS OpenMesh PACKAGE_HASH 1c1df639358526c368e790dfce40c45cbdfcfb1c9a041b9d7054a8949d88ee77) ly_associate_package(PACKAGE_NAME civetweb-1.8-rev1-windows TARGETS civetweb PACKAGE_HASH 36d0e58a59bcdb4dd70493fb1b177aa0354c945b06c30416348fd326cf323dd4) diff --git a/cmake/CommandExecution.cmake b/cmake/CommandExecution.cmake index b37664c048..3ed084bb42 100644 --- a/cmake/CommandExecution.cmake +++ b/cmake/CommandExecution.cmake @@ -87,4 +87,4 @@ endif() if(LY_TIMESTAMP_REFERENCE) # Touch the timestamp file file(TOUCH ${LY_TIMESTAMP_FILE}) -endif() \ No newline at end of file +endif() diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index d7f88f12ec..81c36a9c56 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -289,8 +289,6 @@ function(ly_add_target) foreach(prop IN ITEMS AUTOMOC AUTORCC) if(${ly_add_target_${prop}}) set_property(TARGET ${ly_add_target_NAME} PROPERTY ${prop} ON) - # Flag this target as depending on Qt - set_property(GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${ly_add_target_NAME} ON) endif() endforeach() if(${ly_add_target_AUTOUIC}) @@ -332,14 +330,6 @@ function(ly_add_target) VERBATIM ) - detect_qt_dependency(${ly_add_target_NAME} QT_DEPENDENCY) - if(QT_DEPENDENCY) - if(NOT COMMAND ly_qt_deploy) - message(FATAL_ERROR "Could not find function \"ly_qt_deploy\", this function should be defined in cmake/3rdParty/Platform/${PAL_PLATFORM_NAME}/Qt_${PAL_PLATFORM_NAME_LOWERCASE}.cmake") - endif() - - ly_qt_deploy(TARGET ${ly_add_target_NAME}) - endif() endif() if(ly_add_target_AUTOGEN_RULES) @@ -430,60 +420,6 @@ function(ly_delayed_target_link_libraries) endfunction() -#! detect_qt_dependency: Determine if a target will link directly to a Qt library -# -# qt deployment introspects a shared library or executable for its direct -# dependencies on Qt libraries. In CMake, this will be true if a target, or any -# of its link libraries which are static libraries, recursively, links to Qt. -function(detect_qt_dependency TARGET_NAME OUTPUT_VARIABLE) - - if(TARGET ${TARGET_NAME}) - get_target_property(alias ${TARGET_NAME} ALIASED_TARGET) - if(alias) - set(TARGET_NAME ${alias}) - endif() - endif() - - get_property(cached_is_qt_dependency GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${TARGET_NAME}) - if(cached_is_qt_dependency) - set(${OUTPUT_VARIABLE} ${cached_is_qt_dependency} PARENT_SCOPE) - return() - endif() - - if(${TARGET_NAME} MATCHES "^3rdParty::Qt::.*") - set_property(GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${TARGET_NAME} ON) - set(${OUTPUT_VARIABLE} ON PARENT_SCOPE) - return() - endif() - - get_property(delayed_link GLOBAL PROPERTY LY_DELAYED_LINK_${TARGET_NAME}) - set(exclude_library_types SHARED_LIBRARY MODULE_LIBRARY) - foreach(library IN LISTS delayed_link) - - if(TARGET ${library}) - get_target_property(child_target_type ${library} TYPE) - - # If the dependency to Qt has to go through a shared/module library, - # it is not a direct dependency - if (child_target_type IN_LIST exclude_library_types) - continue() - endif() - endif() - - detect_qt_dependency(${library} child_depends_on_qt) - if(child_depends_on_qt) - set_property(GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${TARGET_NAME} ON) - set(${OUTPUT_VARIABLE} ON PARENT_SCOPE) - return() - endif() - - endforeach() - - set_property(GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${TARGET_NAME} OFF) - set(${OUTPUT_VARIABLE} OFF PARENT_SCOPE) - -endfunction() - #! ly_parse_third_party_dependencies: Validates any 3rdParty library dependencies through the find_package command # # \arg:ly_THIRD_PARTY_LIBRARIES name of the target libraries to validate existance of through the find_package command. diff --git a/cmake/Platform/Android/RuntimeDependencies_android.cmake b/cmake/Platform/Android/RuntimeDependencies_android.cmake index 8b50ec465d..add036a8b8 100644 --- a/cmake/Platform/Android/RuntimeDependencies_android.cmake +++ b/cmake/Platform/Android/RuntimeDependencies_android.cmake @@ -9,4 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +set(LY_RUNTIME_DEPENDENCIES_TEMPLATE ${LY_ROOT_FOLDER}/cmake/Platform/Common/runtime_dependencies_common.cmake.in) include(cmake/Platform/Common/RuntimeDependencies_common.cmake) \ No newline at end of file diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 59a38132bc..0948cf68dd 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -440,16 +440,7 @@ function(ly_setup_runtime_dependencies) # Common functions used by the bellow code install(CODE -"function(ly_deploy_qt_install target_output) - execute_process(COMMAND \"${WINDEPLOYQT_EXECUTABLE}\" --verbose 0 --no-compiler-runtime \"\${target_output}\" ERROR_VARIABLE deploy_error RESULT_VARIABLE deploy_result) - if (NOT \${deploy_result} EQUAL 0) - if(NOT deploy_error MATCHES \"does not seem to be a Qt executable\" ) - message(SEND_ERROR \"Deploying qt for \${target_output} returned \${deploy_result}: \${deploy_error}\") - endif() - endif() -endfunction() - -function(ly_copy source_file target_directory) +"function(ly_copy source_file target_directory) file(COPY \"\${source_file}\" DESTINATION \"\${target_directory}\" FILE_PERMISSIONS ${LY_COPY_PERMISSIONS}) endfunction()" ) @@ -470,18 +461,6 @@ endfunction()" cmake_path(RELATIVE_PATH target_runtime_output_directory BASE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_runtime_output_subdirectory) endif() - # Qt - get_property(has_qt_dependency GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${target}) - if(has_qt_dependency) - # Qt deploy needs to be done after the binary is copied to the output, so we do a install(CODE) which effectively - # puts it as a postbuild step of the "install" target. Binaries are copied at that point. - if(NOT EXISTS ${WINDEPLOYQT_EXECUTABLE}) - message(FATAL_ERROR "Qt deploy executable not found: ${WINDEPLOYQT_EXECUTABLE}") - endif() - set(target_output "${install_output_folder}/${target_runtime_output_subdirectory}/$") - list(APPEND runtime_commands "ly_deploy_qt_install(\"${target_output}\")\n") - endif() - # runtime dependencies that need to be copied to the output set(target_file_dir "${install_output_folder}/${target_runtime_output_subdirectory}") ly_get_runtime_dependencies(runtime_dependencies ${target}) diff --git a/cmake/Platform/Common/RuntimeDependencies_common.cmake b/cmake/Platform/Common/RuntimeDependencies_common.cmake index 4ae914744f..d00dd71f1e 100644 --- a/cmake/Platform/Common/RuntimeDependencies_common.cmake +++ b/cmake/Platform/Common/RuntimeDependencies_common.cmake @@ -35,6 +35,8 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET) return() # Nothing to do endif() + ly_de_alias_target(${ly_TARGET} ly_TARGET) + # To optimize the search, we are going to cache the dependencies for the targets we already walked through. # To do so, we will create a variable named LY_RUNTIME_DEPENDENCIES_${ly_TARGET} which will contain a list # of all the dependencies @@ -96,15 +98,7 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET) # Add the imported locations get_target_property(is_imported ${ly_TARGET} IMPORTED) if(is_imported) - # Skip Qt if this is a 3rdParty - # Qt is deployed using qt_deploy, no need to copy the dependencies set(skip_imported FALSE) - string(REGEX MATCH "3rdParty::([^:,]*)" target_package ${ly_TARGET}) - if(target_package) - if(${CMAKE_MATCH_1} STREQUAL "Qt") - set(skip_imported TRUE) - endif() - endif() if(target_type MATCHES "(STATIC_LIBRARY)") # No need to copy these dependencies since the outputs are not used at runtime set(skip_imported TRUE) @@ -118,10 +112,35 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET) else() set(imported_property IMPORTED_LOCATION) endif() - get_target_property(target_locations ${ly_TARGET} ${imported_property}) + unset(target_locations) + get_target_property(target_locations ${ly_TARGET} ${imported_property}) if(target_locations) list(APPEND all_runtime_dependencies ${target_locations}) + else() + # Check if the property exists for configurations + unset(target_locations) + foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) + string(TOUPPER ${conf} UCONF) + unset(current_target_locations) + get_target_property(current_target_locations ${ly_TARGET} ${imported_property}_${UCONF}) + if(current_target_locations) + string(APPEND target_locations $<$:${current_target_locations}>) + else() + # try to use the mapping + get_target_property(mapped_conf ${ly_TARGET} MAP_IMPORTED_CONFIG_${UCONF}) + if(mapped_conf) + unset(current_target_locations) + get_target_property(current_target_locations ${ly_TARGET} ${imported_property}_${mapped_conf}) + if(current_target_locations) + string(APPEND target_locations $<$:${current_target_locations}>) + endif() + endif() + endif() + endforeach() + if(target_locations) + list(APPEND all_runtime_dependencies ${target_locations}) + endif() endif() endif() @@ -228,34 +247,23 @@ function(ly_delayed_generate_runtime_dependencies) endif() unset(runtime_dependencies) - set(runtime_commands " -function(ly_copy source_file target_directory) - get_filename_component(target_filename \"\${source_file}\" NAME) - if(NOT \"\${source_file}\" STREQUAL \"\${target_directory}/\${target_filename}\") - if(NOT EXISTS \"\${target_directory}\") - file(MAKE_DIRECTORY \"\${target_directory}\") - endif() - if(\"\${source_file}\" IS_NEWER_THAN \"\${target_directory}/\${target_filename}\") - file(LOCK \"\${target_directory}/\${target_filename}.lock\" GUARD FUNCTION TIMEOUT 30) - file(COPY \"\${source_file}\" DESTINATION \"\${target_directory}\" FILE_PERMISSIONS ${LY_COPY_PERMISSIONS}) - endif() - endif() -endfunction() - \n") + unset(LY_COPY_COMMANDS) ly_get_runtime_dependencies(runtime_dependencies ${target}) foreach(runtime_dependency ${runtime_dependencies}) unset(runtime_command) ly_get_runtime_dependency_command(runtime_command ${runtime_dependency}) - string(APPEND runtime_commands ${runtime_command}) + string(APPEND LY_COPY_COMMANDS ${runtime_command}) endforeach() - + # Generate the output file set(target_file_dir "$") - string(CONFIGURE "${runtime_commands}" generated_commands @ONLY) + file(READ ${LY_RUNTIME_DEPENDENCIES_TEMPLATE} template_file) + string(CONFIGURE "${LY_COPY_COMMANDS}" LY_COPY_COMMANDS @ONLY) + string(CONFIGURE "${template_file}" configured_template_file @ONLY) file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/runtime_dependencies/$/${target}.cmake - CONTENT "${generated_commands}" + CONTENT "${configured_template_file}" ) endforeach() diff --git a/cmake/Platform/Common/runtime_dependencies_common.cmake.in b/cmake/Platform/Common/runtime_dependencies_common.cmake.in new file mode 100644 index 0000000000..c245d185d7 --- /dev/null +++ b/cmake/Platform/Common/runtime_dependencies_common.cmake.in @@ -0,0 +1,28 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +cmake_policy(SET CMP0012 NEW) # new policy for the if that evaluates a boolean out of "if(NOT ${same_location})" + +function(ly_copy source_file target_directory) + get_filename_component(target_filename "${source_file}" NAME) + cmake_path(COMPARE "${source_file}" EQUAL "${target_directory}/${target_filename}" same_location) + if(NOT ${same_location}) + if(NOT EXISTS "${target_directory}") + file(MAKE_DIRECTORY "${target_directory}") + endif() + if("${source_file}" IS_NEWER_THAN "${target_directory}/${target_filename}") + file(COPY "${source_file}" DESTINATION "${target_directory}" FILE_PERMISSIONS @LY_COPY_PERMISSIONS@ FOLLOW_SYMLINK_CHAIN) + endif() + endif() +endfunction() + +file(LOCK "${CMAKE_BINARY_DIR}/runtimedependencies.lock" TIMEOUT 300) +@LY_COPY_COMMANDS@ diff --git a/cmake/Platform/Linux/RuntimeDependencies_linux.cmake b/cmake/Platform/Linux/RuntimeDependencies_linux.cmake index 8b50ec465d..add036a8b8 100644 --- a/cmake/Platform/Linux/RuntimeDependencies_linux.cmake +++ b/cmake/Platform/Linux/RuntimeDependencies_linux.cmake @@ -9,4 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +set(LY_RUNTIME_DEPENDENCIES_TEMPLATE ${LY_ROOT_FOLDER}/cmake/Platform/Common/runtime_dependencies_common.cmake.in) include(cmake/Platform/Common/RuntimeDependencies_common.cmake) \ No newline at end of file diff --git a/cmake/Platform/Linux/platform_linux_files.cmake b/cmake/Platform/Linux/platform_linux_files.cmake index 8b6bdf1361..0a9a244ef0 100644 --- a/cmake/Platform/Linux/platform_linux_files.cmake +++ b/cmake/Platform/Linux/platform_linux_files.cmake @@ -19,6 +19,5 @@ set(FILES LYWrappers_linux.cmake PAL_linux.cmake PALDetection_linux.cmake - windeployqt_wrapper.cmake RPathChange.cmake ) diff --git a/cmake/Platform/Linux/windeployqt_wrapper.cmake b/cmake/Platform/Linux/windeployqt_wrapper.cmake deleted file mode 100644 index 320b49aa7a..0000000000 --- a/cmake/Platform/Linux/windeployqt_wrapper.cmake +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/cmake -P - -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -# We use windeployqt on Linux to copy the necessary Qt libraries and files to -# the build directory. After these files are copied, we need to adjust their -# rpath to point to Qt from the build tree. - -# This script is invoked through the CommandExecution.cmake script. The invoked -# commandline is something like: -# cmake -P CommandExecution.cmake EXEC_COMMAND cmake -E env ... cmake -P windeployqt_wrapper.cmake args -# ^ 1 ^ 2 ^ 3 -# cmake #1 invokes cmake #2 which invokes cmake #3. But cmake #1 also sees 2 -P -# arguments, so cmake #1 also invokes windeployqt_wrapper.cmake after -# CommandExecution.cmake finishes. We don't want to run this script 2x, so -# detect this case and exit early - -# Find the first -P argument -foreach(argi RANGE 1 ${CMAKE_ARGC}) - if("${CMAKE_ARGV${argi}}" STREQUAL "-P") - math(EXPR script_argi "${argi} + 1") - set(script_file "${CMAKE_ARGV${script_argi}}") - break() - endif() -endforeach() - -if(NOT script_file STREQUAL "${CMAKE_CURRENT_LIST_FILE}") - return() -endif() - -set(runtime_directory ${CMAKE_ARGV3}) - -foreach(argi RANGE 4 ${CMAKE_ARGC}) - list(APPEND command_arguments "${CMAKE_ARGV${argi}}") -endforeach() -execute_process(COMMAND ${command_arguments} RESULT_VARIABLE command_result OUTPUT_VARIABLE command_output ERROR_VARIABLE command_err) - -if(command_result) - message(FATAL_ERROR "windeployqt returned a non-zero exit status. stdout: ${command_output} stderr: ${command_err}") -endif() - -# Process the output to find the list of files that were updated - -# Transform the output to a list -string(REGEX REPLACE ";" "\\\\;" command_output "${command_output}") -string(REGEX REPLACE "\n" ";" command_output "${command_output}") - -foreach(line IN LISTS command_output) - # windeployqt has output that looks like this if it updated a file: - # > Checking /path/to/src/file.so, /path/to/dst/file.so - # > Updating file.so - # If the file was not modified, it will look like this: - # > Checking /path/to/src/file.so, /path/to/dst/file.so - # > file.so is up to date - if(line MATCHES "^Checking .*") - set(curfile "${line}") - continue() - endif() - - if(line MATCHES "^Updating .*") - # curline has 3 parts, 1) "Checking ", 2) source_file, 3) updated_target_file. We - # just need part 3. But we also want to handle the unfortunate - # possibility of spaces in the filename. - - string(REGEX REPLACE "^Checking " "" curfile "${curfile}") - string(REPLACE ", " ";" curfile "${curfile}") - list(LENGTH curfile curfile_parts_count) - if(NOT curfile_parts_count EQUAL 2) - message(SEND_ERROR "Unable to parse output of windeployqt output line ${curfile}") - continue() - endif() - list(GET curfile 1 updated_file) - - file(RELATIVE_PATH relative_file "${runtime_directory}" "${updated_file}") - - get_filename_component(basename "${relative_file}" NAME) - if(basename MATCHES "^libQt5Core\\.so.*") - # We don't need to patch QtCore - continue() - endif() - - # READ_ELF has a CAPTURE_ERROR argument, but that is only set on - # platforms that don't support cmake's elf parser. On linux, no error - # will be set, even when the input is not an ELF formatted file. We - # want to skip any non-executable files, so check for the ELF tag at - # the head of the file. - file(READ "${updated_file}" elf_tag LIMIT 4 HEX) - if(NOT elf_tag STREQUAL 7f454c46) # Binary \0x7f followed by ELF - continue() - endif() - - # READ_ELF is an undocumented command that allows us to introspect the - # current rpath set in the file - file(READ_ELF "${updated_file}" RUNPATH plugin_runpath) - - get_filename_component(dirname "${relative_file}" DIRECTORY) - if(dirname) - file(RELATIVE_PATH parent_dirs "${updated_file}" "${runtime_directory}") - string(REGEX REPLACE "/../$" "" parent_dirs "${parent_dirs}") - set(new_runpath "\$ORIGIN/${parent_dirs}") - else() - set(new_runpath "\$ORIGIN") - endif() - - # RPATH_CHANGE is an undocumented command that allows for replacing an - # existing rpath entry with a new value, as long as the new value's - # strlen is <= the current rpath - file(RPATH_CHANGE FILE "${updated_file}" OLD_RPATH "${plugin_runpath}" NEW_RPATH "${new_runpath}") - - unset(curfile) - endif() -endforeach() diff --git a/cmake/Platform/Mac/RuntimeDependencies_mac.cmake b/cmake/Platform/Mac/RuntimeDependencies_mac.cmake index 8b50ec465d..383a3d5985 100644 --- a/cmake/Platform/Mac/RuntimeDependencies_mac.cmake +++ b/cmake/Platform/Mac/RuntimeDependencies_mac.cmake @@ -9,4 +9,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +set(LY_BUILD_FIXUP_BUNDLE TRUE CACHE BOOL "Fix bundles on build (deploys frameworks and calls fixup_bundle)") + +set(LY_RUNTIME_DEPENDENCIES_TEMPLATE ${LY_ROOT_FOLDER}/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in) include(cmake/Platform/Common/RuntimeDependencies_common.cmake) \ No newline at end of file diff --git a/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in b/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in new file mode 100644 index 0000000000..6ad428c08d --- /dev/null +++ b/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in @@ -0,0 +1,146 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +function(gp_resolve_item_override context item exepath dirs resolved_item_var resolved_var) + # Qt frameworks could resolve the binary to eg qt/lib/QtCore.framework/Headers/QtCore instead of qt/lib/QtCore.framework/Versions/5/QtCore + # This is because GetPrerequisites.cmake gp_resolve_item function searches for the first file that matches the "frameworks name" + if(${${resolved_var}} AND ${item} MATCHES "/(Qt[^\\.]+\\.framework)/(.*)") + set(qt_framework ${CMAKE_MATCH_1}) + set(qt_framework_subpath ${CMAKE_MATCH_2}) + string(REGEX REPLACE "(.*)/(Qt[^\\.]+\\.framework)/(.*)" "\\1/\\2/${qt_framework_subpath}" new_resolved_item "${${resolved_item_var}}") + set(${resolved_item_var} ${new_resolved_item} PARENT_SCOPE) + endif() +endfunction() + +include(BundleUtilities) + +cmake_policy(SET CMP0012 NEW) # new policy for the if that evaluates a boolean out of the LY_BUILD_FIXUP_BUNDLE expansion + +set(anything_new FALSE) +set(plugin_libs) +set(plugin_dirs) + +function(ly_copy source_file target_directory) + + get_filename_component(target_filename "${source_file}" NAME) + + # If source_file is a Framework and target_directory is a bundle + if("${source_file}" MATCHES "\\.[Ff]ramework[^\\.]" AND "${target_directory}" MATCHES "\\.app/Contents/MacOS") + + if(NOT @LY_BUILD_FIXUP_BUNDLE@) + return() + endif() + + # fixup origin to copy the whole Framework folder and change destination to Contents/Frameworks + string(REGEX REPLACE "(.*\\.[Ff]ramework).*" "\\1" source_file "${source_file}") + get_filename_component(source_file_folder "${source_file}" DIRECTORY) + + set(local_plugin_dirs ${plugin_dirs}) + list(APPEND local_plugin_dirs "${source_file_folder}") + set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE) + return() + + elseif("${source_file}" MATCHES "qt/plugins" AND "${target_directory}" MATCHES "\\.app/Contents/MacOS") + + if(NOT @LY_BUILD_FIXUP_BUNDLE@) + return() + endif() + + # fixup the destination so it ends up in Contents/Plugins + string(REGEX REPLACE "(.*\\.app/Contents)/MacOS" "\\1/plugins" target_directory "${target_directory}") + + set(local_plugin_dirs ${plugin_dirs}) + list(APPEND local_plugin_dirs "${target_directory}") + set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE) + set(local_plugin_libs ${plugin_libs}) + list(APPEND local_plugin_libs "${target_directory}/${target_filename}") + set(plugin_libs ${local_plugin_libs} PARENT_SCOPE) + + elseif("${source_file}" MATCHES "qt/translations" AND "${target_directory}" MATCHES "\\.app/Contents/MacOS") + + return() # skip, is this used? + + elseif("${source_file}" MATCHES ".dylib") + + set(local_plugin_dirs ${plugin_dirs}) + list(APPEND local_plugin_dirs "${target_directory}") + set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE) + + endif() + + cmake_path(COMPARE "${source_file}" EQUAL "${target_directory}/${target_filename}" same_location) + if(NOT ${same_location}) + if(NOT EXISTS "${target_directory}") + file(MAKE_DIRECTORY "${target_directory}") + endif() + if(NOT EXISTS "${target_directory}/${target_filename}" OR "${source_file}" IS_NEWER_THAN "${target_directory}/${target_filename}") + message(STATUS "Copying \"${source_file}\" to \"${target_directory}\"...") + file(COPY "${source_file}" DESTINATION "${target_directory}" FILE_PERMISSIONS @LY_COPY_PERMISSIONS@ FOLLOW_SYMLINK_CHAIN) + file(TOUCH ${target_directory}/${target_filename}) + set(anything_new TRUE PARENT_SCOPE) + endif() + endif() +endfunction() + +@LY_COPY_COMMANDS@ + +if(NOT @LY_BUILD_FIXUP_BUNDLE@) + return() +endif() + +if(@target_file_dir@ MATCHES ".app/Contents/MacOS") + string(REGEX REPLACE "(.*\\.app)/Contents/MacOS.*" "\\1" bundle_path "@target_file_dir@") + set(fixup_timestamp_file "${bundle_path}.fixup.stamp") + if(NOT anything_new) + if(NOT EXISTS "${fixup_timestamp_file}" OR "${bundle_path}" IS_NEWER_THAN "${fixup_timestamp_file}") + set(anything_new TRUE) + endif() + endif() + if(anything_new) + # LYN-4505: Patch dxc, is configured in the wrong folder in 3p + if(EXISTS ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7) + # we copy to not invalidate the copy check from above + file(COPY ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/lib/libdxcompiler.3.7.dylib + DESTINATION ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin + ) + endif() + # Python.framework being copied by fixup_bundle + #if(EXISTS ${bundle_path}/Contents/Frameworks/Python.framework) + # # LYN-4502: Patch python bundle, it contains some windows executables, some files that fixup_bundle doesnt like and has + # # duplicated binaries between Versions/3.7 and Versions/Current. + # file(GLOB exe_files + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/distutils/command/*.exe + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pip/_vendor/distlib/*.exe + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/setuptools/*.exe + # ) + # foreach(exe_file ${exe_files}) + # file(REMOVE ${exe_file}) + # endforeach() + # file(REMOVE_RECURSE + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/test + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/scipy/io/tests + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/Resources + # ${bundle_path}/Contents/Frameworks/Python.framework/Python + # ${bundle_path}/Contents/Frameworks/Python.framework/Resources/Python.app + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/Python + # ) + # file(REMOVE_RECURSE ${bundle_path}/Contents/Frameworks/Python.framework/Versions/Current) + # execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink 3.7 Current + # WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework/Versions/ + # ) + #endif() + list(REMOVE_DUPLICATES plugin_libs) + list(REMOVE_DUPLICATES plugin_dirs) + fixup_bundle("${bundle_path}" "${plugin_libs}" "${plugin_dirs}") + file(TOUCH "${bundle_path}") + file(TOUCH "${fixup_timestamp_file}") + endif() +endif() diff --git a/cmake/Platform/Windows/RuntimeDependencies_windows.cmake b/cmake/Platform/Windows/RuntimeDependencies_windows.cmake index 8b50ec465d..add036a8b8 100644 --- a/cmake/Platform/Windows/RuntimeDependencies_windows.cmake +++ b/cmake/Platform/Windows/RuntimeDependencies_windows.cmake @@ -9,4 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +set(LY_RUNTIME_DEPENDENCIES_TEMPLATE ${LY_ROOT_FOLDER}/cmake/Platform/Common/runtime_dependencies_common.cmake.in) include(cmake/Platform/Common/RuntimeDependencies_common.cmake) \ No newline at end of file