diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/Qt6CoreDeploySupport.cmake | 126 | ||||
-rw-r--r-- | src/corelib/Qt6CoreMacros.cmake | 40 | ||||
-rw-r--r-- | src/corelib/doc/src/cmake/qt_generate_deploy_app_script.qdoc | 8 |
3 files changed, 167 insertions, 7 deletions
diff --git a/src/corelib/Qt6CoreDeploySupport.cmake b/src/corelib/Qt6CoreDeploySupport.cmake index 24ddc47bcb..7c307d18e0 100644 --- a/src/corelib/Qt6CoreDeploySupport.cmake +++ b/src/corelib/Qt6CoreDeploySupport.cmake @@ -105,6 +105,108 @@ if(NOT __QT_NO_CREATE_VERSIONLESS_FUNCTIONS) endfunction() endif() +# Copied from QtCMakeHelpers.cmake +function(_qt_internal_re_escape out_var str) + string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" regex "${str}") + set(${out_var} ${regex} PARENT_SCOPE) +endfunction() + +function(_qt_internal_generic_deployqt) + set(no_value_options + VERBOSE + ) + set(single_value_options + EXECUTABLE + LIB_DIR + PLUGINS_DIR + ) + set(multi_value_options + ADDITIONAL_EXECUTABLES + ADDITIONAL_LIBRARIES + ADDITIONAL_MODULES + ) + cmake_parse_arguments(PARSE_ARGV 0 arg + "${no_value_options}" "${single_value_options}" "${multi_value_options}" + ) + + if(arg_VERBOSE OR __QT_DEPLOY_VERBOSE) + set(verbose TRUE) + endif() + + # Make input file paths absolute + foreach(var IN ITEMS EXECUTABLE ADDITIONAL_EXECUTABLES ADDITIONAL_LIBRARIES ADDITIONAL_MODULES) + string(PREPEND var arg_) + set(abspaths "") + foreach(path IN LISTS ${var}) + get_filename_component(abspath "${path}" REALPATH BASE_DIR "${QT_DEPLOY_PREFIX}") + list(APPEND abspaths "${abspath}") + endforeach() + set(${var} "${abspaths}") + endforeach() + + # We need to get the runtime dependencies of plugins too. + list(APPEND arg_ADDITIONAL_MODULES ${__QT_DEPLOY_PLUGINS}) + + set(file_args "") + if(arg_EXECUTABLE OR arg_ADDITIONAL_EXECUTABLES) + list(APPEND file_args EXECUTABLES ${arg_EXECUTABLE} ${arg_ADDITIONAL_EXECUTABLES}) + endif() + if(arg_ADDITIONAL_LIBRARIES) + list(APPEND file_args LIBRARIES ${arg_ADDITIONAL_LIBRARIES}) + endif() + if(arg_ADDITIONAL_MODULES) + list(APPEND file_args MODULES ${arg_ADDITIONAL_MODULES}) + endif() + + # Compile a list of regular expressions that represent the Qt installation prefixes. + set(prefix_regexes) + foreach(path IN LISTS __QT_DEPLOY_QT_INSTALL_PREFIX + __QT_DEPLOY_QT_ADDITIONAL_PACKAGES_PREFIX_PATH) + _qt_internal_re_escape(path_rex "${path}") + list(APPEND prefix_regexes "^${path_rex}") + endforeach() + + # Get the runtime dependencies recursively, restricted to Qt's installation prefix. + file(GET_RUNTIME_DEPENDENCIES + ${file_args} + POST_INCLUDE_REGEXES ${prefix_regexes} + POST_EXCLUDE_REGEXES ".*" + RESOLVED_DEPENDENCIES_VAR resolved + UNRESOLVED_DEPENDENCIES_VAR unresolved + CONFLICTING_DEPENDENCIES_PREFIX conflicting + ) + if(verbose) + message("file(GET_RUNTIME_DEPENDENCIES ${file_args})") + foreach(file IN LISTS resolved) + message(" resolved: ${file}") + endforeach() + foreach(file IN LISTS unresolved) + message(" unresolved: ${file}") + endforeach() + foreach(file IN LISTS conflicting_FILENAMES) + message(" conflicting: ${file}") + message(" with ${conflicting_${file}}") + endforeach() + endif() + + # Deploy the Qt libraries. + file(INSTALL ${resolved} + DESTINATION "${QT_DEPLOY_PREFIX}/${arg_LIB_DIR}" + FOLLOW_SYMLINK_CHAIN + ) + + # Deploy the Qt plugins. + foreach(file_path IN LISTS __QT_DEPLOY_PLUGINS) + file(RELATIVE_PATH destination + "${__QT_DEPLOY_QT_INSTALL_PREFIX}/${__QT_DEPLOY_QT_INSTALL_PLUGINS}" + "${file_path}" + ) + get_filename_component(destination "${destination}" DIRECTORY) + string(PREPEND destination "${QT_DEPLOY_PREFIX}/${arg_PLUGINS_DIR}/") + file(INSTALL ${file_path} DESTINATION ${destination}) + endforeach() +endfunction() + # This function is currently in Technical Preview. # Its signature and behavior might change. function(qt6_deploy_runtime_dependencies) @@ -202,6 +304,8 @@ function(qt6_deploy_runtime_dependencies) list(APPEND tool_options --verbose 2) elseif(__QT_DEPLOY_SYSTEM_NAME STREQUAL Darwin) list(APPEND tool_options -verbose=3) + else() + list(APPEND tool_options VERBOSE) endif() endif() @@ -228,10 +332,28 @@ function(qt6_deploy_runtime_dependencies) # for debugging purposes. It may be removed at any time without warning. list(APPEND tool_options ${__qt_deploy_tool_extra_options}) + if(__QT_DEPLOY_TOOL STREQUAL "GRD") + message(STATUS "Running generic Qt deploy tool on ${arg_EXECUTABLE}") + + # Forward the ADDITIONAL_* arguments. + foreach(file_type EXECUTABLES LIBRARIES MODULES) + if("${arg_ADDITIONAL_${file_type}}" STREQUAL "") + continue() + endif() + list(APPEND tool_options ADDITIONAL_${file_type} ${arg_ADDITIONAL_${file_type}}) + endforeach() + + _qt_internal_generic_deployqt( + EXECUTABLE "${arg_EXECUTABLE}" + LIB_DIR "${arg_LIB_DIR}" + PLUGINS_DIR "${arg_PLUGINS_DIR}" + ${tool_options} + ) + return() + endif() + # Both windeployqt and macdeployqt don't differentiate between the different # types of binaries, so we merge the lists and treat them all the same. - # A purely CMake-based implementation would need to treat them differently - # because of how file(GET_RUNTIME_DEPENDENCIES) works. set(additional_binaries ${arg_ADDITIONAL_EXECUTABLES} ${arg_ADDITIONAL_LIBRARIES} diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index 1587af1302..3bea0f135b 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -2437,6 +2437,8 @@ function(_qt_internal_setup_deploy_support) set(safe_target_file "$<TARGET_FILE:$<IF:${have_deploy_tool},${target_if_exists},${target}>>") set(__QT_DEPLOY_TOOL "$<IF:${have_deploy_tool},${safe_target_file},${fallback}>") + elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT CMAKE_CROSSCOMPILING) + set(__QT_DEPLOY_TOOL "GRD") else() # Android is handled as a build target, not via this install-based approach. # Therefore, we don't consider androiddeployqt here. @@ -2480,6 +2482,10 @@ set(__QT_DEPLOY_GENERATOR_IS_MULTI_CONFIG \"${is_multi_config}\") set(__QT_DEPLOY_ACTIVE_CONFIG \"$<CONFIG>\") set(__QT_NO_CREATE_VERSIONLESS_FUNCTIONS \"${QT_NO_CREATE_VERSIONLESS_FUNCTIONS}\") set(__QT_DEFAULT_MAJOR_VERSION \"${QT_DEFAULT_MAJOR_VERSION}\") +set(__QT_DEPLOY_QT_ADDITIONAL_PACKAGES_PREFIX_PATH \"${QT_ADDITIONAL_PACKAGES_PREFIX_PATH}\") +set(__QT_DEPLOY_QT_INSTALL_PREFIX \"${QT6_INSTALL_PREFIX}\") +set(__QT_DEPLOY_QT_INSTALL_PLUGINS \"${QT6_INSTALL_PLUGINS}\") +set(__QT_DEPLOY_PLUGINS \"\") # Define the CMake commands to be made available during deployment. set(__qt_deploy_support_files @@ -2593,6 +2599,21 @@ function(qt6_generate_deploy_script) message(FATAL_ERROR "CONTENT must be specified") endif() + # Check whether manual finalization is needed. + if(CMAKE_VERSION VERSION_LESS "3.19") + get_target_property(is_immediately_finalized ${arg_TARGET} _qt_is_immediately_finalized) + if(is_immediately_finalized) + message(WARNING + "Deployment of plugins for target '${arg_TARGET}' will not work. " + "Either, upgrade CMake to version 3.19 or newer, or call " + "qt_finalize_target(${arg_TARGET}) after generating the deployment script." + ) + endif() + endif() + + # Mark the target as "to be deployed". + set_property(TARGET ${arg_TARGET} PROPERTY _qt_marked_for_deployment ON) + # Create a file name that will be unique for this target and the combination # of arguments passed to this command. This allows the project to call us # multiple times with different arguments for the same target (e.g. to @@ -2610,12 +2631,15 @@ function(qt6_generate_deploy_script) set(file_name "${deploy_impl_dir}/deploy_${target_id}_${short_hash}") get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG) if(is_multi_config) - string(APPEND file_name "-$<CONFIG>") + set(config_infix "-$<CONFIG>") + else() + set(config_infix "") endif() - string(APPEND file_name ".cmake") + string(APPEND file_name "${config_infix}.cmake") set(${arg_FILENAME_VARIABLE} "${file_name}" PARENT_SCOPE) set(boiler_plate "include(${QT_DEPLOY_SUPPORT}) +include(\"\${CMAKE_CURRENT_LIST_DIR}/${arg_TARGET}-plugins${config_infix}.cmake\" OPTIONAL) ") list(TRANSFORM arg_CONTENT REPLACE "\\$" "\$") file(GENERATE OUTPUT ${file_name} CONTENT "${boiler_plate}${arg_CONTENT}") @@ -2694,7 +2718,17 @@ qt6_deploy_runtime_dependencies( qt6_deploy_runtime_dependencies( EXECUTABLE $<TARGET_FILE:${arg_TARGET}> GENERATE_QT_CONF -)") +) +") + + elseif(UNIX AND NOT APPLE AND NOT ANDROID AND QT6_IS_SHARED_LIBS_BUILD) + qt6_generate_deploy_script(${generate_args} + CONTENT " +qt6_deploy_runtime_dependencies( + EXECUTABLE $<TARGET_FILE:${arg_TARGET}> + GENERATE_QT_CONF +) +") elseif(NOT arg_NO_UNSUPPORTED_PLATFORM_ERROR AND NOT QT_INTERNAL_NO_UNSUPPORTED_PLATFORM_ERROR) # Currently we don't deploy runtime dependencies if cross-compiling or using a static Qt. diff --git a/src/corelib/doc/src/cmake/qt_generate_deploy_app_script.qdoc b/src/corelib/doc/src/cmake/qt_generate_deploy_app_script.qdoc index e3e4901512..8d059f4c86 100644 --- a/src/corelib/doc/src/cmake/qt_generate_deploy_app_script.qdoc +++ b/src/corelib/doc/src/cmake/qt_generate_deploy_app_script.qdoc @@ -48,8 +48,12 @@ which should come after the application's target has been installed using The deployment script will call \l{qt_deploy_runtime_dependencies()} with a suitable set of options for the standard install layout. -Currently, this is only implemented for macOS app bundles built on a macOS -host and Windows executables built on a Windows host. +Currently, this is only implemented for +\list + \li macOS app bundles built on a macOS host, + \li Linux executables built on a Linux host, + \li and Windows executables built on a Windows host. +\endlist Cross-building a Windows executable on a Linux host, as well as similar scenarios, are not currently supported. Calling \c{qt_generate_deploy_app_script()} in such a case will result |