From d8f34049ffbed73fe55bb875409af750d354cb9f Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 10 Mar 2025 11:58:18 +0100 Subject: [PATCH] CMake: Fix generation of precompiled headers in per-repo Qt builds When a Qt module Foo links against a Qt module Bar then we add the ${QT_BUILD_DIR}/include/QtBar/QtBar header to the list of precompiled header files. However, this only works if Foo and Bar are in the same build system, e.g. in the same repository or in a top-level build. For example, the QtCore header was never precompiled when in a per-repo build of QtSvg. Now, we determine whether Foo and Bar are in the same build system. If they are, we proceed as before. Otherwise, we calculate the QtBar header's location from the following data: - the location of Qt6BarConfig.cmake - the relative path to Bar's include directory The Q*Application tests' project files had to be adjusted to use NO_PCH_SOURCES now, because they use the source file apphelper_plugin.cpp that specifically checks that pre-compiled headers are not used for its compilation. Fixes: QTBUG-134424 Change-Id: I04ede51e4d853e8b813f660f29be8cfeb684c0b2 Reviewed-by: Alexandru Croitor Reviewed-by: Alexey Edelev --- cmake/QtModuleHelpers.cmake | 18 +++++++ cmake/QtPrecompiledHeadersHelpers.cmake | 47 +++++++++++++++++-- .../kernel/qcoreapplication/CMakeLists.txt | 2 + .../gui/kernel/qguiapplication/CMakeLists.txt | 2 + .../kernel/qapplication/CMakeLists.txt | 2 + 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake index 76ae2edb524..bdf00c68b64 100644 --- a/cmake/QtModuleHelpers.cmake +++ b/cmake/QtModuleHelpers.cmake @@ -454,6 +454,24 @@ function(qt_internal_add_module target) set(module_header "${module_build_interface_include_dir}/${module_include_name}") set_property(TARGET "${target}" PROPERTY MODULE_HEADER "${module_header}") + + if(QT_FEATURE_no_prefix) + file(RELATIVE_PATH relative_include_dir + "/${QT_CONFIG_INSTALL_DIR}/${module_include_name}" + "/${module_build_interface_include_dir}" + ) + else() + file(RELATIVE_PATH relative_include_dir + "/${QT_CONFIG_INSTALL_DIR}/${module_include_name}" + "/${module_install_interface_include_dir}" + ) + endif() + set_property(TARGET "${target}" PROPERTY + _qt_module_relative_include_dir "${relative_include_dir}" + ) + set_property(TARGET ${target} APPEND PROPERTY + EXPORT_PROPERTIES _qt_module_relative_include_dir + ) endif() set(qpa_filter_regex "") diff --git a/cmake/QtPrecompiledHeadersHelpers.cmake b/cmake/QtPrecompiledHeadersHelpers.cmake index fa152e4447c..b47e4e74e33 100644 --- a/cmake/QtPrecompiledHeadersHelpers.cmake +++ b/cmake/QtPrecompiledHeadersHelpers.cmake @@ -8,13 +8,50 @@ function(qt_update_precompiled_header target precompiled_header) endfunction() function(qt_update_precompiled_header_with_library target library) - if (TARGET "${library}") - get_target_property(TARGET_TYPE "${library}" TYPE) - if (NOT TARGET_TYPE STREQUAL "INTERFACE_LIBRARY") - get_target_property(HEADER "${library}" MODULE_HEADER) - qt_update_precompiled_header("${target}" "${HEADER}") + if(NOT TARGET "${library}") + return() + endif() + + get_target_property(target_type "${library}" TYPE) + if(target_type STREQUAL "INTERFACE_LIBRARY") + return() + endif() + + get_target_property(header_file_path "${library}" MODULE_HEADER) + if(NOT header_file_path) + # The Qt module is imported from the Qt installation prefix. + # Calculate the module header location. + get_target_property(include_name "${library}" _qt_module_include_name) + if(NOT include_name) + message(DEBUG "Property _qt_module_include_name is not set on ${library}.") + return() + endif() + + get_target_property(relative_include_dir "${library}" _qt_module_relative_include_dir) + if(NOT relative_include_dir) + message(DEBUG "Property _qt_module_relative_include_dir is not set on ${library}.") + return() + endif() + + get_target_property(package_name ${library} _qt_package_name) + if(NOT package_name) + message(DEBUG "No package name found for ${library}.") + return() + endif() + set(package_location "${${package_name}_DIR}") + get_filename_component(absolute_include_dir + "${package_location}/${relative_include_dir}" + ABSOLUTE + ) + + set(header_file_path "${absolute_include_dir}/${include_name}") + if(NOT EXISTS "${header_file_path}") + message(DEBUG "Module header '${header_file_path}' does not exist.") + return() endif() endif() + + qt_update_precompiled_header("${target}" "${header_file_path}") endfunction() function(qt_update_ignore_pch_source target sources) diff --git a/tests/auto/corelib/kernel/qcoreapplication/CMakeLists.txt b/tests/auto/corelib/kernel/qcoreapplication/CMakeLists.txt index 1c1006a1410..da9d2da7fd3 100644 --- a/tests/auto/corelib/kernel/qcoreapplication/CMakeLists.txt +++ b/tests/auto/corelib/kernel/qcoreapplication/CMakeLists.txt @@ -66,6 +66,8 @@ if(QT_FEATURE_library) MODULE SOURCES apphelper_plugin.cpp + NO_PCH_SOURCES + apphelper_plugin.cpp LIBRARIES Qt::Core ) diff --git a/tests/auto/gui/kernel/qguiapplication/CMakeLists.txt b/tests/auto/gui/kernel/qguiapplication/CMakeLists.txt index 130421dd0e7..328c3b3d42a 100644 --- a/tests/auto/gui/kernel/qguiapplication/CMakeLists.txt +++ b/tests/auto/gui/kernel/qguiapplication/CMakeLists.txt @@ -76,6 +76,8 @@ if(QT_FEATURE_library) MODULE SOURCES ../../../corelib/kernel/qcoreapplication/apphelper_plugin.cpp + NO_PCH_SOURCES + ../../../corelib/kernel/qcoreapplication/apphelper_plugin.cpp LIBRARIES Qt::Gui ) diff --git a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt index 07c6bba5e69..b9d0ce3c67e 100644 --- a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt @@ -27,6 +27,8 @@ if(QT_FEATURE_library) MODULE SOURCES ../../../corelib/kernel/qcoreapplication/apphelper_plugin.cpp + NO_PCH_SOURCES + ../../../corelib/kernel/qcoreapplication/apphelper_plugin.cpp LIBRARIES Qt::Widgets )