qtbase/cmake/QtExecutableHelpers.cmake

505 lines
19 KiB
CMake
Raw Permalink Normal View History

# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
# This function creates a CMake target for a generic console or GUI binary.
# Please consider to use a more specific version target like the one created
# by qt_add_test or qt_add_tool below.
# One-value Arguments:
# CORE_LIBRARY
# The argument accepts 'Bootstrap' or 'None' values. If the argument value is set to
# 'Bootstrap' the Qt::Bootstrap library is linked to the executable instead of Qt::Core.
# The 'None' value points that core library is not necessary and avoids linking neither
# Qt::Core or Qt::Bootstrap libraries. Otherwise the Qt::Core library will be publicly
# linked to the executable target by default.
function(qt_internal_add_executable name)
cmake_parse_arguments(PARSE_ARGV 1 arg
"${__qt_internal_add_executable_optional_args}"
"${__qt_internal_add_executable_single_args}"
"${__qt_internal_add_executable_multi_args}")
_qt_internal_validate_all_args_are_parsed(arg)
if ("x${arg_OUTPUT_DIRECTORY}" STREQUAL "x")
set(arg_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_BINDIR}")
endif()
get_filename_component(arg_OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}"
ABSOLUTE BASE_DIR "${QT_BUILD_DIR}")
if ("x${arg_INSTALL_DIRECTORY}" STREQUAL "x")
set(arg_INSTALL_DIRECTORY "${INSTALL_BINDIR}")
endif()
_qt_internal_create_executable(${name})
qt_internal_mark_as_internal_target(${name})
CMake:Android: add wrapper scripts to easily run apps Create a script that allows running an app or a test easily similar to running on host. This improves development workflow and time by allowing quick runs without having to manually call the various adb commands to launch, get a pid of the app and then print the logcat, let alone passing parameters or environment variables. For normal apps, the app package name is retrieved by the script, run and live logcat is printed as long as the app is still running. For tests, the script calls androidtestrunner, allowing test parameters to be passed to the test. For CI debugging, this would save quite a lot of hussle and frustration trying to run or debug a test app. One other benefit for this is enabling running Android tests from Qt Creator's testlib plugin without big changes to Qt Creator to support androidtestrunner explicitly. Because file(GENERATE) would fail if called twice for the same file, I use file(WRITE). This is used because at the time of calling the target executable finalizer, we don't know if the target is a test or not, so we rely on writing the script first as a normal target, then call it if the target is a test where it overrides the script. For this also, parameters passed to the runner or androidtestrunner can't handle generator expressions. [ChangeLog][CMake][Android] Add wrapper scripts to run Android apps and tests with ease from the host. Task-number: QTBUG-129889 Change-Id: I84e85ce2bbf6944c8aa20bdc2c2b6d7b956bc748 Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
2024-10-07 17:43:31 +03:00
set_target_properties(${name} PROPERTIES
_qt_is_test_executable ${arg_QT_TEST}
_qt_is_manual_test ${arg_QT_MANUAL_TEST}
_qt_is_benchmark_test ${arg_QT_BENCHMARK_TEST}
CMake:Android: add wrapper scripts to easily run apps Create a script that allows running an app or a test easily similar to running on host. This improves development workflow and time by allowing quick runs without having to manually call the various adb commands to launch, get a pid of the app and then print the logcat, let alone passing parameters or environment variables. For normal apps, the app package name is retrieved by the script, run and live logcat is printed as long as the app is still running. For tests, the script calls androidtestrunner, allowing test parameters to be passed to the test. For CI debugging, this would save quite a lot of hussle and frustration trying to run or debug a test app. One other benefit for this is enabling running Android tests from Qt Creator's testlib plugin without big changes to Qt Creator to support androidtestrunner explicitly. Because file(GENERATE) would fail if called twice for the same file, I use file(WRITE). This is used because at the time of calling the target executable finalizer, we don't know if the target is a test or not, so we rely on writing the script first as a normal target, then call it if the target is a test where it overrides the script. For this also, parameters passed to the runner or androidtestrunner can't handle generator expressions. [ChangeLog][CMake][Android] Add wrapper scripts to run Android apps and tests with ease from the host. Task-number: QTBUG-129889 Change-Id: I84e85ce2bbf6944c8aa20bdc2c2b6d7b956bc748 Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
2024-10-07 17:43:31 +03:00
)
# Opt out to skip the new way of running test finalizers, and instead use the old way for
# specific platforms.
# TODO: Remove once we confirm that the new way of running test finalizers for all platforms
# doesn't cause any issues.
if(NOT QT_INTERNAL_SKIP_TEST_FINALIZERS_V2)
# We don't run finalizers for all executables on all platforms, because there are still
# some unsolved issues there. One of them is trying to run finalizers for the
# qmlimportscanner executable would create a circular depenendecy trying to run
# qmlimportscanner on itself.
#
# For now, we only run finalizers for test-like executables on all platforms, and all
# android and wasm internal executables.
# For android and wasm all executables, to be behavior compatible with the old way of
# running finalizers.
if(ANDROID
OR WASM
OR arg_QT_TEST
OR arg_QT_MANUAL_TEST
OR arg_QT_BENCHMARK_TEST)
set(QT_INTERNAL_USE_POOR_MANS_SCOPE_FINALIZER TRUE)
_qt_internal_finalize_target_defer("${name}")
endif()
else()
if(ANDROID)
# This direct calls the finalizer, which in the v2 way is deferred.
_qt_internal_android_executable_finalizer(${name})
endif()
if(WASM)
# This defer calls the finalizer.
qt_internal_wasm_add_finalizers(${name})
endif()
endif()
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
if(arg_QT_APP
AND QT_FEATURE_debug_and_release
AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.19.0"
AND is_multi_config
)
set_property(TARGET "${name}"
PROPERTY EXCLUDE_FROM_ALL "$<NOT:$<CONFIG:${QT_MULTI_CONFIG_FIRST_CONFIG}>>")
endif()
if (arg_VERSION)
if(arg_VERSION MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+")
# nothing to do
elseif(arg_VERSION MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+")
set(arg_VERSION "${arg_VERSION}.0")
elseif(arg_VERSION MATCHES "[0-9]+\\.[0-9]+")
set(arg_VERSION "${arg_VERSION}.0.0")
elseif (arg_VERSION MATCHES "[0-9]+")
set(arg_VERSION "${arg_VERSION}.0.0.0")
else()
message(FATAL_ERROR "Invalid version format")
endif()
endif()
if(arg_DELAY_TARGET_INFO)
# Delay the setting of target info properties if requested. Needed for scope finalization
# of Qt apps.
set_target_properties("${name}" PROPERTIES
QT_DELAYED_TARGET_VERSION "${arg_VERSION}"
QT_DELAYED_TARGET_PRODUCT "${arg_TARGET_PRODUCT}"
QT_DELAYED_TARGET_DESCRIPTION "${arg_TARGET_DESCRIPTION}"
QT_DELAYED_TARGET_COMPANY "${arg_TARGET_COMPANY}"
QT_DELAYED_TARGET_COPYRIGHT "${arg_TARGET_COPYRIGHT}"
)
else()
if(NOT arg_TARGET_DESCRIPTION)
set(arg_TARGET_DESCRIPTION "Qt ${name}")
endif()
qt_set_target_info_properties(${name} ${ARGN}
TARGET_DESCRIPTION ${arg_TARGET_DESCRIPTION}
TARGET_VERSION ${arg_VERSION})
endif()
if (WIN32 AND NOT arg_DELAY_RC)
_qt_internal_generate_win32_rc_file(${name})
endif()
qt_set_common_target_properties(${name})
qt_internal_add_repo_local_defines(${name})
if(ANDROID)
# The above call to qt_set_common_target_properties() sets the symbol
# visibility to hidden, but for Android, we need main() to not be hidden
# because it has to be loadable at runtime using dlopen().
set_property(TARGET ${name} PROPERTY C_VISIBILITY_PRESET default)
set_property(TARGET ${name} PROPERTY CXX_VISIBILITY_PRESET default)
endif()
qt_autogen_tools_initial_setup(${name})
qt_internal_default_warnings_are_errors("${name}")
set(extra_libraries "")
if(arg_CORE_LIBRARY STREQUAL "Bootstrap")
list(APPEND extra_libraries ${QT_CMAKE_EXPORT_NAMESPACE}::Bootstrap)
elseif(NOT arg_CORE_LIBRARY STREQUAL "None")
list(APPEND extra_libraries ${QT_CMAKE_EXPORT_NAMESPACE}::Core)
endif()
set(private_includes
"${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}"
${arg_INCLUDE_DIRECTORIES}
)
if(arg_PUBLIC_LIBRARIES)
message(WARNING
"qt_internal_add_executable's PUBLIC_LIBRARIES option is deprecated, and will be "
"removed in a future Qt version. Use the LIBRARIES option instead.")
endif()
if(arg_NO_UNITY_BUILD)
set(arg_NO_UNITY_BUILD "NO_UNITY_BUILD")
else()
set(arg_NO_UNITY_BUILD "")
endif()
qt_internal_extend_target("${name}"
${arg_NO_UNITY_BUILD}
SOURCES ${arg_SOURCES}
NO_PCH_SOURCES ${arg_NO_PCH_SOURCES}
NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}
INCLUDE_DIRECTORIES ${private_includes}
DEFINES ${arg_DEFINES}
LIBRARIES
${arg_LIBRARIES}
${arg_PUBLIC_LIBRARIES}
Qt::PlatformCommonInternal
${extra_libraries}
DBUS_ADAPTOR_SOURCES ${arg_DBUS_ADAPTOR_SOURCES}
DBUS_ADAPTOR_FLAGS ${arg_DBUS_ADAPTOR_FLAGS}
DBUS_INTERFACE_SOURCES ${arg_DBUS_INTERFACE_SOURCES}
DBUS_INTERFACE_FLAGS ${arg_DBUS_INTERFACE_FLAGS}
COMPILE_OPTIONS ${arg_COMPILE_OPTIONS}
LINK_OPTIONS ${arg_LINK_OPTIONS}
MOC_OPTIONS ${arg_MOC_OPTIONS}
ENABLE_AUTOGEN_TOOLS ${arg_ENABLE_AUTOGEN_TOOLS}
DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS}
)
set_target_properties("${name}" PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}"
LIBRARY_OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}"
)
if(arg_GUI)
# Only override if GUI is set. Otherwise leave up to
# CMake defaults, which may be set by the user elsewhere.
set_target_properties("${name}" PROPERTIES
MACOSX_BUNDLE ON
WIN32_EXECUTABLE ON
)
endif()
if(NOT arg_EXCEPTIONS)
qt_internal_set_exceptions_flags("${name}" "DEFAULT")
else()
qt_internal_set_exceptions_flags("${name}" "${arg_EXCEPTIONS}")
endif()
# Check if target needs to be excluded from all target. Also affects qt_install.
# Set by qt_exclude_tool_directories_from_default_target.
set(exclude_from_all FALSE)
if(__qt_exclude_tool_directories)
foreach(absolute_dir ${__qt_exclude_tool_directories})
_qt_internal_path_is_prefix(absolute_dir "${CMAKE_CURRENT_SOURCE_DIR}"
in_current_source)
if(in_current_source)
set(exclude_from_all TRUE)
set_target_properties("${name}" PROPERTIES
EXCLUDE_FROM_ALL TRUE
_qt_internal_excluded_from_default_target TRUE
)
break()
endif()
endforeach()
endif()
if(NOT arg_NO_INSTALL)
set(additional_install_args "")
if(exclude_from_all)
list(APPEND additional_install_args EXCLUDE_FROM_ALL COMPONENT "ExcludedExecutables")
endif()
qt_get_cmake_configurations(cmake_configs)
foreach(cmake_config ${cmake_configs})
qt_get_install_target_default_args(
OUT_VAR install_targets_default_args
CMAKE_CONFIG "${cmake_config}"
ALL_CMAKE_CONFIGS ${cmake_configs}
RUNTIME "${arg_INSTALL_DIRECTORY}"
LIBRARY "${arg_INSTALL_DIRECTORY}"
BUNDLE "${arg_INSTALL_DIRECTORY}")
# Make installation optional for targets that are not built by default in this config
if(NOT exclude_from_all AND arg_QT_APP AND QT_FEATURE_debug_and_release
AND NOT (cmake_config STREQUAL QT_MULTI_CONFIG_FIRST_CONFIG))
set(install_optional_arg "OPTIONAL")
else()
unset(install_optional_arg)
endif()
qt_install(TARGETS "${name}"
${additional_install_args} # Needs to be before the DESTINATIONS.
${install_optional_arg}
CONFIGURATIONS ${cmake_config}
${install_targets_default_args})
endforeach()
if(NOT exclude_from_all AND arg_QT_APP AND QT_FEATURE_debug_and_release)
set(separate_debug_info_executable_arg "QT_EXECUTABLE")
else()
unset(separate_debug_info_executable_arg)
endif()
qt_internal_defer_separate_debug_info("${name}"
SEPARATE_DEBUG_INFO_ARGS
"${arg_INSTALL_DIRECTORY}"
${separate_debug_info_executable_arg}
ADDITIONAL_INSTALL_ARGS ${additional_install_args}
)
qt_internal_install_pdb_files(${name} "${arg_INSTALL_DIRECTORY}")
endif()
qt_add_list_file_finalizer(qt_internal_finalize_executable "${name}")
endfunction()
# Finalizer for all generic internal executables.
function(qt_internal_finalize_executable target)
qt_internal_finalize_executable_separate_debug_info("${target}")
endfunction()
# This function compiles the target at configure time the very first time and creates the custom
# ${target}_build that re-runs compilation at build time if necessary. The resulting executable is
# imported under the provided target name. This function should only be used to compile tiny
# executables with system dependencies only.
# One-value Arguments:
# CMAKELISTS_TEMPLATE
# The CMakeLists.txt templated that is used to configure the project
# for an executable. By default the predefined template from the Qt installation is used.
# INSTALL_DIRECTORY
# installation directory of the executable. Ignored if NO_INSTALL is set.
# OUTPUT_NAME
# the output name of an executable
# CONFIG
# the name of configuration that tool needs to be build with.
# Multi-value Arguments:
# PACKAGES
# list of system packages are required to successfully build the project.
# INCLUDES
# list of include directories are required to successfully build the project.
# DEFINES
# list of definitions are required to successfully build the project.
# COMPILE_OPTIONS
# list of compiler options are required to successfully build the project.
# LINK_OPTIONS
# list of linker options are required to successfully build the project.
# SOURCES
# list of project sources.
# CMAKE_FLAGS
# specify flags of the form -DVAR:TYPE=VALUE to be passed to the cmake command-line used to
# drive the test build.
# Options:
# WIN32
# reflects the corresponding add_executable argument.
# MACOSX_BUNDLE
# reflects the corresponding add_executable argument.
# NO_INSTALL
# avoids installing the tool.
function(qt_internal_add_configure_time_executable target)
set(one_value_args
CMAKELISTS_TEMPLATE
INSTALL_DIRECTORY
OUTPUT_NAME
CONFIG
)
set(multi_value_args
PACKAGES
INCLUDES
DEFINES
COMPILE_OPTIONS
LINK_OPTIONS
SOURCES
CMAKE_FLAGS
)
set(option_args WIN32 MACOSX_BUNDLE NO_INSTALL)
cmake_parse_arguments(PARSE_ARGV 1 arg
"${option_args}" "${one_value_args}" "${multi_value_args}")
set(target_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/configure_time_bins")
if(arg_CONFIG)
set(CMAKE_TRY_COMPILE_CONFIGURATION "${arg_CONFIG}")
string(TOUPPER "_${arg_CONFIG}" config_suffix)
endif()
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
if(is_multi_config AND CMAKE_TRY_COMPILE_CONFIGURATION)
set(configuration_path "${CMAKE_TRY_COMPILE_CONFIGURATION}/")
set(config_build_arg "--config" "${CMAKE_TRY_COMPILE_CONFIGURATION}")
endif()
set(configure_time_target "${target}")
if(arg_OUTPUT_NAME)
set(configure_time_target "${arg_OUTPUT_NAME}")
endif()
set(target_binary "${configure_time_target}${CMAKE_EXECUTABLE_SUFFIX}")
set(install_dir "${INSTALL_BINDIR}")
if(arg_INSTALL_DIRECTORY)
set(install_dir "${arg_INSTALL_DIRECTORY}")
endif()
CMake: Fix syncqt IMPORTED_LOCATION path for multi-config builds When building examples as ExternalProjects as part of a multi-config qtbase build, syncqt can not be located with the following error: CMake Error at Qt6CoreToolsAdditionalTargetInfo.cmake:10 (message): Unable to add configure time executable Qt6::syncqt qtbase/libexec/syncqt doesn't exist Call Stack (most recent call first): qtbase/lib/cmake/Qt6CoreTools/Qt6CoreToolsConfig.cmake:44 (include) qtbase/cmake/QtPublicDependencyHelpers.cmake:65 (find_package) qtbase/lib/cmake/Qt6Core/Qt6CoreDependencies.cmake:34 (_qt_internal_find_tool_dependencies) qtbase/lib/cmake/Qt6Core/Qt6CoreConfig.cmake:42 (include) qtbase/lib/cmake/Qt6/Qt6Config.cmake:165 (find_package) CMakeLists.txt:13 (find_package) The Qt6CoreToolsAdditionalTargetInfo.cmake file is used both for install(EXPORT) Config files as well as export(EXPORT) Config files, and in the latter case, the path that syncqt is looked up in is not correct because syncqt is not yet installed. In addition to checking whether syncqt exists in the install path, also check if it exists in the build dir. Ideally the additional path would be stored in a separate file that is not installed, but the current code infrastructure does not provide such a feature. Because we store a relative path instead of an absolute path, the build path does not leak, so the situation is bearable. Task-number: QTBUG-90820 Task-number: QTBUG-96232 Change-Id: I16ad5c280751e050bc9b039ebd38ec9a66a6554c Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
2024-03-05 14:21:25 +01:00
set(output_directory_relative "${install_dir}")
set(output_directory "${QT_BUILD_DIR}/${install_dir}")
CMake: Fix syncqt IMPORTED_LOCATION path for multi-config builds When building examples as ExternalProjects as part of a multi-config qtbase build, syncqt can not be located with the following error: CMake Error at Qt6CoreToolsAdditionalTargetInfo.cmake:10 (message): Unable to add configure time executable Qt6::syncqt qtbase/libexec/syncqt doesn't exist Call Stack (most recent call first): qtbase/lib/cmake/Qt6CoreTools/Qt6CoreToolsConfig.cmake:44 (include) qtbase/cmake/QtPublicDependencyHelpers.cmake:65 (find_package) qtbase/lib/cmake/Qt6Core/Qt6CoreDependencies.cmake:34 (_qt_internal_find_tool_dependencies) qtbase/lib/cmake/Qt6Core/Qt6CoreConfig.cmake:42 (include) qtbase/lib/cmake/Qt6/Qt6Config.cmake:165 (find_package) CMakeLists.txt:13 (find_package) The Qt6CoreToolsAdditionalTargetInfo.cmake file is used both for install(EXPORT) Config files as well as export(EXPORT) Config files, and in the latter case, the path that syncqt is looked up in is not correct because syncqt is not yet installed. In addition to checking whether syncqt exists in the install path, also check if it exists in the build dir. Ideally the additional path would be stored in a separate file that is not installed, but the current code infrastructure does not provide such a feature. Because we store a relative path instead of an absolute path, the build path does not leak, so the situation is bearable. Task-number: QTBUG-90820 Task-number: QTBUG-96232 Change-Id: I16ad5c280751e050bc9b039ebd38ec9a66a6554c Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
2024-03-05 14:21:25 +01:00
set(target_binary_path_relative
"${output_directory_relative}/${configuration_path}${target_binary}")
set(target_binary_path
"${output_directory}/${configuration_path}${target_binary}")
CMake: Fix syncqt IMPORTED_LOCATION path for multi-config builds When building examples as ExternalProjects as part of a multi-config qtbase build, syncqt can not be located with the following error: CMake Error at Qt6CoreToolsAdditionalTargetInfo.cmake:10 (message): Unable to add configure time executable Qt6::syncqt qtbase/libexec/syncqt doesn't exist Call Stack (most recent call first): qtbase/lib/cmake/Qt6CoreTools/Qt6CoreToolsConfig.cmake:44 (include) qtbase/cmake/QtPublicDependencyHelpers.cmake:65 (find_package) qtbase/lib/cmake/Qt6Core/Qt6CoreDependencies.cmake:34 (_qt_internal_find_tool_dependencies) qtbase/lib/cmake/Qt6Core/Qt6CoreConfig.cmake:42 (include) qtbase/lib/cmake/Qt6/Qt6Config.cmake:165 (find_package) CMakeLists.txt:13 (find_package) The Qt6CoreToolsAdditionalTargetInfo.cmake file is used both for install(EXPORT) Config files as well as export(EXPORT) Config files, and in the latter case, the path that syncqt is looked up in is not correct because syncqt is not yet installed. In addition to checking whether syncqt exists in the install path, also check if it exists in the build dir. Ideally the additional path would be stored in a separate file that is not installed, but the current code infrastructure does not provide such a feature. Because we store a relative path instead of an absolute path, the build path does not leak, so the situation is bearable. Task-number: QTBUG-90820 Task-number: QTBUG-96232 Change-Id: I16ad5c280751e050bc9b039ebd38ec9a66a6554c Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
2024-03-05 14:21:25 +01:00
get_filename_component(target_binary_path "${target_binary_path}" ABSOLUTE)
if(NOT DEFINED arg_SOURCES)
message(FATAL_ERROR "No SOURCES given to target: ${target}")
endif()
set(sources "${arg_SOURCES}")
# Timestamp file is required because CMake ignores 'add_custom_command' if we use only the
# binary file as the OUTPUT.
set(timestamp_file "${target_binary_dir}/${target_binary}_timestamp")
add_custom_command(OUTPUT "${target_binary_path}" "${timestamp_file}"
COMMAND
${CMAKE_COMMAND} --build "${target_binary_dir}" --clean-first ${config_build_arg}
COMMAND
${CMAKE_COMMAND} -E touch "${timestamp_file}"
DEPENDS
${sources}
COMMENT
"Compiling ${target}"
VERBATIM
)
add_custom_target(${target}_build ALL
DEPENDS
"${target_binary_path}"
"${timestamp_file}"
)
set(should_build_at_configure_time TRUE)
if(QT_INTERNAL_HAVE_CONFIGURE_TIME_${target} AND
EXISTS "${target_binary_path}" AND EXISTS "${timestamp_file}")
set(last_ts 0)
foreach(source IN LISTS sources)
file(TIMESTAMP "${source}" ts "%s")
if(${ts} GREATER ${last_ts})
set(last_ts ${ts})
endif()
endforeach()
file(TIMESTAMP "${target_binary_path}" ts "%s")
if(${ts} GREATER_EQUAL ${last_ts})
set(should_build_at_configure_time FALSE)
endif()
endif()
set(cmake_flags_arg "")
if(arg_CMAKE_FLAGS)
set(cmake_flags_arg CMAKE_FLAGS "${arg_CMAKE_FLAGS}")
endif()
qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages)
foreach(lang IN LISTS enabled_languages)
set(compiler_flags_var "CMAKE_${lang}_FLAGS")
list(APPEND cmake_flags_arg "-D${compiler_flags_var}:STRING=${${compiler_flags_var}}")
if(arg_CONFIG)
set(compiler_flags_var_config "${compiler_flags_var}${config_suffix}")
list(APPEND cmake_flags_arg
"-D${compiler_flags_var_config}:STRING=${${compiler_flags_var_config}}")
endif()
endforeach()
qt_internal_get_target_link_types_for_flag_manipulation(target_link_types)
foreach(linker_type IN LISTS target_link_types)
set(linker_flags_var "CMAKE_${linker_type}_LINKER_FLAGS")
list(APPEND cmake_flags_arg "-D${linker_flags_var}:STRING=${${linker_flags_var}}")
if(arg_CONFIG)
set(linker_flags_var_config "${linker_flags_var}${config_suffix}")
list(APPEND cmake_flags_arg
"-D${linker_flags_var_config}:STRING=${${linker_flags_var_config}}")
endif()
endforeach()
if(NOT "${QT_INTERNAL_CMAKE_FLAGS_CONFIGURE_TIME_TOOL_${target}}" STREQUAL "${cmake_flags_arg}")
set(should_build_at_configure_time TRUE)
endif()
if(should_build_at_configure_time)
foreach(arg IN LISTS multi_value_args)
string(TOLOWER "${arg}" template_arg_name)
set(${template_arg_name} "")
if(DEFINED arg_${arg})
set(${template_arg_name} "${arg_${arg}}")
endif()
endforeach()
foreach(arg IN LISTS option_args)
string(TOLOWER "${arg}" template_arg_name)
set(${template_arg_name} "")
if(arg_${arg})
set(${template_arg_name} "${arg}")
endif()
endforeach()
file(MAKE_DIRECTORY "${target_binary_dir}")
set(template "${QT_CMAKE_DIR}/QtConfigureTimeExecutableCMakeLists.txt.in")
if(DEFINED arg_CMAKELISTS_TEMPLATE)
set(template "${arg_CMAKELISTS_TEMPLATE}")
endif()
configure_file("${template}" "${target_binary_dir}/CMakeLists.txt" @ONLY)
if(EXISTS "${target_binary_dir}/CMakeCache.txt")
file(REMOVE "${target_binary_dir}/CMakeCache.txt")
endif()
try_compile(result
"${target_binary_dir}"
"${target_binary_dir}"
${target}
${cmake_flags_arg}
OUTPUT_VARIABLE try_compile_output
)
set(QT_INTERNAL_CMAKE_FLAGS_CONFIGURE_TIME_TOOL_${target}
"${cmake_flags_arg}" CACHE INTERNAL "")
file(WRITE "${timestamp_file}" "")
set(QT_INTERNAL_HAVE_CONFIGURE_TIME_${target} ${result} CACHE INTERNAL
"Indicates that the configure-time target ${target} was built")
if(NOT result)
message(FATAL_ERROR "Unable to build ${target}: ${try_compile_output}")
endif()
endif()
add_executable(${target} IMPORTED GLOBAL)
add_executable(${QT_CMAKE_EXPORT_NAMESPACE}::${target} ALIAS ${target})
set_target_properties(${target} PROPERTIES
_qt_internal_configure_time_target TRUE
CMake: Fix syncqt IMPORTED_LOCATION path for multi-config builds When building examples as ExternalProjects as part of a multi-config qtbase build, syncqt can not be located with the following error: CMake Error at Qt6CoreToolsAdditionalTargetInfo.cmake:10 (message): Unable to add configure time executable Qt6::syncqt qtbase/libexec/syncqt doesn't exist Call Stack (most recent call first): qtbase/lib/cmake/Qt6CoreTools/Qt6CoreToolsConfig.cmake:44 (include) qtbase/cmake/QtPublicDependencyHelpers.cmake:65 (find_package) qtbase/lib/cmake/Qt6Core/Qt6CoreDependencies.cmake:34 (_qt_internal_find_tool_dependencies) qtbase/lib/cmake/Qt6Core/Qt6CoreConfig.cmake:42 (include) qtbase/lib/cmake/Qt6/Qt6Config.cmake:165 (find_package) CMakeLists.txt:13 (find_package) The Qt6CoreToolsAdditionalTargetInfo.cmake file is used both for install(EXPORT) Config files as well as export(EXPORT) Config files, and in the latter case, the path that syncqt is looked up in is not correct because syncqt is not yet installed. In addition to checking whether syncqt exists in the install path, also check if it exists in the build dir. Ideally the additional path would be stored in a separate file that is not installed, but the current code infrastructure does not provide such a feature. Because we store a relative path instead of an absolute path, the build path does not leak, so the situation is bearable. Task-number: QTBUG-90820 Task-number: QTBUG-96232 Change-Id: I16ad5c280751e050bc9b039ebd38ec9a66a6554c Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
2024-03-05 14:21:25 +01:00
_qt_internal_configure_time_target_build_location "${target_binary_path_relative}"
IMPORTED_LOCATION "${target_binary_path}"
)
if(NOT arg_NO_INSTALL)
set_target_properties(${target} PROPERTIES
_qt_internal_configure_time_target_install_location
"${install_dir}/${target_binary}"
)
qt_path_join(target_install_dir ${QT_INSTALL_DIR} ${install_dir})
qt_install(PROGRAMS "${target_binary_path}" DESTINATION "${target_install_dir}")
endif()
endfunction()