diff --git a/cmake/QtBuildHelpers.cmake b/cmake/QtBuildHelpers.cmake index 8da84aa2f45..8ef788f8741 100644 --- a/cmake/QtBuildHelpers.cmake +++ b/cmake/QtBuildHelpers.cmake @@ -246,6 +246,7 @@ function(qt_internal_get_qt_build_private_files_to_install out_var) QtGenerateLibPri.cmake QtGenerateVersionScript.cmake QtModuleConfig.cmake.in + QtModuleConfigPrivate.cmake.in QtModuleDependencies.cmake.in QtModuleHeadersCheck.cmake QtModuleToolsConfig.cmake.in diff --git a/cmake/QtModuleConfig.cmake.in b/cmake/QtModuleConfig.cmake.in index 501e1780dc5..93185857162 100644 --- a/cmake/QtModuleConfig.cmake.in +++ b/cmake/QtModuleConfig.cmake.in @@ -29,7 +29,47 @@ if (NOT QT_NO_CREATE_TARGETS AND @INSTALL_CMAKE_NAMESPACE@@target@_FOUND) include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@AdditionalTargetInfo.cmake") include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@ExtraProperties.cmake" OPTIONAL) +endif() +# Find the private module counterpart. +if (@INSTALL_CMAKE_NAMESPACE@@target@_FOUND AND NOT @arg_NO_PRIVATE_MODULE@) + if(NOT @INSTALL_CMAKE_NAMESPACE@@target_private@_FOUND) + if("${_qt_cmake_dir}" STREQUAL "") + set(_qt_cmake_dir "${QT_TOOLCHAIN_RELOCATABLE_CMAKE_DIR}") + endif() + set(__qt_use_no_default_path_for_qt_packages "NO_DEFAULT_PATH") + if(QT_DISABLE_NO_DEFAULT_PATH_IN_QT_PACKAGES) + set(__qt_use_no_default_path_for_qt_packages "") + endif() + find_package(@INSTALL_CMAKE_NAMESPACE@@target_private@ "@PROJECT_VERSION@" EXACT + QUIET + CONFIG + PATHS + ${QT_BUILD_CMAKE_PREFIX_PATH} + "${CMAKE_CURRENT_LIST_DIR}/.." + "${_qt_cmake_dir}" + ${_qt_additional_packages_prefix_paths} + ${__qt_use_no_default_path_for_qt_packages} + ) + endif() + if(NOT @INSTALL_CMAKE_NAMESPACE@@target_private@_FOUND) + get_property(@INSTALL_CMAKE_NAMESPACE@@target_private@_warning_shown GLOBAL PROPERTY + @INSTALL_CMAKE_NAMESPACE@@target_private@_warning_shown + ) + if(NOT @INSTALL_CMAKE_NAMESPACE@@target_private@_warning_shown) + message(VERBOSE + "The private module package '@INSTALL_CMAKE_NAMESPACE@@target_private@' " + "could not be found. It possibly needs to be installed separately with your " + "package manager." + ) + set_property(GLOBAL PROPERTY + @INSTALL_CMAKE_NAMESPACE@@target_private@_warning_shown ON + ) + endif() + endif() +endif() + +if (NOT QT_NO_CREATE_TARGETS AND @INSTALL_CMAKE_NAMESPACE@@target@_FOUND) # DEPRECATED # Provide old style variables for includes, compile definitions, etc. # These variables are deprecated and only provided on a best-effort basis to facilitate porting. diff --git a/cmake/QtModuleConfigPrivate.cmake.in b/cmake/QtModuleConfigPrivate.cmake.in new file mode 100644 index 00000000000..94117e6f9d3 --- /dev/null +++ b/cmake/QtModuleConfigPrivate.cmake.in @@ -0,0 +1,51 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +@PACKAGE_INIT@ + +cmake_minimum_required(VERSION @min_new_policy_version@...@max_new_policy_version@) + +include(CMakeFindDependencyMacro) + +# Find required dependencies, if any. +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target_private@Dependencies.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target_private@Dependencies.cmake") + _qt_internal_suggest_dependency_debugging(@target_private@ + __qt_@target_private@_pkg ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE) +endif() + +# If *ConfigDependencies.cmake exists, the variable value will be defined there. +# Don't override it in that case. +if(NOT DEFINED "@INSTALL_CMAKE_NAMESPACE@@target_private@_FOUND") + set("@INSTALL_CMAKE_NAMESPACE@@target_private@_FOUND" TRUE) +endif() + +if(NOT QT_NO_CREATE_TARGETS AND @INSTALL_CMAKE_NAMESPACE@@target_private@_FOUND) + include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target_private@Targets.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target_private@AdditionalTargetInfo.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target_private@ExtraProperties.cmake" + OPTIONAL) +endif() + +if(TARGET @QT_CMAKE_EXPORT_NAMESPACE@::@target_private@) + if(NOT QT_NO_CREATE_VERSIONLESS_TARGETS) + if(CMAKE_VERSION VERSION_LESS 3.18 OR QT_USE_OLD_VERSION_LESS_TARGETS) + include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target_private@VersionlessTargets.cmake") + else() + include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target_private@VersionlessAliasTargets.cmake") + endif() + endif() +else() + set(@INSTALL_CMAKE_NAMESPACE@@target_private@_FOUND FALSE) + if(NOT DEFINED @INSTALL_CMAKE_NAMESPACE@@target_private@_NOT_FOUND_MESSAGE) + set(@INSTALL_CMAKE_NAMESPACE@@target_private@_NOT_FOUND_MESSAGE + "Target \"@QT_CMAKE_EXPORT_NAMESPACE@::@target_private@\" was not found.") + + if(QT_NO_CREATE_TARGETS) + string(APPEND @INSTALL_CMAKE_NAMESPACE@@target_private@_NOT_FOUND_MESSAGE + "Possibly due to QT_NO_CREATE_TARGETS being set to TRUE and thus " + "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target_private@Targets.cmake was not " + "included to define the target.") + endif() + endif() +endif() diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake index d44cf752127..30f199d8daf 100644 --- a/cmake/QtModuleHelpers.cmake +++ b/cmake/QtModuleHelpers.cmake @@ -691,6 +691,12 @@ function(qt_internal_add_module target) set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}") qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix}) qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix}) + if(NOT arg_NO_PRIVATE_MODULE) + set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target_private}") + qt_path_join(private_config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix}) + qt_path_join(private_config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix}) + endif() + unset(path_suffix) set(extra_cmake_files) set(extra_cmake_includes) @@ -781,10 +787,9 @@ set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)") qt_internal_get_min_new_policy_cmake_version(min_new_policy_version) qt_internal_get_max_new_policy_cmake_version(max_new_policy_version) - configure_package_config_file( - "${QT_CMAKE_DIR}/QtModuleConfig.cmake.in" - "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}Config.cmake" - INSTALL_DESTINATION "${config_install_dir}" + qt_internal_write_basic_module_package("${target}" "${target_private}" + CONFIG_BUILD_DIR ${config_build_dir} + CONFIG_INSTALL_DIR ${config_install_dir} ) if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/${INSTALL_CMAKE_NAMESPACE}${target}BuildInternals.cmake") @@ -794,38 +799,44 @@ set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)") list(APPEND extra_cmake_files "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}BuildInternals.cmake") endif() - write_basic_package_version_file( - "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigVersionImpl.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY AnyNewerVersion - ) - qt_internal_write_qt_package_version_file( - "${INSTALL_CMAKE_NAMESPACE}${target}" - "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigVersion.cmake" - ) qt_install(FILES - "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}Config.cmake" - "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigVersion.cmake" - "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigVersionImpl.cmake" ${extra_cmake_files} DESTINATION "${config_install_dir}" COMPONENT Devel ) - file(COPY ${extra_cmake_files} DESTINATION "${config_build_dir}") - set(exported_targets ${target}) - if(NOT ${arg_NO_PRIVATE_MODULE}) - list(APPEND exported_targets ${target_private}) + if(NOT arg_NO_PRIVATE_MODULE) + qt_internal_write_basic_module_package(${target} ${target_private} + PRIVATE + CONFIG_BUILD_DIR ${private_config_build_dir} + CONFIG_INSTALL_DIR ${private_config_install_dir} + ) endif() - set(export_name "${INSTALL_CMAKE_NAMESPACE}${target}Targets") - qt_install(TARGETS ${exported_targets} - EXPORT ${export_name} - RUNTIME DESTINATION ${INSTALL_BINDIR} - LIBRARY DESTINATION ${INSTALL_LIBDIR} - ARCHIVE DESTINATION ${INSTALL_LIBDIR} - FRAMEWORK DESTINATION ${INSTALL_LIBDIR} + file(COPY ${extra_cmake_files} DESTINATION "${config_build_dir}") + + set(targets_to_export ${target}) + if(NOT ${arg_NO_PRIVATE_MODULE}) + list(APPEND targets_to_export ${target_private}) + endif() + + _qt_internal_forward_function_args( + FORWARD_PREFIX arg + FORWARD_OUT_VAR export_module_args + FORWARD_OPTIONS NO_ADDITIONAL_TARGET_INFO ) + qt_internal_export_module(${target} + ${export_module_args} + CONFIG_BUILD_DIR ${config_build_dir} + CONFIG_INSTALL_DIR ${config_install_dir} + ) + if(NOT arg_NO_PRIVATE_MODULE) + qt_internal_export_module(${target_private} + ${export_module_args} + CONFIG_BUILD_DIR ${private_config_build_dir} + CONFIG_INSTALL_DIR ${private_config_install_dir} + ) + endif() if(BUILD_SHARED_LIBS) qt_apply_rpaths(TARGET "${target}" INSTALL_PATH "${INSTALL_LIBDIR}" RELATIVE_RPATH) @@ -839,29 +850,6 @@ set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)") QT_ANDROID_MODULE_INSTALL_DIR ${INSTALL_LIBDIR}) endif() - qt_install(EXPORT ${export_name} - NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE}:: - DESTINATION ${config_install_dir}) - - if(NOT arg_NO_ADDITIONAL_TARGET_INFO) - qt_internal_export_additional_targets_file( - TARGETS ${exported_targets} - EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target} - CONFIG_INSTALL_DIR "${config_install_dir}") - endif() - - qt_internal_export_modern_cmake_config_targets_file( - TARGETS ${exported_targets} - EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target} - CONFIG_BUILD_DIR "${config_build_dir}" - CONFIG_INSTALL_DIR "${config_install_dir}" - ) - - qt_internal_export_genex_properties(TARGETS ${target} - EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target} - CONFIG_INSTALL_DIR "${config_install_dir}" - ) - ### fixme: cmake is missing a built-in variable for this. We want to apply it only to modules and plugins # that belong to Qt. if(NOT arg_HEADER_MODULE) @@ -986,6 +974,104 @@ set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)") qt_add_list_file_finalizer(qt_finalize_module ${target} ${arg_INTERNAL_MODULE} ${arg_NO_PRIVATE_MODULE}) endfunction() +# Write and install the basic Qt6Foo and Qt6FooPrivate packages. +# +# If PRIVATE is specified, write Qt6FooPrivate. +# Otherwise write its public counterpart. +# +# Note that this function is supposed to be called from qt_internal_add_module, and depends on +# variables set in the scope of that function, e.g. target and target_private. +function(qt_internal_write_basic_module_package) + set(no_value_options + PRIVATE + ) + set(single_value_options + CONFIG_BUILD_DIR + CONFIG_INSTALL_DIR + ) + set(multi_value_options "") + cmake_parse_arguments(PARSE_ARGV 0 arg + "${no_value_options}" "${single_value_options}" "${multi_value_options}" + ) + + if(arg_PRIVATE) + set(package_name "${INSTALL_CMAKE_NAMESPACE}${target_private}") + set(module_config_input_file "QtModuleConfigPrivate.cmake.in") + else() + set(package_name "${INSTALL_CMAKE_NAMESPACE}${target}") + set(module_config_input_file "QtModuleConfig.cmake.in") + endif() + + configure_package_config_file( + "${QT_CMAKE_DIR}/${module_config_input_file}" + "${arg_CONFIG_BUILD_DIR}/${package_name}Config.cmake" + INSTALL_DESTINATION "${arg_CONFIG_INSTALL_DIR}" + ) + write_basic_package_version_file( + "${arg_CONFIG_BUILD_DIR}/${package_name}ConfigVersionImpl.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion + ) + qt_internal_write_qt_package_version_file( + "${package_name}" + "${arg_CONFIG_BUILD_DIR}/${package_name}ConfigVersion.cmake" + ) + qt_install(FILES + "${arg_CONFIG_BUILD_DIR}/${package_name}Config.cmake" + "${arg_CONFIG_BUILD_DIR}/${package_name}ConfigVersion.cmake" + "${arg_CONFIG_BUILD_DIR}/${package_name}ConfigVersionImpl.cmake" + DESTINATION "${arg_CONFIG_INSTALL_DIR}" + COMPONENT Devel + ) +endfunction() + +function(qt_internal_export_module target) + set(no_value_options + NO_ADDITIONAL_TARGET_INFO + ) + set(single_value_options + CONFIG_BUILD_DIR + CONFIG_INSTALL_DIR + ) + set(multi_value_options "") + cmake_parse_arguments(PARSE_ARGV 1 arg + "${no_value_options}" "${single_value_options}" "${multi_value_options}" + ) + _qt_internal_validate_all_args_are_parsed(arg) + + set(export_name "${INSTALL_CMAKE_NAMESPACE}${target}Targets") + qt_install(TARGETS ${target} + EXPORT ${export_name} + RUNTIME DESTINATION ${INSTALL_BINDIR} + LIBRARY DESTINATION ${INSTALL_LIBDIR} + ARCHIVE DESTINATION ${INSTALL_LIBDIR} + FRAMEWORK DESTINATION ${INSTALL_LIBDIR} + ) + + qt_install(EXPORT ${export_name} + NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE}:: + DESTINATION ${arg_CONFIG_INSTALL_DIR}) + + if(NOT arg_NO_ADDITIONAL_TARGET_INFO) + qt_internal_export_additional_targets_file( + TARGETS ${target} + EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target} + CONFIG_INSTALL_DIR "${arg_CONFIG_INSTALL_DIR}") + endif() + + qt_internal_export_modern_cmake_config_targets_file( + TARGETS ${target} + EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target} + CONFIG_BUILD_DIR "${arg_CONFIG_BUILD_DIR}" + CONFIG_INSTALL_DIR "${arg_CONFIG_INSTALL_DIR}" + ) + + qt_internal_export_genex_properties(TARGETS ${target} + EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target} + CONFIG_INSTALL_DIR "${arg_CONFIG_INSTALL_DIR}" + ) +endfunction() + function(qt_internal_apply_apple_privacy_manifest target) # Avoid "INTERFACE_LIBRARY targets may only have whitelisted properties" error on CMake < 3.17. get_target_property(target_type ${target} TYPE) diff --git a/cmake/QtPostProcessHelpers.cmake b/cmake/QtPostProcessHelpers.cmake index 6ecb0c492dc..974b588822d 100644 --- a/cmake/QtPostProcessHelpers.cmake +++ b/cmake/QtPostProcessHelpers.cmake @@ -143,6 +143,15 @@ function(qt_internal_remove_qt_dependency_duplicates out_deps deps) endfunction() function(qt_internal_create_module_depends_file target) + set(no_value_options "") + set(single_value_options "") + set(multi_value_options + EXTRA_PACKAGE_DEPENDENCIES + ) + cmake_parse_arguments(PARSE_ARGV 1 arg + "${no_value_options}" "${single_value_options}" "${multi_value_options}" + ) + get_target_property(target_type "${target}" TYPE) set(is_interface_lib FALSE) if(target_type STREQUAL "INTERFACE_LIBRARY") @@ -173,6 +182,9 @@ function(qt_internal_create_module_depends_file target) if(NOT extra_depends MATCHES "-NOTFOUND$") list(APPEND target_deps "${extra_depends}") endif() + if(DEFINED arg_EXTRA_PACKAGE_DEPENDENCIES) + list(APPEND target_deps "${arg_EXTRA_PACKAGE_DEPENDENCIES}") + endif() # Extra 3rd party targets who's packages should be considered dependencies. get_target_property(extra_third_party_deps "${target}" _qt_extra_third_party_dep_targets) @@ -467,6 +479,11 @@ function(qt_internal_create_depends_files) foreach (target ${repo_known_modules}) qt_internal_create_module_depends_file(${target}) + if(TARGET "${target}Private") + qt_internal_create_module_depends_file(${target}Private + EXTRA_PACKAGE_DEPENDENCIES "${INSTALL_CMAKE_NAMESPACE}${target};${PROJECT_VERSION}" + ) + endif() endforeach() foreach (target ${QT_KNOWN_PLUGINS})