diff options
author | Joerg Bornemann <joerg.bornemann@qt.io> | 2022-08-29 11:43:09 +0200 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@qt.io> | 2022-09-11 03:02:16 +0200 |
commit | 6ed89be125b2870394d8c6398f3a87ab9a1459b9 (patch) | |
tree | 69db9813ef344f1b74cf90e9ea2c8a8a29eaf67c | |
parent | 9807c4e5afc953444a4b5a161ceb31c68fdf2484 (diff) |
CMake: Introduce qt_generate_deploy_script
Should the deployment script that qt_generate_deploy_app_script not be
sufficient, the new function qt_generate_deploy_script can be used to
generate a custom deployment script. Before, one had to add quite some
boilerplate code to generate a custom deployment script.
The qt_generate_deploy_app_script function now uses
qt_generate_deploy_script internally.
The TARGET option of qt_generate_deploy_script is currently only used
for controlling the base name of the generated deployment script. We
will do more with the target in a subsequent commit.
Fixes: QTBUG-105731
Change-Id: I85bfc50dac1f0b0b1aae0f657f803e9e30f53616
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
6 files changed, 179 insertions, 32 deletions
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index 6397d15a5b..3d7b911827 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -2526,19 +2526,13 @@ endif() # This function is currently in Technical Preview. # Its signature and behavior might change. -function(qt6_generate_deploy_app_script) - # We use a TARGET keyword option instead of taking the target as the first - # positional argument. This is to keep open the possibility of deploying - # an app for which we don't have a target (e.g. an application from a - # third party project that the caller may want to include in their own - # package). We would add an EXECUTABLE keyword for that, which would be - # mutually exclusive with the TARGET keyword. - set(no_value_options - NO_UNSUPPORTED_PLATFORM_ERROR - ) +function(qt6_generate_deploy_script) + set(no_value_options "") set(single_value_options - TARGET + CONTENT FILENAME_VARIABLE + NAME + TARGET ) set(multi_value_options "") cmake_parse_arguments(PARSE_ARGV 0 arg @@ -2547,18 +2541,24 @@ function(qt6_generate_deploy_app_script) if(arg_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unexpected arguments: ${arg_UNPARSED_ARGUMENTS}") endif() - if(NOT arg_TARGET) - message(FATAL_ERROR "TARGET must be specified") - endif() if(NOT arg_FILENAME_VARIABLE) message(FATAL_ERROR "FILENAME_VARIABLE must be specified") endif() + if("${arg_CONTENT}" STREQUAL "") + message(FATAL_ERROR "CONTENT must be specified") + endif() # 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 # create deployment scripts for different scenarios). - string(MAKE_C_IDENTIFIER "${arg_TARGET}" target_id) + set(file_base_name "custom") + if(NOT "${arg_NAME}" STREQUAL "") + set(file_base_name "${arg_NAME}") + elseif(NOT "${arg_TARGET}" STREQUAL "") + set(file_base_name "${arg_TARGET}") + endif() + string(MAKE_C_IDENTIFIER "${file_base_name}" target_id) string(SHA1 args_hash "${ARGV}") string(SUBSTRING "${args_hash}" 0 10 short_hash) _qt_internal_get_deploy_impl_dir(deploy_impl_dir) @@ -2567,14 +2567,66 @@ function(qt6_generate_deploy_app_script) if(is_multi_config) string(APPEND file_name "-$<CONFIG>") endif() + string(APPEND file_name ".cmake") set(${arg_FILENAME_VARIABLE} "${file_name}" PARENT_SCOPE) + set(boiler_plate "include(${QT_DEPLOY_SUPPORT}) +") + list(TRANSFORM arg_CONTENT REPLACE "\\$" "\$") + file(GENERATE OUTPUT ${file_name} CONTENT "${boiler_plate}${arg_CONTENT}") +endfunction() + +if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS) + macro(qt_generate_deploy_script) + if(QT_DEFAULT_MAJOR_VERSION EQUAL 6) + qt6_generate_deploy_script(${ARGV}) + else() + message(FATAL_ERROR "qt_generate_deploy_script() is only available in Qt 6.") + endif() + endmacro() +endif() + +# This function is currently in Technical Preview. +# Its signature and behavior might change. +function(qt6_generate_deploy_app_script) + # We use a TARGET keyword option instead of taking the target as the first + # positional argument. This is to keep open the possibility of deploying + # an app for which we don't have a target (e.g. an application from a + # third party project that the caller may want to include in their own + # package). We would add an EXECUTABLE keyword for that, which would be + # mutually exclusive with the TARGET keyword. + set(no_value_options + NO_UNSUPPORTED_PLATFORM_ERROR + ) + set(single_value_options + TARGET + FILENAME_VARIABLE + ) + set(multi_value_options "") + cmake_parse_arguments(PARSE_ARGV 0 arg + "${no_value_options}" "${single_value_options}" "${multi_value_options}" + ) + if(arg_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unexpected arguments: ${arg_UNPARSED_ARGUMENTS}") + endif() + if(NOT arg_TARGET) + message(FATAL_ERROR "TARGET must be specified") + endif() + if(NOT arg_FILENAME_VARIABLE) + message(FATAL_ERROR "FILENAME_VARIABLE must be specified") + endif() + if(QT6_IS_SHARED_LIBS_BUILD) set(qt_build_type_string "shared Qt libs") else() set(qt_build_type_string "static Qt libs") endif() + set(generate_args + TARGET ${arg_TARGET} + FILENAME_VARIABLE file_name + ) + if(APPLE AND NOT IOS AND QT6_IS_SHARED_LIBS_BUILD) # TODO: Handle non-bundle applications if possible. get_target_property(is_bundle ${arg_TARGET} MACOSX_BUNDLE) @@ -2584,16 +2636,16 @@ function(qt6_generate_deploy_app_script) "on Apple platforms." ) endif() - file(GENERATE OUTPUT "${file_name}" CONTENT " -include(${QT_DEPLOY_SUPPORT}) + qt6_generate_deploy_script(${generate_args} + CONTENT " qt6_deploy_runtime_dependencies( EXECUTABLE $<TARGET_FILE_NAME:${arg_TARGET}>.app ) ") elseif(WIN32 AND QT6_IS_SHARED_LIBS_BUILD) - file(GENERATE OUTPUT "${file_name}" CONTENT " -include(${QT_DEPLOY_SUPPORT}) + qt6_generate_deploy_script(${generate_args} + CONTENT " qt6_deploy_runtime_dependencies( EXECUTABLE \${QT_DEPLOY_BIN_DIR}/$<TARGET_FILE_NAME:${arg_TARGET}> GENERATE_QT_CONF @@ -2610,12 +2662,13 @@ qt6_deploy_runtime_dependencies( "this target platform (${CMAKE_SYSTEM_NAME}, ${qt_build_type_string})." ) else() - file(GENERATE OUTPUT "${file_name}" CONTENT " -include(${QT_DEPLOY_SUPPORT}) + qt6_generate_deploy_script(${generate_args} + CONTENT " _qt_internal_show_skip_runtime_deploy_message(\"${qt_build_type_string}\") ") endif() + set(${arg_FILENAME_VARIABLE} "${file_name}" PARENT_SCOPE) endfunction() if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS) diff --git a/src/corelib/doc/snippets/cmake-macros/deployment.cmake b/src/corelib/doc/snippets/cmake-macros/deployment.cmake new file mode 100644 index 0000000000..c5979a9ff2 --- /dev/null +++ b/src/corelib/doc/snippets/cmake-macros/deployment.cmake @@ -0,0 +1,27 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +#! [qt_generate_deploy_script_example] +cmake_minimum_required(VERSION 3.16...3.22) +project(MyThings) + +find_package(Qt6 REQUIRED COMPONENTS Core) +qt_standard_project_setup() + +qt_add_executable(MyApp main.cpp) + +install(TARGETS MyApp + BUNDLE DESTINATION . + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +qt_generate_deploy_script( + TARGET MyApp + FILENAME_VARIABLE deploy_script + CONTENT " +qt_deploy_runtime_dependencies( + EXECUTABLE $<TARGET_FILE_NAME:MyApp> +) +") +install(SCRIPT ${deploy_script}) +#! [qt_generate_deploy_script_example] diff --git a/src/corelib/doc/src/cmake/qt_deploy_qt_conf.qdoc b/src/corelib/doc/src/cmake/qt_deploy_qt_conf.qdoc index 4f2b638835..e295b213e9 100644 --- a/src/corelib/doc/src/cmake/qt_deploy_qt_conf.qdoc +++ b/src/corelib/doc/src/cmake/qt_deploy_qt_conf.qdoc @@ -64,10 +64,9 @@ as shown in the example below. This helps avoid hard-coding an absolute path. \badcode # The following script must only be executed at install time -set(deploy_script "${CMAKE_CURRENT_BINARY_DIR}/deploy_custom.cmake") - -file(GENERATE OUTPUT ${deploy_script} CONTENT " -include(\"${QT_DEPLOY_SUPPORT}\") +qt_generate_deploy_script( + FILENAME_VARIABLE deploy_script + CONTENT " qt_deploy_qt_conf(\"\${QT_DEPLOY_PREFIX}/\${QT_DEPLOY_BIN_DIR}/qt.conf\" DATA_DIR \"./custom_data_dir\" TRANSLATIONS_DIR \"./custom_translations_dir\" 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 b3a3328098..e3e4901512 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 @@ -59,7 +59,11 @@ For deploying a QML application, use \l{qt6_generate_deploy_qml_app_script}{qt_generate_deploy_qml_app_script()} instead. +For generating a custom deployment script, use +\l{qt6_generate_deploy_script}{qt_generate_deploy_script}. + \sa {qt6_standard_project_setup}{qt_standard_project_setup()}, + {qt6_generate_deploy_script}{qt_generate_deploy_script()}, {qt6_generate_deploy_qml_app_script}{qt_generate_deploy_qml_app_script()} \section1 Example diff --git a/src/corelib/doc/src/cmake/qt_generate_deploy_script.qdoc b/src/corelib/doc/src/cmake/qt_generate_deploy_script.qdoc new file mode 100644 index 0000000000..17ef93f26c --- /dev/null +++ b/src/corelib/doc/src/cmake/qt_generate_deploy_script.qdoc @@ -0,0 +1,66 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\page qt_generate_deploy_script.html +\ingroup cmake-commands-qtcore + +\title qt_generate_deploy_script +\target qt6_generate_deploy_script + +\summary {Generate a custom deployment script.} + +\include cmake-find-package-core.qdocinc + +\cmakecommandsince 6.5 +\preliminarycmakecommand + +\section1 Synopsis + +\badcode +qt_generate_deploy_script( + FILENAME_VARIABLE var_name + [TARGET target] + [NAME script_name] + [CONTENT content] +) +\endcode + +\versionlessCMakeCommandsNote qt6_generate_deploy_script() + +\section1 Description + +The command generates a script whose full file path will be stored in the +variable named by the \c{FILENAME_VARIABLE} option. That script is only written +at CMake generation time. It is intended to be used with the \l{install(SCRIPT)} +command, which should come after the application's target has been installed +using \l{install(TARGETS)}. + +The command takes care of generating a file named suitably for multi-config +generators. Necessary includes are added such that Qt's CMake deployment +functions and variables are accessible. + +The \c TARGET argument specifies the target that will be deployed by the script. +This affects the file name of the generated script, unless \c NAME is specified. + +The \c NAME argument controls an identifiable portion within the deployment +script's automatically generated name. The \c NAME argument defaults to \c +custom if neither \c NAME nor \c TARGET are given. + +The \c CONTENT argument specifies the code that is written to the deployment +script. The content may contain generator expressions. + +This command is intended for generating custom deployment scripts that +directly call functions of Qt's deployment API. For less complex +deployment purposes, it is more convenient to use +\l{qt6_generate_deploy_app_script}{qt_generate_deploy_app_script()} or +\l{qt6_generate_deploy_qml_app_script}{qt_generate_deploy_qml_app_script()}. + +\sa {qt6_generate_deploy_app_script}{qt_generate_deploy_app_script()}, + {qt6_generate_deploy_qml_app_script}{qt_generate_deploy_qml_app_script()} + +\section1 Example + +\snippet cmake-macros/deployment.cmake qt_generate_deploy_script_example + +*/ diff --git a/src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies.qdocinc b/src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies.qdocinc index 3c7fb8d5ee..26503ddece 100644 --- a/src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies.qdocinc +++ b/src/corelib/doc/src/includes/cmake-deploy-runtime-dependencies.qdocinc @@ -23,13 +23,11 @@ endif() qt_add_executable(HelperApp helper.cpp) set(helper_app_path "\${QT_DEPLOY_BIN_DIR}/$<TARGET_FILE_NAME:HelperApp>") -# The following script must only be executed at install time -set(deploy_script "${CMAKE_CURRENT_BINARY_DIR}/deploy_MyApp.cmake") - -file(GENERATE OUTPUT ${deploy_script} CONTENT " -# Including the file pointed to by QT_DEPLOY_SUPPORT ensures the generated -# deployment script has access to qt_deploy_runtime_dependencies() -include(\"${QT_DEPLOY_SUPPORT}\") +# Generate a deployment script to be executed at install time +qt_generate_deploy_script( + TARGET MyApp + FILENAME_VARIABLE deploy_script + CONTENT " qt_deploy_runtime_dependencies( EXECUTABLE \"${executable_path}\" ADDITIONAL_EXECUTABLES \"${helper_app_path}\" |