summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@qt.io>2022-08-16 10:42:48 +0200
committerJoerg Bornemann <joerg.bornemann@qt.io>2022-09-15 12:55:23 +0200
commitc9c04291f5f96ff885f7caae6c15ce9bc1377fcc (patch)
treebc2fc9d726915445181a2db48ec7089930b0b488 /src
parent6329fed0a8721a530d9dc485ecc5611a22db59d9 (diff)
CMake: Add Linux support to qt_deploy_runtime_dependencies
Before this change, qt_deploy_runtime_dependencies supported Windows and macOS only. We add a generic deployment method implemented in cmake-language with file(GET_RUNTIME_DEPENDENCIES). This deployment method is now enabled for shared builds on Linux. The file(GRD) command requires that the EXECUTABLE argument points to the executable in the build directory. Only libraries in Qt's installation directory are considered for deployment. This includes Qt's own libraries and also things like libicu*.so we're shipping with the installer. Unlike macdeployqt and windeployqt, the generic qt_deploy_runtime_dependencies does not yet support deploying translations. We will catch up on this in a later commit. Change-Id: Iea23abcdba774d4c1885c8d2c243eb3e48fb7fae Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/Qt6CoreDeploySupport.cmake126
-rw-r--r--src/corelib/Qt6CoreMacros.cmake40
-rw-r--r--src/corelib/doc/src/cmake/qt_generate_deploy_app_script.qdoc8
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