diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index cb5b67362b0..78d934d2686 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -335,6 +335,7 @@ set(__public_cmake_helpers cmake/QtPublicAppleHelpers.cmake cmake/QtPublicCMakeHelpers.cmake cmake/QtPublicCMakeVersionHelpers.cmake + cmake/QtPublicExternalProjectHelpers.cmake cmake/QtPublicFinalizerHelpers.cmake cmake/QtPublicPluginHelpers.cmake cmake/QtPublicTargetHelpers.cmake diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 1dc576d27af..0b8b00015e0 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -560,6 +560,7 @@ endif() # Helpers that are available in public projects and while building Qt itself. include(QtPublicAppleHelpers) include(QtPublicCMakeHelpers) +include(QtPublicExternalProjectHelpers) include(QtPublicPluginHelpers) include(QtPublicTargetHelpers) include(QtPublicWalkLibsHelpers) diff --git a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake index 20783d8934b..2b7219745e3 100644 --- a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake +++ b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake @@ -1101,39 +1101,13 @@ function(qt_internal_add_example_external_project subdir) cmake_parse_arguments(PARSE_ARGV 1 arg "${options}" "${singleOpts}" "${multiOpts}") - # TODO: Fix example builds when using Conan / install prefixes are different for each repo. - if(QT_SUPERBUILD OR QtBase_BINARY_DIR) - # When doing a top-level build or when building qtbase, - # always use the Config file from the current build directory, even for prefix builds. - # We strive to allow building examples without installing Qt first, which means we can't - # use the install or staging Config files. - set(qt_prefixes "${QT_BUILD_DIR}") - set(qt_cmake_dir "${QT_CONFIG_BUILD_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}") - else() - # This is a per-repo build that isn't the qtbase repo, so we know that - # qtbase was found via find_package() and Qt6_DIR must be set - set(qt_cmake_dir "${${QT_CMAKE_EXPORT_NAMESPACE}_DIR}") + _qt_internal_get_build_vars_for_external_projects( + CMAKE_DIR_VAR qt_cmake_dir + PREFIXES_VAR qt_prefixes + ADDITIONAL_PACKAGES_PREFIXES_VAR qt_additional_packages_prefixes + ) - # In a prefix build of a non-qtbase repo, we want to pick up the installed Config files - # for all repos except the one that is currently built. For the repo that is currently - # built, we pick up the Config files from the current repo build dir instead. - # For non-prefix builds, there's only one prefix, the main build dir. - # Both are handled by this assignment. - set(qt_prefixes "${QT_BUILD_DIR}") - - # Appending to QT_ADDITIONAL_PACKAGES_PREFIX_PATH helps find Qt6 components in - # non-qtbase prefix builds because we use NO_DEFAULT_PATH in find_package calls. - # It also handles the cross-compiling scenario where we need to adjust both the root path - # and prefixes, with the prefixes containing lib/cmake. This leverages the infrastructure - # previously added for Conan. - list(APPEND QT_ADDITIONAL_PACKAGES_PREFIX_PATH ${qt_prefixes}) - - # In a prefix build, look up all repo Config files in the install prefix, - # except for the current repo, which will look in the build dir (handled above). - if(QT_WILL_INSTALL) - list(APPEND qt_prefixes "${QT6_INSTALL_PREFIX}") - endif() - endif() + list(APPEND QT_ADDITIONAL_PACKAGES_PREFIX_PATH "${qt_additional_packages_prefixes}") set(vars_to_pass_if_defined) set(var_defs) diff --git a/cmake/QtConfig.cmake.in b/cmake/QtConfig.cmake.in index 2e498284724..66c10f3a57c 100644 --- a/cmake/QtConfig.cmake.in +++ b/cmake/QtConfig.cmake.in @@ -41,6 +41,7 @@ endif() # Public helpers available to all Qt packages. include("${CMAKE_CURRENT_LIST_DIR}/QtFeature.cmake") include("${CMAKE_CURRENT_LIST_DIR}/QtPublicAppleHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicExternalProjectHelpers.cmake") include("${CMAKE_CURRENT_LIST_DIR}/QtPublicFinalizerHelpers.cmake") include("${CMAKE_CURRENT_LIST_DIR}/QtPublicPluginHelpers.cmake") include("${CMAKE_CURRENT_LIST_DIR}/QtPublicTargetHelpers.cmake") diff --git a/cmake/QtPublicExternalProjectHelpers.cmake b/cmake/QtPublicExternalProjectHelpers.cmake new file mode 100644 index 00000000000..88bcce53a57 --- /dev/null +++ b/cmake/QtPublicExternalProjectHelpers.cmake @@ -0,0 +1,72 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +include_guard() + +# Get CMake variables that are needed to build external projects such as examples or CMake test +# projects. +# +# CMAKE_DIR_VAR: Variable name to store the path to the Qt6 CMake config module. +# +# PREFIXES_VAR: Variable name to store the prefixes that can be passed as CMAKE_PREFIX_PATH. +# +# ADDITIONAL_PACKAGES_PREFIXES_VAR: Variable name to store the prefixes that can be appended to +# QT_ADDITIONAL_PACKAGES_PREFIX_PATH. +function(_qt_internal_get_build_vars_for_external_projects) + set(no_value_options "") + set(single_value_options + CMAKE_DIR_VAR + PREFIXES_VAR + ADDITIONAL_PACKAGES_PREFIXES_VAR + ) + set(multi_value_options "") + cmake_parse_arguments(PARSE_ARGV 0 arg + "${no_value_options}" "${single_value_options}" "${multi_value_options}" + ) + + # TODO: Fix example/test builds when using Conan / install prefixes are different for each repo. + if(QT_SUPERBUILD OR QtBase_BINARY_DIR) + # When doing a top-level build or when building qtbase, + # always use the Config file from the current build directory, even for prefix builds. + # We strive to allow building examples without installing Qt first, which means we can't + # use the install or staging Config files. + set(qt_prefixes "${QT_BUILD_DIR}") + set(qt_cmake_dir "${QT_CONFIG_BUILD_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}") + set(qt_additional_packages_prefixes "") + else() + # This is a per-repo build that isn't the qtbase repo, so we know that + # qtbase was found via find_package() and Qt6_DIR must be set + set(qt_cmake_dir "${${QT_CMAKE_EXPORT_NAMESPACE}_DIR}") + + # In a prefix build of a non-qtbase repo, we want to pick up the installed Config files + # for all repos except the one that is currently built. For the repo that is currently + # built, we pick up the Config files from the current repo build dir instead. + # For non-prefix builds, there's only one prefix, the main build dir. + # Both are handled by this assignment. + set(qt_prefixes "${QT_BUILD_DIR}") + + # Appending to QT_ADDITIONAL_PACKAGES_PREFIX_PATH helps find Qt6 components in + # non-qtbase prefix builds because we use NO_DEFAULT_PATH in find_package calls. + # It also handles the cross-compiling scenario where we need to adjust both the root path + # and prefixes, with the prefixes containing lib/cmake. This leverages the infrastructure + # previously added for Conan. + set(qt_additional_packages_prefixes "${qt_prefixes}") + + # In a prefix build, look up all repo Config files in the install prefix, + # except for the current repo, which will look in the build dir (handled above). + if(QT_WILL_INSTALL) + list(APPEND qt_prefixes "${QT6_INSTALL_PREFIX}") + endif() + endif() + + if(arg_CMAKE_DIR) + set("${arg_CMAKE_DIR}" "${qt_cmake_dir}" PARENT_SCOPE) + endif() + if(arg_PREFIXES_VAR) + set("${arg_PREFIXES_VAR}" "${qt_prefixes}" PARENT_SCOPE) + endif() + if(arg_ADDITIONAL_PACKAGES_PREFIXES_VAR) + set("${arg_ADDITIONAL_PACKAGES_PREFIXES_VAR}" "${qt_additional_packages_prefixes}" + PARENT_SCOPE) + endif() +endfunction() diff --git a/src/corelib/Qt6CTestMacros.cmake b/src/corelib/Qt6CTestMacros.cmake index fb2ee6d3d0f..11101f7fa6f 100644 --- a/src/corelib/Qt6CTestMacros.cmake +++ b/src/corelib/Qt6CTestMacros.cmake @@ -142,17 +142,18 @@ function(_qt_internal_get_cmake_test_configure_options out_var) ) endforeach() - set(prefixes "") - foreach(prefix_path IN LISTS CMAKE_PREFIX_PATH) - file(TO_CMAKE_PATH "${prefix_path}" prefix_path) - list(APPEND prefixes "${prefix_path}") - endforeach() + _qt_internal_get_build_vars_for_external_projects( + PREFIXES_VAR prefixes + ADDITIONAL_PACKAGES_PREFIXES_VAR additional_prefixes + ) + if(arg_OUT_PREFIX_PATH) set(${arg_OUT_PREFIX_PATH} "${prefixes}" PARENT_SCOPE) endif() string(REPLACE ";" "\;" prefixes "${prefixes}") list(APPEND option_list "-DCMAKE_PREFIX_PATH=${prefixes}") + list(APPEND option_list "-DQT_ADDITIONAL_PACKAGES_PREFIX_PATH=${additional_prefixes}") set(${out_var} "${option_list}" PARENT_SCOPE) endfunction()