diff options
Diffstat (limited to 'cmake/QtModuleHelpers.cmake')
-rw-r--r-- | cmake/QtModuleHelpers.cmake | 780 |
1 files changed, 556 insertions, 224 deletions
diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake index b345e1797c..ba03173073 100644 --- a/cmake/QtModuleHelpers.cmake +++ b/cmake/QtModuleHelpers.cmake @@ -1,3 +1,6 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + macro(qt_internal_get_internal_add_module_keywords option_args single_args multi_args) set(${option_args} STATIC @@ -12,9 +15,10 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi NO_CONFIG_HEADER_FILE NO_ADDITIONAL_TARGET_INFO NO_GENERATE_METATYPES - GENERATE_CPP_EXPORTS # TODO: Rename to NO_GENERATE_CPP_EXPORTS once migration is done - GENERATE_METATYPES # TODO: Remove once it is not used anymore - GENERATE_PRIVATE_CPP_EXPORTS + NO_HEADERSCLEAN_CHECK + GENERATE_CPP_EXPORTS # deprecated + NO_GENERATE_CPP_EXPORTS + NO_UNITY_BUILD ) set(${single_args} MODULE_INCLUDE_NAME @@ -24,20 +28,43 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi CONFIGURE_FILE_PATH CPP_EXPORT_HEADER_BASE_NAME EXTERNAL_HEADERS_DIR + PRIVATE_HEADER_FILTERS + QPA_HEADER_FILTERS + RHI_HEADER_FILTERS + SSG_HEADER_FILTERS + HEADER_SYNC_SOURCE_DIRECTORY ${__default_target_info_args} ) set(${multi_args} QMAKE_MODULE_CONFIG EXTRA_CMAKE_FILES EXTRA_CMAKE_INCLUDES - NO_PCH_SOURCES EXTERNAL_HEADERS + POLICIES ${__default_private_args} ${__default_public_args} ${__default_private_module_args} ) endmacro() +# The function helps to wrap module include paths with the header existence check. +function(qt_internal_append_include_directories_with_headers_check target list_to_append type) + string(TOLOWER "${type}" type) + string(JOIN "" has_headers_check + "$<BOOL:" + "$<TARGET_PROPERTY:" + "$<TARGET_NAME:${target}>," + "_qt_module_has_${type}_headers" + ">" + ">" + ) + foreach(directory IN LISTS ARGN) + list(APPEND ${list_to_append} + "$<${has_headers_check}:${directory}>") + endforeach() + set(${list_to_append} "${${list_to_append}}" PARENT_SCOPE) +endfunction() + # This is the main entry function for creating a Qt module, that typically # consists of a library, public header files, private header files and configurable # features. @@ -80,7 +107,28 @@ endmacro() # A module directory with non qt headers (like 3rdparty) to be installed. # Note this option overrides install headers used as PUBLIC_HEADER by cmake install(TARGET) # otherwise set by syncqt. - +# +# PRIVATE_HEADER_FILTERS +# The regular expressions that filter private header files out of target sources. +# The value must use the following format 'regex1|regex2|regex3'. +# +# QPA_HEADER_FILTERS +# The regular expressions that filter QPA header files out of target sources. +# The value must use the following format 'regex1|regex2|regex3'. +# +# RHI_HEADER_FILTERS +# The regular expressions that filter RHI header files out of target sources. +# The value must use the following format 'regex1|regex2|regex3'. +# +# SSG_HEADER_FILTERS +# The regular expressions that filter ssg header files out of target sources. +# The value must use the following format 'regex1|regex2|regex3'. +# +# HEADER_SYNC_SOURCE_DIRECTORY +# The source directory for header sync procedure. Header files outside this directory will be +# ignored by syncqt. The specifying this directory allows to skip the parsing of the whole +# CMAKE_CURRENT_SOURCE_DIR for the header files that needs to be synced and only parse the +# single subdirectory, that meanwhile can be outside the CMAKE_CURRENT_SOURCE_DIR tree. function(qt_internal_add_module target) qt_internal_get_internal_add_module_keywords( module_option_args @@ -88,14 +136,16 @@ function(qt_internal_add_module target) module_multi_args ) - qt_parse_all_arguments(arg "qt_internal_add_module" + cmake_parse_arguments(PARSE_ARGV 1 arg "${module_option_args}" "${module_single_args}" "${module_multi_args}" - ${ARGN} ) + _qt_internal_validate_all_args_are_parsed(arg) + set(is_internal_module FALSE) if(arg_INTERNAL_MODULE) + set(is_internal_module TRUE) set(arg_INTERNAL_MODULE "INTERNAL_MODULE") set(arg_NO_PRIVATE_MODULE TRUE) # Assume the interface name of the internal module should be the module name without the @@ -154,10 +204,31 @@ function(qt_internal_add_module target) set_target_properties(${target} PROPERTIES _qt_module_interface_name "${arg_MODULE_INTERFACE_NAME}" _qt_package_version "${PROJECT_VERSION}" + _qt_package_name "${INSTALL_CMAKE_NAMESPACE}${target}" + ) + set(export_properties + "_qt_module_interface_name" + "_qt_package_version" + "_qt_package_name" ) - set_property(TARGET ${target} - APPEND PROPERTY - EXPORT_PROPERTIES "_qt_module_interface_name;_qt_package_version") + if(NOT is_internal_module) + set_target_properties(${target} PROPERTIES + _qt_is_public_module TRUE + ) + list(APPEND export_properties + "_qt_is_public_module" + ) + if(NOT ${arg_NO_PRIVATE_MODULE}) + set_target_properties(${target} PROPERTIES + _qt_private_module_target_name "${target}Private" + ) + list(APPEND export_properties + "_qt_private_module_target_name" + ) + endif() + endif() + + set_property(TARGET ${target} APPEND PROPERTY EXPORT_PROPERTIES "${export_properties}") qt_internal_module_info(module "${target}") qt_internal_add_qt_repo_known_module("${target}") @@ -172,6 +243,13 @@ function(qt_internal_add_module target) set(module_config_header "qt${arg_CONFIG_MODULE_NAME}-config.h") set(module_config_private_header "qt${arg_CONFIG_MODULE_NAME}-config_p.h") + # qt<module>-config.h/-config_p.h header files are not marked as GENERATED automatically + # for old CMake versions. Set the property explicitly here. + set_source_files_properties("${module_config_header}" "${module_config_private_header}" + PROPERTIES + GENERATED TRUE + SKIP_AUTOGEN TRUE + ) # Module define needs to take into account the config module name. string(TOUPPER "${arg_CONFIG_MODULE_NAME}" module_define_infix) @@ -204,7 +282,7 @@ function(qt_internal_add_module target) qt_internal_get_framework_info(fw ${target}) endif() - if(NOT QT_FEATURE_no_extern_direct_access AND QT_FEATURE_reduce_relocations AND + if(NOT QT_FEATURE_no_direct_extern_access AND QT_FEATURE_reduce_relocations AND UNIX AND NOT is_interface_lib) # On x86 and x86-64 systems with ELF binaries (especially Linux), due to # a new optimization in GCC 5.x in combination with a recent version of @@ -243,10 +321,30 @@ function(qt_internal_add_module target) set_target_properties(${target_private} PROPERTIES _qt_config_module_name ${arg_CONFIG_MODULE_NAME}_private _qt_package_version "${PROJECT_VERSION}" + _qt_package_name "${INSTALL_CMAKE_NAMESPACE}${target}" + _qt_is_private_module TRUE + _qt_public_module_target_name "${target}" ) - set_property(TARGET "${target_private}" APPEND PROPERTY - EXPORT_PROPERTIES "_qt_config_module_name;_qt_package_version" + set(export_properties + "_qt_config_module_name" + "_qt_package_version" + "_qt_package_name" + "_qt_is_private_module" + "_qt_public_module_target_name" ) + set_property(TARGET "${target_private}" APPEND PROPERTY + EXPORT_PROPERTIES "${export_properties}") + endif() + + # FIXME: This workaround is needed because the deployment logic + # for iOS and WASM just copies/embeds the directly linked library, + # which will just be a versioned symlink to the actual library. + if((UIKIT OR WASM) AND BUILD_SHARED_LIBS) + set(version_args "") + else() + set(version_args + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR}) endif() if(NOT arg_HEADER_MODULE) @@ -254,9 +352,8 @@ function(qt_internal_add_module target) LIBRARY_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}" RUNTIME_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_BINDIR}" ARCHIVE_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}" - VERSION ${PROJECT_VERSION} - SOVERSION ${PROJECT_VERSION_MAJOR} - ) + ${version_args} + ) qt_set_target_info_properties(${target} ${ARGN}) qt_handle_multi_config_output_dirs("${target}") @@ -313,102 +410,90 @@ function(qt_internal_add_module target) else() set_property(TARGET ${target} APPEND PROPERTY EXPORT_PROPERTIES _qt_module_include_name) set_target_properties("${target}" PROPERTIES - _qt_module_include_name "${module_include_name}") - - # Use QT_BUILD_DIR for the syncqt call. - # So we either write the generated files into the qtbase non-prefix build root, or the - # module specific build root. - qt_ensure_sync_qt() - set(syncqt_full_command "${HOST_PERL}" -w "${QT_SYNCQT}" - -quiet - -check-includes - -module "${module_include_name}" - -version "${PROJECT_VERSION}" - -outdir "${QT_BUILD_DIR}" - -builddir "${PROJECT_BINARY_DIR}" - "${PROJECT_SOURCE_DIR}") - message(STATUS "Running syncqt for module: '${module_include_name}' ") - execute_process(COMMAND ${syncqt_full_command} RESULT_VARIABLE syncqt_ret) - if(NOT syncqt_ret EQUAL 0) - message(FATAL_ERROR "Failed to run syncqt, return code: ${syncqt_ret}") - endif() - - set_target_properties("${target}" PROPERTIES - _qt_module_has_headers ON) - - ### FIXME: Can we replace headers.pri? - qt_read_headers_pri("${module_build_interface_include_dir}" "module_headers") + _qt_module_include_name "${module_include_name}" + _qt_module_has_headers ON + ) - if(arg_EXTERNAL_HEADERS) - set(module_headers_public ${arg_EXTERNAL_HEADERS}) + set(sync_source_directory "${CMAKE_CURRENT_SOURCE_DIR}") + if(arg_HEADER_SYNC_SOURCE_DIRECTORY) + set(sync_source_directory "${arg_HEADER_SYNC_SOURCE_DIRECTORY}") endif() - - set_property(TARGET ${target} APPEND PROPERTY - _qt_module_timestamp_dependencies "${module_headers_public}") - + set_target_properties(${target} PROPERTIES + _qt_sync_source_directory "${sync_source_directory}") # We should not generate export headers if module is defined as pure STATIC. # Static libraries don't need to export their symbols, and corner cases when sources are # also used in shared libraries, should be handled manually. - if(arg_GENERATE_CPP_EXPORTS AND NOT arg_STATIC) + if((NOT arg_NO_GENERATE_CPP_EXPORTS OR arg_GENERATE_CPP_EXPORTS) AND NOT arg_STATIC + AND NOT arg_HEADER_MODULE) if(arg_CPP_EXPORT_HEADER_BASE_NAME) set(cpp_export_header_base_name "CPP_EXPORT_HEADER_BASE_NAME;${arg_CPP_EXPORT_HEADER_BASE_NAME}" ) endif() - if(arg_GENERATE_PRIVATE_CPP_EXPORTS) - set(generate_private_cpp_export "GENERATE_PRIVATE_CPP_EXPORTS") - endif() qt_internal_generate_cpp_global_exports(${target} ${module_define_infix} "${cpp_export_header_base_name}" - "${generate_private_cpp_export}" ) endif() set(module_depends_header "${module_build_interface_include_dir}/${module_include_name}Depends") - if(is_framework) - if(NOT is_interface_lib) - set(public_headers_to_copy "${module_headers_public}" "${module_depends_header}") - qt_copy_framework_headers(${target} PUBLIC "${public_headers_to_copy}") - qt_copy_framework_headers(${target} PRIVATE "${module_headers_private}") - endif() - else() - set_property(TARGET ${target} APPEND PROPERTY PUBLIC_HEADER "${module_headers_public}") - set_property(TARGET ${target} APPEND PROPERTY PUBLIC_HEADER ${module_depends_header}) - set_property(TARGET ${target} APPEND PROPERTY PRIVATE_HEADER "${module_headers_private}") - endif() - if (NOT ${arg_HEADER_MODULE}) + set_source_files_properties("${module_depends_header}" PROPERTIES GENERATED TRUE) + set_target_properties(${target} PROPERTIES _qt_module_depends_header + "${module_depends_header}") + if(NOT ${arg_HEADER_MODULE}) + set(module_header "${module_build_interface_include_dir}/${module_include_name}") set_property(TARGET "${target}" PROPERTY MODULE_HEADER - "${module_build_interface_include_dir}/${module_include_name}") + "${module_header}") endif() - if(module_headers_qpa) - if(is_framework) - qt_copy_framework_headers(${target} QPA "${module_headers_qpa}") - else() - qt_install( - FILES ${module_headers_qpa} - DESTINATION "${module_install_interface_qpa_include_dir}") - endif() + set(qpa_filter_regex "") + if(arg_QPA_HEADER_FILTERS) + set(qpa_filter_regex "${arg_QPA_HEADER_FILTERS}") endif() + set_target_properties(${target} + PROPERTIES _qt_module_qpa_headers_filter_regex "${qpa_filter_regex}") + + set(rhi_filter_regex "") + if(arg_RHI_HEADER_FILTERS) + set(rhi_filter_regex "${arg_RHI_HEADER_FILTERS}") + endif() + set_target_properties(${target} + PROPERTIES _qt_module_rhi_headers_filter_regex "${rhi_filter_regex}") + + set(ssg_filter_regex "") + if(arg_SSG_HEADER_FILTERS) + set(ssg_filter_regex "${arg_SSG_HEADER_FILTERS}") + endif() + set_target_properties(${target} + PROPERTIES _qt_module_ssg_headers_filter_regex "${ssg_filter_regex}") + + set(private_filter_regex ".+_p(ch)?\\.h") + if(arg_PRIVATE_HEADER_FILTERS) + set(private_filter_regex "${private_filter_regex}|${arg_PRIVATE_HEADER_FILTERS}") + endif() + set_target_properties(${target} + PROPERTIES _qt_module_private_headers_filter_regex "${private_filter_regex}") + + # If EXTERNAL_HEADERS_DIR is set we install the specified directory and keep the structure + # without taking into the account the CMake source tree and syncqt outputs. + if(arg_EXTERNAL_HEADERS_DIR) + set_property(TARGET ${target} + PROPERTY _qt_external_headers_dir "${arg_EXTERNAL_HEADERS_DIR}") + qt_install(DIRECTORY "${arg_EXTERNAL_HEADERS_DIR}/" + DESTINATION "${module_install_interface_include_dir}" + ) + endif() + endif() + + if(arg_NO_HEADERSCLEAN_CHECK OR arg_NO_MODULE_HEADERS OR arg_NO_SYNC_QT + OR NOT INPUT_headersclean) + set_target_properties("${target}" PROPERTIES _qt_no_headersclean_check ON) endif() if(NOT arg_HEADER_MODULE) # Plugin types associated to a module if(NOT "x${arg_PLUGIN_TYPES}" STREQUAL "x") - # Reset the variable containing the list of plugins for the given plugin type - foreach(plugin_type ${arg_PLUGIN_TYPES}) - qt_get_sanitized_plugin_type("${plugin_type}" plugin_type) - set_property(TARGET "${target}" APPEND PROPERTY MODULE_PLUGIN_TYPES "${plugin_type}") - qt_internal_add_qt_repo_known_plugin_types("${plugin_type}") - endforeach() - - # Save the non-sanitized plugin type values for qmake consumption via .pri files. - set_property(TARGET "${target}" - PROPERTY QMAKE_MODULE_PLUGIN_TYPES "${arg_PLUGIN_TYPES}") - - # Export the plugin types. - set_property(TARGET ${target} APPEND PROPERTY EXPORT_PROPERTIES MODULE_PLUGIN_TYPES) + qt_internal_add_plugin_types("${target}" "${arg_PLUGIN_TYPES}") endif() endif() @@ -440,15 +525,15 @@ function(qt_internal_add_module target) # Make sure to create such paths for both the the BUILD_INTERFACE and the INSTALL_INTERFACE. # # Only add syncqt headers if they exist. - # This handles cases like QmlDevToolsPrivate which do not have their own headers, but borrow them - # from another module. + # This handles cases like QmlDevToolsPrivate which do not have their own headers, but borrow + # them from another module. if(NOT arg_NO_SYNC_QT AND NOT arg_NO_MODULE_HEADERS) # Don't include private headers unless they exist, aka syncqt created them. - if(module_headers_private) - list(APPEND private_includes - "$<BUILD_INTERFACE:${module_build_interface_versioned_include_dir}>" - "$<BUILD_INTERFACE:${module_build_interface_versioned_inner_include_dir}>") - endif() + qt_internal_append_include_directories_with_headers_check(${target} + private_includes PRIVATE + "$<BUILD_INTERFACE:${module_build_interface_versioned_include_dir}>" + "$<BUILD_INTERFACE:${module_build_interface_versioned_inner_include_dir}>" + ) list(APPEND public_includes # For the syncqt headers @@ -493,26 +578,12 @@ function(qt_internal_add_module target) endif() list(APPEND ${public_headers_list} ${arg_PUBLIC_INCLUDE_DIRECTORIES}) - set(header_module) - if(arg_HEADER_MODULE) - set(header_module "HEADER_MODULE") - - # Provide a *_timestamp target that can be used to trigger the build of custom_commands. - set(timestamp_file "${CMAKE_CURRENT_BINARY_DIR}/timestamp") - add_custom_command(OUTPUT "${timestamp_file}" - COMMAND ${CMAKE_COMMAND} -E touch "${timestamp_file}" - DEPENDS "$<TARGET_PROPERTY:${target},_qt_module_timestamp_dependencies>" - VERBATIM) - add_custom_target(${target}_timestamp ALL DEPENDS "${timestamp_file}") - endif() - set(defines_for_extend_target "") if(NOT arg_HEADER_MODULE) list(APPEND defines_for_extend_target QT_NO_CAST_TO_ASCII QT_ASCII_CAST_WARNINGS QT_MOC_COMPAT #we don't need warnings from calling moc code in our generated code - QT_USE_QSTRINGBUILDER QT_DEPRECATED_WARNINGS QT_BUILDING_QT QT_BUILD_${module_define_infix}_LIB ### FIXME: use QT_BUILD_ADDON for Add-ons or remove if we don't have add-ons anymore @@ -523,11 +594,27 @@ function(qt_internal_add_module target) qt_internal_add_repo_local_defines("${target}") + if(arg_NO_UNITY_BUILD) + set(arg_NO_UNITY_BUILD "NO_UNITY_BUILD") + else() + set(arg_NO_UNITY_BUILD "") + endif() + + if(NOT arg_EXTERNAL_HEADERS) + set(arg_EXTERNAL_HEADERS "") + endif() + qt_internal_extend_target("${target}" - ${header_module} - SOURCES ${arg_SOURCES} + ${arg_NO_UNITY_BUILD} + SOURCES + ${arg_SOURCES} + ${arg_EXTERNAL_HEADERS} + NO_UNITY_BUILD_SOURCES + ${arg_NO_UNITY_BUILD_SOURCES} INCLUDE_DIRECTORIES ${private_includes} + SYSTEM_INCLUDE_DIRECTORIES + ${arg_SYSTEM_INCLUDE_DIRECTORIES} PUBLIC_INCLUDE_DIRECTORIES ${public_includes} PUBLIC_DEFINES @@ -580,39 +667,13 @@ function(qt_internal_add_module target) include(${configureFile}) qt_feature_module_end("${target}") - set_property(TARGET "${target}" APPEND PROPERTY - PUBLIC_HEADER "${CMAKE_CURRENT_BINARY_DIR}/${module_config_header}" - ) - set_property(TARGET "${target}" APPEND PROPERTY - PRIVATE_HEADER "${CMAKE_CURRENT_BINARY_DIR}/${module_config_private_header}" + qt_internal_extend_target("${target}" + SOURCES + "${CMAKE_CURRENT_BINARY_DIR}/${module_config_header}" + "${CMAKE_CURRENT_BINARY_DIR}/${module_config_private_header}" ) endif() - if(NOT arg_HEADER_MODULE) - if(DEFINED module_headers_private) - qt_internal_add_linker_version_script("${target}" PRIVATE_HEADERS ${module_headers_private} ${module_headers_qpa}) - else() - qt_internal_add_linker_version_script("${target}") - endif() - endif() - - # Handle injections. Aka create forwarding headers for certain headers that have been - # automatically generated in the build dir (for example qconfig.h, qtcore-config.h, - # qvulkanfunctions.h, etc) - # module_headers_injections come from the qt_read_headers_pri() call. - # extra_library_injections come from the qt_feature_module_end() call. - set(final_injections "") - if(module_headers_injections) - string(APPEND final_injections "${module_headers_injections} ") - endif() - if(extra_library_injections) - string(APPEND final_injections "${extra_library_injections} ") - endif() - - if(final_injections) - qt_install_injections(${target} "${QT_BUILD_DIR}" "${QT_INSTALL_DIR}" ${final_injections}) - endif() - # Handle creation of cmake files for consumers of find_package(). set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}") qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix}) @@ -624,8 +685,21 @@ function(qt_internal_add_module target) list(APPEND extra_cmake_files "${CMAKE_CURRENT_LIST_DIR}/${INSTALL_CMAKE_NAMESPACE}${target}Macros.cmake") list(APPEND extra_cmake_includes "${INSTALL_CMAKE_NAMESPACE}${target}Macros.cmake") endif() + if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigExtras.cmake.in") if(target STREQUAL Core) + if(NOT "${QT_NAMESPACE}" STREQUAL "") + string(MAKE_C_IDENTIFIER "${QT_NAMESPACE}" qt_namespace_sanity) + if(NOT "${QT_NAMESPACE}" STREQUAL "${qt_namespace_sanity}") + message(FATAL_ERROR "QT_NAMESPACE is not a valid C++ identifier: " + "${QT_NAMESPACE}.") + endif() + string(JOIN "" qtcore_namespace_definition + "set_property(TARGET \${__qt_core_target} " + "APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS QT_NAMESPACE=${QT_NAMESPACE})" + ) + endif() + set(extra_cmake_code "") # Add some variables for compatibility with Qt5 config files. if(QT_FEATURE_reduce_exports) @@ -637,6 +711,11 @@ set(QT_VISIBILITY_AVAILABLE TRUE)") set(QT_LIBINFIX \"${QT_LIBINFIX}\")") endif() + # Store whether find_package(Qt6Foo) should succeed if Qt6FooTools is missing. + if(QT_ALLOW_MISSING_TOOLS_PACKAGES) + string(APPEND qtcore_extra_cmake_code " +set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)") + endif() endif() configure_file("${CMAKE_CURRENT_LIST_DIR}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigExtras.cmake.in" @@ -650,29 +729,40 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")") get_filename_component(basename ${cmake_file} NAME) file(COPY ${cmake_file} DESTINATION ${config_build_dir}) list(APPEND extra_cmake_files "${config_build_dir}/${basename}") + + # Make sure touched extra cmake files cause a reconfigure, so they get re-copied. + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${cmake_file}") endforeach() list(APPEND extra_cmake_includes ${arg_EXTRA_CMAKE_INCLUDES}) set(extra_cmake_code "") - # Generate metatypes - if(${arg_GENERATE_METATYPES}) - # No mention of NO_GENERATE_METATYPES. You should not use it. - message(WARNING "GENERATE_METATYPES is on by default for Qt modules. Please remove the manual specification.") + if(arg_POLICIES) + set(policies "") + foreach(policy IN LISTS arg_POLICIES) + list(APPEND policies "set(QT_KNOWN_POLICY_${policy} TRUE)") + + # When building Qt, tests and examples might expect a policy to be known, but they + # won't be known depending on which scope or when a find_package(Module) with the + # respective policy is called. Check the global list of known policies to accommodate + # that. + set_property(GLOBAL APPEND PROPERTY _qt_global_known_policies "${policy}") + endforeach() + list(JOIN policies "\n" policies_str) + string(APPEND extra_cmake_code "${policies_str}\n") endif() - if (NOT ${arg_NO_GENERATE_METATYPES}) - if (NOT target_type STREQUAL "INTERFACE_LIBRARY") - set(args "") - if(QT_WILL_INSTALL) - set(metatypes_install_dir "${INSTALL_LIBDIR}/metatypes") - list(APPEND args - __QT_INTERNAL_INSTALL __QT_INTERNAL_INSTALL_DIR "${metatypes_install_dir}") - endif() - qt6_extract_metatypes(${target} ${args}) - elseif(${arg_GENERATE_METATYPES}) - message(FATAL_ERROR "Meta types generation does not work on interface libraries") + + # Generate metatypes + if (NOT ${arg_NO_GENERATE_METATYPES} AND NOT target_type STREQUAL "INTERFACE_LIBRARY") + set(args "") + if(QT_WILL_INSTALL) + set(metatypes_install_dir "${INSTALL_ARCHDATADIR}/metatypes") + list(APPEND args + __QT_INTERNAL_INSTALL __QT_INTERNAL_INSTALL_DIR "${metatypes_install_dir}") endif() + qt6_extract_metatypes(${target} ${args}) endif() + 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( @@ -712,14 +802,6 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")") list(APPEND exported_targets ${target_private}) endif() set(export_name "${INSTALL_CMAKE_NAMESPACE}${target}Targets") - if(arg_EXTERNAL_HEADERS_DIR) - qt_install(DIRECTORY "${arg_EXTERNAL_HEADERS_DIR}/" - DESTINATION "${module_install_interface_include_dir}" - ) - unset(public_header_destination) - else() - set(public_header_destination PUBLIC_HEADER DESTINATION "${module_install_interface_include_dir}") - endif() qt_install(TARGETS ${exported_targets} EXPORT ${export_name} @@ -727,9 +809,7 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")") LIBRARY DESTINATION ${INSTALL_LIBDIR} ARCHIVE DESTINATION ${INSTALL_LIBDIR} FRAMEWORK DESTINATION ${INSTALL_LIBDIR} - PRIVATE_HEADER DESTINATION "${module_install_interface_private_include_dir}" - ${public_header_destination} - ) + ) if(BUILD_SHARED_LIBS) qt_apply_rpaths(TARGET "${target}" INSTALL_PATH "${INSTALL_LIBDIR}" RELATIVE_RPATH) @@ -757,7 +837,14 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")") qt_internal_export_modern_cmake_config_targets_file( TARGETS ${exported_targets} EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target} - CONFIG_INSTALL_DIR "${config_install_dir}") + 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. @@ -769,39 +856,36 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")") # Handle cases like QmlDevToolsPrivate which do not have their own headers, but rather borrow them # from another module. - if(NOT arg_NO_SYNC_QT) + if(NOT arg_NO_SYNC_QT AND NOT arg_NO_MODULE_HEADERS) list(APPEND interface_includes "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>") - # syncqt.pl does not create a private header directory like 'include/6.0/QtFoo' unless + # syncqt does not create a private header directory like 'include/6.0/QtFoo' unless # the module has foo_p.h header files. For QtZlib, there are no such private headers, so we # need to make sure not to add such include paths unless the directory exists, otherwise # consumers of the module will fail at CMake generation time stating that # INTERFACE_INCLUDE_DIRECTORIES contains a non-existent path. - if(NOT arg_NO_MODULE_HEADERS - AND EXISTS "${module_build_interface_versioned_inner_include_dir}") - list(APPEND interface_includes - "$<BUILD_INTERFACE:${module_build_interface_versioned_include_dir}>" - "$<BUILD_INTERFACE:${module_build_interface_versioned_inner_include_dir}>") - - if(is_framework) - set(fw_install_private_header_dir "${INSTALL_LIBDIR}/${fw_private_header_dir}") - set(fw_install_private_module_header_dir "${INSTALL_LIBDIR}/${fw_private_module_header_dir}") - list(APPEND interface_includes - "$<INSTALL_INTERFACE:${fw_install_private_header_dir}>" - "$<INSTALL_INTERFACE:${fw_install_private_module_header_dir}>") - else() - list(APPEND interface_includes - "$<INSTALL_INTERFACE:${module_install_interface_versioned_include_dir}>" - "$<INSTALL_INTERFACE:${module_install_interface_versioned_inner_include_dir}>") - endif() - endif() - endif() + qt_internal_append_include_directories_with_headers_check(${target} + interface_includes PRIVATE + "$<BUILD_INTERFACE:${module_build_interface_versioned_include_dir}>" + "$<BUILD_INTERFACE:${module_build_interface_versioned_inner_include_dir}>" + ) - if(QT_FEATURE_headersclean AND NOT arg_NO_MODULE_HEADERS) - qt_internal_add_headers_clean_target( - ${target} - "${module_include_name}" - "${module_headers_clean}") + if(is_framework) + set(fw_install_private_header_dir "${INSTALL_LIBDIR}/${fw_private_header_dir}") + set(fw_install_private_module_header_dir + "${INSTALL_LIBDIR}/${fw_private_module_header_dir}") + qt_internal_append_include_directories_with_headers_check(${target} + interface_includes PRIVATE + "$<INSTALL_INTERFACE:${fw_install_private_header_dir}>" + "$<INSTALL_INTERFACE:${fw_install_private_module_header_dir}>" + ) + else() + qt_internal_append_include_directories_with_headers_check(${target} + interface_includes PRIVATE + "$<INSTALL_INTERFACE:${module_install_interface_versioned_include_dir}>" + "$<INSTALL_INTERFACE:${module_install_interface_versioned_inner_include_dir}>" + ) + endif() endif() if(arg_INTERNAL_MODULE) @@ -829,14 +913,49 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")") endif() qt_describe_module(${target}) - qt_add_list_file_finalizer(qt_finalize_module ${target} ${arg_INTERNAL_MODULE} ${arg_NO_PRIVATE_MODULE} ${header_module}) + qt_add_list_file_finalizer(qt_finalize_module ${target} ${arg_INTERNAL_MODULE} ${arg_NO_PRIVATE_MODULE}) +endfunction() + +function(qt_internal_apply_apple_privacy_manifest target) + if(APPLE) + # Privacy manifest + get_target_property(is_framework ${target} FRAMEWORK) + if(is_framework) + get_target_property(privacy_manifest ${target} _qt_privacy_manifest) + if(NOT privacy_manifest) + set(privacy_manifest + "${__qt_internal_cmake_apple_support_files_path}/PrivacyInfo.xcprivacy") + endif() + target_sources("${target}" PRIVATE "${privacy_manifest}") + set_property(TARGET "${target}" APPEND PROPERTY RESOURCE "${privacy_manifest}") + endif() + endif() endfunction() function(qt_finalize_module target) + qt_internal_collect_module_headers(module_headers ${target}) + + # qt_internal_install_module_headers needs to be called before + # qt_finalize_framework_headers_copy, because the last uses the QT_COPIED_FRAMEWORK_HEADERS + # property which supposed to be updated inside every qt_internal_install_module_headers + # call. + qt_internal_add_headersclean_target(${target} "${module_headers_public}") + qt_internal_target_sync_headers(${target} "${module_headers_all}" + "${module_headers_generated}") + get_target_property(module_depends_header ${target} _qt_module_depends_header) + qt_internal_install_module_headers(${target} + PUBLIC ${module_headers_public} "${module_depends_header}" + PRIVATE ${module_headers_private} + QPA ${module_headers_qpa} + RHI ${module_headers_rhi} + SSG ${module_headers_ssg} + ) + qt_finalize_framework_headers_copy(${target}) qt_generate_prl_file(${target} "${INSTALL_LIBDIR}") qt_generate_module_pri_file("${target}" ${ARGN}) qt_internal_generate_pkg_config_file(${target}) + qt_internal_apply_apple_privacy_manifest(${target}) endfunction() # Get a set of Qt module related values based on the target. @@ -863,6 +982,8 @@ endfunction() # * foo_versioned_inner_include_dir with the value "QtCore/6.2.0/QtCore" # * foo_private_include_dir with the value "QtCore/6.2.0/QtCore/private" # * foo_qpa_include_dir with the value "QtCore/6.2.0/QtCore/qpa" +# * foo_rhi_include_dir with the value "QtCore/6.2.0/QtCore/rhi" +# * foo_ssg_include_dir with the value "QtQuick3D/6.2.0/QtQuick3D/ssg" # * foo_interface_name the interface name of the module stored in _qt_module_interface_name # property, e.g. Core. # @@ -885,6 +1006,12 @@ endfunction() # * foo_<build|install>_qpa_include_dir with # qtbase_build_dir/include/QtCore/6.2.0/QtCore/qpa for build interface and # include/QtCore/6.2.0/QtCore/qpa for install interface. +# * foo_<build|install>_rhi_include_dir with +# qtbase_build_dir/include/QtCore/6.2.0/QtCore/rhi for build interface and +# include/QtCore/6.2.0/QtCore/rhi for install interface. +# * foo_<build|install>_ssg_include_dir with +# qtbase_build_dir/include/<module>/x.y.z/<module>/ssg for build interface and +# include/<module>/x.y.z/<module>/ssg for install interface. # The following values are set by the function and might be useful in caller's scope: # * repo_install_interface_include_dir contains path to the top-level repository include directory, # e.g. qtbase_build_dir/include @@ -919,6 +1046,10 @@ the different base name for the module info variables.") "${${result}_versioned_inner_include_dir}/private") set("${result}_qpa_include_dir" "${${result}_versioned_inner_include_dir}/qpa") + set("${result}_rhi_include_dir" + "${${result}_versioned_inner_include_dir}/rhi") + set("${result}_ssg_include_dir" + "${${result}_versioned_inner_include_dir}/ssg") # Module build interface directories set(repo_build_interface_include_dir "${QT_BUILD_DIR}/include") @@ -932,6 +1063,10 @@ the different base name for the module info variables.") "${repo_build_interface_include_dir}/${${result}_private_include_dir}") set("${result}_build_interface_qpa_include_dir" "${repo_build_interface_include_dir}/${${result}_qpa_include_dir}") + set("${result}_build_interface_rhi_include_dir" + "${repo_build_interface_include_dir}/${${result}_rhi_include_dir}") + set("${result}_build_interface_ssg_include_dir" + "${repo_build_interface_include_dir}/${${result}_ssg_include_dir}") # Module install interface directories set(repo_install_interface_include_dir "${INSTALL_INCLUDEDIR}") @@ -945,6 +1080,10 @@ the different base name for the module info variables.") "${repo_install_interface_include_dir}/${${result}_private_include_dir}") set("${result}_install_interface_qpa_include_dir" "${repo_install_interface_include_dir}/${${result}_qpa_include_dir}") + set("${result}_install_interface_rhi_include_dir" + "${repo_install_interface_include_dir}/${${result}_rhi_include_dir}") + set("${result}_install_interface_ssg_include_dir" + "${repo_install_interface_include_dir}/${${result}_ssg_include_dir}") set("${result}" "${module}" PARENT_SCOPE) set("${result}_versioned" "${module_versioned}" PARENT_SCOPE) @@ -958,6 +1097,8 @@ the different base name for the module info variables.") "${${result}_versioned_inner_include_dir}" PARENT_SCOPE) set("${result}_private_include_dir" "${${result}_private_include_dir}" PARENT_SCOPE) set("${result}_qpa_include_dir" "${${result}_qpa_include_dir}" PARENT_SCOPE) + set("${result}_rhi_include_dir" "${${result}_rhi_include_dir}" PARENT_SCOPE) + set("${result}_ssg_include_dir" "${${result}_ssg_include_dir}" PARENT_SCOPE) set("${result}_interface_name" "${module_interface_name}" PARENT_SCOPE) # Setting module build interface directories in parent scope @@ -972,6 +1113,10 @@ the different base name for the module info variables.") "${${result}_build_interface_private_include_dir}" PARENT_SCOPE) set("${result}_build_interface_qpa_include_dir" "${${result}_build_interface_qpa_include_dir}" PARENT_SCOPE) + set("${result}_build_interface_rhi_include_dir" + "${${result}_build_interface_rhi_include_dir}" PARENT_SCOPE) + set("${result}_build_interface_ssg_include_dir" + "${${result}_build_interface_ssg_include_dir}" PARENT_SCOPE) # Setting module install interface directories in parent scope set(repo_install_interface_include_dir "${repo_install_interface_include_dir}" PARENT_SCOPE) @@ -985,6 +1130,21 @@ the different base name for the module info variables.") "${${result}_install_interface_private_include_dir}" PARENT_SCOPE) set("${result}_install_interface_qpa_include_dir" "${${result}_install_interface_qpa_include_dir}" PARENT_SCOPE) + set("${result}_install_interface_rhi_include_dir" + "${${result}_install_interface_rhi_include_dir}" PARENT_SCOPE) + set("${result}_install_interface_ssg_include_dir" + "${${result}_install_interface_ssg_include_dir}" PARENT_SCOPE) +endfunction() + +function(qt_internal_list_to_json_array out_var list_var) + set(result "") + foreach(item IN LISTS ${list_var}) + if(NOT "${result}" STREQUAL "") + string(APPEND result ", ") + endif() + string(APPEND result "\"${item}\"") + endforeach() + set("${out_var}" "[${result}]" PARENT_SCOPE) endfunction() # Generate a module description file based on the template in ModuleDescription.json.in @@ -995,10 +1155,41 @@ function(qt_describe_module target) set(descfile_in "${QT_CMAKE_DIR}/ModuleDescription.json.in") set(descfile_out "${build_dir}/${target}.json") + string(TOLOWER "${PROJECT_NAME}" lower_case_project_name) set(cross_compilation "false") if(CMAKE_CROSSCOMPILING) set(cross_compilation "true") endif() + set(extra_module_information "") + + get_target_property(target_type ${target} TYPE) + if(NOT target_type STREQUAL "INTERFACE_LIBRARY") + get_target_property(plugin_types ${target} QMAKE_MODULE_PLUGIN_TYPES) + if(plugin_types) + qt_internal_list_to_json_array(plugin_types plugin_types) + string(APPEND extra_module_information "\n \"plugin_types\": ${plugin_types},") + endif() + endif() + + get_target_property(is_internal ${target} _qt_is_internal_module) + if(is_internal) + string(APPEND extra_module_information "\n \"internal\": true,") + endif() + + set(extra_build_information "") + if(NOT QT_NAMESPACE STREQUAL "") + string(APPEND extra_build_information " + \"namespace\": \"${QT_NAMESPACE}\",") + endif() + if(ANDROID) + string(APPEND extra_build_information " + \"android\": { + \"api_version\": \"${QT_ANDROID_API_VERSION}\", + \"ndk\": { + \"version\": \"${ANDROID_NDK_REVISION}\" + } + },") + endif() configure_file("${descfile_in}" "${descfile_out}") qt_install(FILES "${descfile_out}" DESTINATION "${install_dir}") @@ -1006,7 +1197,7 @@ endfunction() function(qt_internal_generate_cpp_global_exports target module_define_infix) cmake_parse_arguments(arg - "GENERATE_PRIVATE_CPP_EXPORTS" + "" "CPP_EXPORT_HEADER_BASE_NAME" "" ${ARGN} ) @@ -1030,49 +1221,190 @@ function(qt_internal_generate_cpp_global_exports target module_define_infix) set(${out_public_header} "${generated_header_path}" PARENT_SCOPE) target_sources(${target} PRIVATE "${generated_header_path}") + set_source_files_properties("${generated_header_path}" PROPERTIES GENERATED TRUE) +endfunction() - if(arg_GENERATE_PRIVATE_CPP_EXPORTS) - set(generated_private_header_path - "${module_build_interface_private_include_dir}/${header_base_name}_p.h" - ) +function(qt_internal_install_module_headers target) + set(options) + set(one_value_args) + set(multi_value_args PUBLIC PRIVATE QPA RHI SSG) + cmake_parse_arguments(arg "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) - configure_file("${QT_CMAKE_DIR}/modulecppexports_p.h.in" - "${generated_private_header_path}" @ONLY - ) + qt_internal_module_info(module ${target}) + + get_target_property(target_type ${target} TYPE) + set(is_interface_lib FALSE) + if(target_type STREQUAL "INTERFACE_LIBRARY") + set(is_interface_lib TRUE) + else() + get_target_property(is_framework ${target} FRAMEWORK) + endif() - set(${out_private_header} "${generated_private_header_path}" PARENT_SCOPE) - target_sources(${target} PRIVATE "${generated_private_header_path}") + + foreach(header_type IN LISTS multi_value_args) + if(NOT arg_${header_type}) + set(arg_${header_type} "") + endif() + endforeach() + + if(is_framework) + qt_copy_framework_headers(${target} + PUBLIC ${arg_PUBLIC} + PRIVATE ${arg_PRIVATE} + QPA ${arg_QPA} + RHI ${arg_RHI} + SSG ${arg_SSG} + ) + else() + if(arg_PUBLIC) + qt_install(FILES ${arg_PUBLIC} + DESTINATION "${module_install_interface_include_dir}") + endif() + if(arg_PRIVATE) + qt_install(FILES ${arg_PRIVATE} + DESTINATION "${module_install_interface_private_include_dir}") + endif() + if(arg_QPA) + qt_install(FILES ${arg_QPA} DESTINATION "${module_install_interface_qpa_include_dir}") + endif() + if(arg_RHI) + qt_install(FILES ${arg_RHI} DESTINATION "${module_install_interface_rhi_include_dir}") + endif() + if(arg_SSG) + qt_install(FILES ${arg_SSG} DESTINATION "${module_install_interface_ssg_include_dir}") + endif() endif() +endfunction() + +function(qt_internal_collect_module_headers out_var target) + set(${out_var}_public "") + set(${out_var}_private "") + set(${out_var}_qpa "") + set(${out_var}_rhi "") + set(${out_var}_ssg "") + set(${out_var}_all "") - get_target_property(is_framework ${target} FRAMEWORK) + qt_internal_get_target_sources(sources ${target}) get_target_property(target_type ${target} TYPE) - set(is_interface_lib 0) if(target_type STREQUAL "INTERFACE_LIBRARY") - set(is_interface_lib 1) + set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}") + set(binary_dir "${CMAKE_CURRENT_BINARY_DIR}") + else() + get_target_property(source_dir ${target} SOURCE_DIR) + get_target_property(binary_dir ${target} BINARY_DIR) endif() + get_filename_component(source_dir "${source_dir}" ABSOLUTE) + get_filename_component(binary_dir "${binary_dir}" ABSOLUTE) + + get_target_property(is_3rdparty_library ${target} _qt_module_is_3rdparty_header_library) + + get_target_property(public_filter ${target} _qt_module_public_headers_filter_regex) + get_target_property(private_filter ${target} _qt_module_private_headers_filter_regex) + get_target_property(qpa_filter ${target} _qt_module_qpa_headers_filter_regex) + get_target_property(rhi_filter ${target} _qt_module_rhi_headers_filter_regex) + get_target_property(ssg_filter ${target} _qt_module_ssg_headers_filter_regex) + + set(condition_independent_headers_warning "") + foreach(file_path IN LISTS sources) + get_filename_component(file_name "${file_path}" NAME) + if(NOT file_name MATCHES ".+\\.h$") + continue() + endif() - set_property(TARGET ${target} APPEND PROPERTY - _qt_module_timestamp_dependencies "${generated_header_path}") + get_source_file_property(non_module_header ${file_path} _qt_non_module_header) + if(non_module_header) + continue() + endif() - if(is_framework) - if(NOT is_interface_lib) - qt_copy_framework_headers(${target} PUBLIC "${generated_header_path}") + get_filename_component(file_path "${file_path}" ABSOLUTE) - if(arg_GENERATE_PRIVATE_CPP_EXPORTS) - qt_copy_framework_headers(${target} PRIVATE "${generated_private_header_path}") - endif() + string(FIND "${file_path}" "${source_dir}" source_dir_pos) + if(source_dir_pos EQUAL 0) + set(is_outside_module_source_dir FALSE) + else() + set(is_outside_module_source_dir TRUE) endif() - else() - set_property(TARGET ${target} APPEND PROPERTY PUBLIC_HEADER "${generated_header_path}") - qt_install(FILES "${generated_header_path}" - DESTINATION "${module_install_interface_include_dir}") - - if(arg_GENERATE_PRIVATE_CPP_EXPORTS) - set_property(TARGET ${target} APPEND PROPERTY PRIVATE_HEADER - "${generated_private_header_path}") - qt_install(FILES "${generated_private_header_path}" - DESTINATION "${module_install_interface_private_include_dir}") + + get_source_file_property(is_generated "${file_path}" GENERATED) + # Skip all header files outside the module source directory, except the generated files. + if(is_outside_module_source_dir AND NOT is_generated) + continue() + endif() + + get_source_file_property(condition ${file_path} _qt_extend_target_condition) + if(NOT condition STREQUAL "" AND NOT condition STREQUAL "NOTFOUND") + list(JOIN condition " " condition_string) + string(APPEND condition_independent_headers_warning + "\nFile:\n ${file_path}" + "\nCondition:\n ${condition_string}") + endif() + + if(is_outside_module_source_dir) + set(base_dir "${binary_dir}") + else() + set(base_dir "${source_dir}") + endif() + + file(RELATIVE_PATH file_path_rel "${base_dir}" "${file_path}") + if(file_path_rel MATCHES "3rdparty/.+" AND NOT is_3rdparty_library) + set(is_3rdparty_header TRUE) + else() + set(is_3rdparty_header FALSE) + endif() + list(APPEND ${out_var}_all "${file_path}") + if(qpa_filter AND file_name MATCHES "${qpa_filter}") + list(APPEND ${out_var}_qpa "${file_path}") + elseif(rhi_filter AND file_name MATCHES "${rhi_filter}") + list(APPEND ${out_var}_rhi "${file_path}") + elseif(ssg_filter AND file_name MATCHES "${ssg_filter}") + list(APPEND ${out_var}_ssg "${file_path}") + elseif(private_filter AND file_name MATCHES "${private_filter}") + list(APPEND ${out_var}_private "${file_path}") + elseif((NOT public_filter OR file_name MATCHES "${public_filter}") + AND NOT is_3rdparty_header) + list(APPEND ${out_var}_public "${file_path}") + endif() + if(is_generated) + list(APPEND ${out_var}_generated "${file_path}") endif() + endforeach() + + if(NOT condition_independent_headers_warning STREQUAL "" AND QT_FEATURE_developer_build) + message(AUTHOR_WARNING "Condition is ignored when adding the following header file(s) to" + " the ${target} module:" + "${condition_independent_headers_warning}" + "\nThe usage of the file(s) is not properly isolated in this or other modules according" + " to the condition. This warning is for the Qt maintainers. Please make sure that file" + " include(s) are guarded with the appropriate macros in the Qt code. If files should be" + " added to the module unconditionally, please move them to the common SOURCES section" + " in the qt_internal_add_module call.") endif() + + + set(header_types public private qpa rhi ssg) + set(has_header_types_properties "") + foreach(header_type IN LISTS header_types) + get_target_property(current_propety_value ${target} _qt_module_has_${header_type}_headers) + if(${out_var}_${header_type}) + list(APPEND has_header_types_properties + _qt_module_has_${header_type}_headers TRUE) + endif() + + set(${out_var}_${header_type} "${${out_var}_${header_type}}" PARENT_SCOPE) + endforeach() + set(${out_var}_all "${${out_var}_all}" PARENT_SCOPE) + set(${out_var}_generated "${${out_var}_generated}" PARENT_SCOPE) + + if(has_header_types_properties) + set_target_properties(${target} PROPERTIES ${has_header_types_properties}) + endif() + set_property(TARGET ${target} APPEND PROPERTY + EXPORT_PROPERTIES + _qt_module_has_public_headers + _qt_module_has_private_headers + _qt_module_has_qpa_headers + _qt_module_has_rhi_headers + _qt_module_has_ssg_headers + ) endfunction() |