Replace the syncqt.pl script with syncqt tool

syncqt.pl adds an extra dependency on perl when building Qt. Modern C++
provides the convenient cross-platform way to access a filesystem and
to use regular expressions, so we may replace the perl script with C++
application. The syncqt executable is built at configure time and
installed as QtCore tool. It's running at configure time to deliver the
required header files for IDE to build a consistent code model and at
the build time to keep tracking changes in header files and generate
the missing aliases without reconfiguring. 'syncqt' only parses header
files from a CMake build tree, so the resulting Qt installation only
contains interfacing headers that belong to the platform that Qt is
built for. 'sync.profile' files are not used as the 'source of truth'
for sync qt procedure anymore, all the necessary information is taken
from either CMake files at configure time or from the module header
files while parsing them.

syncqt.pl is still in place since it's required as fallback solution
for a smooth transition to the new syncqt implementation for all qt
repositories.

This patchset only enables the C++ based syncqt for 'qtbase'
repository.

From the performance perspective C++ version works faster then perl
script, also the configure time is reduced significally on subsequent
reconfigurations - up x2 times faster when re-configuring repository,
but it also takes time to compile the tool itself the first time.
Numbers for qtbase:
           syncqt.pl  syncqt.cpp
 initial:  0m16,035s  0m20,413s
 reconfig: 0m6,819s   0m3,725s

The syncing procedure can be run separately for each module using
<ModuleName>_sync_headers targets. The 'sync_headers' target can be
used to sync all the modules at once.

Task-number: QTBUG-87480
Task-number: QTBUG-103196
Change-Id: I8c938bcaf88a8713b39bbfd66d9e7ef12b2c3523
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Alexey Edelev 2022-08-15 18:29:41 +02:00
parent 458ec4cb54
commit b89d63515b
31 changed files with 2213 additions and 181 deletions

View File

@ -31,3 +31,6 @@ set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT_STATIC "3.21")
# in sync. # in sync.
set(QT_MIN_NEW_POLICY_CMAKE_VERSION "3.16") set(QT_MIN_NEW_POLICY_CMAKE_VERSION "3.16")
set(QT_MAX_NEW_POLICY_CMAKE_VERSION "3.21") set(QT_MAX_NEW_POLICY_CMAKE_VERSION "3.21")
# Use cpp-based syncqt
set(QT_USE_SYNCQT_CPP TRUE)

View File

@ -247,6 +247,7 @@ qt_copy_or_install(FILES
cmake/QtLalrHelpers.cmake cmake/QtLalrHelpers.cmake
cmake/QtModuleConfig.cmake.in cmake/QtModuleConfig.cmake.in
cmake/QtModuleDependencies.cmake.in cmake/QtModuleDependencies.cmake.in
cmake/QtModuleHeadersCheck.cmake
cmake/QtModuleHelpers.cmake cmake/QtModuleHelpers.cmake
cmake/QtModuleToolsConfig.cmake.in cmake/QtModuleToolsConfig.cmake.in
cmake/QtModuleToolsDependencies.cmake.in cmake/QtModuleToolsDependencies.cmake.in

View File

@ -228,6 +228,15 @@ if(NOT QT_MKSPECS_DIR)
set(QT_MKSPECS_DIR "${QT_MKSPECS_DIR}" CACHE INTERNAL "") set(QT_MKSPECS_DIR "${QT_MKSPECS_DIR}" CACHE INTERNAL "")
endif() endif()
# macOS versions 10.14 and less don't have the implementation of std::filesystem API.
if(CMAKE_HOST_APPLE AND CMAKE_HOST_SYSTEM_VERSION VERSION_LESS "19.0.0")
message(FATAL_ERROR "macOS versions less than 10.15 are not supported for building Qt.")
endif()
if(NOT DEFINED QT_USE_SYNCQT_CPP)
set(QT_USE_SYNCQT_CPP FALSE)
endif()
# the default RPATH to be used when installing, but only if it's not a system directory # the default RPATH to be used when installing, but only if it's not a system directory
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBDIR}" isSystemDir) list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBDIR}" isSystemDir)
if("${isSystemDir}" STREQUAL "-1") if("${isSystemDir}" STREQUAL "-1")

View File

@ -419,6 +419,10 @@ macro(qt_build_repo_begin)
add_dependencies(install_docs install_html_docs install_qch_docs) add_dependencies(install_docs install_html_docs install_qch_docs)
endif() endif()
if(NOT TARGET sync_headers)
add_custom_target(sync_headers)
endif()
# Add global qt_plugins, qpa_plugins and qpa_default_plugins convenience custom targets. # Add global qt_plugins, qpa_plugins and qpa_default_plugins convenience custom targets.
# Internal executables will add a dependency on the qpa_default_plugins target, # Internal executables will add a dependency on the qpa_default_plugins target,
# so that building and running a test ensures it won't fail at runtime due to a missing qpa # so that building and running a test ensures it won't fail at runtime due to a missing qpa
@ -474,6 +478,10 @@ macro(qt_build_repo_begin)
if(NOT TARGET benchmark) if(NOT TARGET benchmark)
add_custom_target(benchmark) add_custom_target(benchmark)
endif() endif()
if(QT_INTERNAL_SYNCED_MODULES)
set_property(GLOBAL PROPERTY _qt_synced_modules ${QT_INTERNAL_SYNCED_MODULES})
endif()
endmacro() endmacro()
macro(qt_build_repo_end) macro(qt_build_repo_end)
@ -510,6 +518,12 @@ macro(qt_build_repo_end)
if(NOT QT_SUPERBUILD) if(NOT QT_SUPERBUILD)
qt_print_build_instructions() qt_print_build_instructions()
endif() endif()
get_property(synced_modules GLOBAL PROPERTY _qt_synced_modules)
if(synced_modules)
set(QT_INTERNAL_SYNCED_MODULES ${synced_modules} CACHE INTERNAL
"List of the synced modules. Prevents running syncqt.cpp after the first configuring.")
endif()
endmacro() endmacro()
macro(qt_build_repo) macro(qt_build_repo)

View File

@ -140,6 +140,12 @@ function(qt_internal_add_docs)
) )
add_dependencies(prepare_docs_${target} qattributionsscanner_${target}) add_dependencies(prepare_docs_${target} qattributionsscanner_${target})
if(QT_USE_SYNCQT_CPP)
if(NOT TARGET sync_all_public_headers)
add_custom_target(sync_all_public_headers)
endif()
add_dependencies(prepare_docs_${target} sync_all_public_headers)
endif()
# generate docs target # generate docs target
set(generate_qdoc_args set(generate_qdoc_args

View File

@ -429,7 +429,7 @@ function(qt_internal_add_configure_time_executable target)
set(cmake_flags_arg) set(cmake_flags_arg)
if(arg_CMAKE_FLAGS) if(arg_CMAKE_FLAGS)
set(cmake_flags_arg CMAKE_FLAGS ${arg_CMAKE_FLAGS}) set(cmake_flags_arg CMAKE_FLAGS "${arg_CMAKE_FLAGS}")
endif() endif()
configure_file("${template}" "${target_binary_dir}/CMakeLists.txt" @ONLY) configure_file("${template}" "${target_binary_dir}/CMakeLists.txt" @ONLY)
try_compile(result try_compile(result

View File

@ -97,6 +97,19 @@ function(qt_copy_framework_headers target)
QT_COPIED_FRAMEWORK_HEADERS "${out_files}") QT_COPIED_FRAMEWORK_HEADERS "${out_files}")
endfunction() endfunction()
function(qt_internal_generate_fake_framework_header target)
# Hack to create the "Headers" symlink in the framework:
# Create a fake header file and copy it into the framework by marking it as PUBLIC_HEADER.
# CMake now takes care of creating the symlink.
set(fake_header "${CMAKE_CURRENT_BINARY_DIR}/${target}_fake_header.h")
qt_internal_get_main_cmake_configuration(main_config)
file(GENERATE OUTPUT "${fake_header}" CONTENT "// ignore this file\n"
CONDITION "$<CONFIG:${main_config}>")
target_sources(${target} PRIVATE "${fake_header}")
set_source_files_properties("${fake_header}" PROPERTIES GENERATED ON)
set_property(TARGET ${target} APPEND PROPERTY PUBLIC_HEADER "${fake_header}")
endfunction()
function(qt_finalize_framework_headers_copy target) function(qt_finalize_framework_headers_copy target)
get_target_property(target_type ${target} TYPE) get_target_property(target_type ${target} TYPE)
if(${target_type} STREQUAL "INTERFACE_LIBRARY") if(${target_type} STREQUAL "INTERFACE_LIBRARY")
@ -108,17 +121,7 @@ function(qt_finalize_framework_headers_copy target)
endif() endif()
get_target_property(headers ${target} QT_COPIED_FRAMEWORK_HEADERS) get_target_property(headers ${target} QT_COPIED_FRAMEWORK_HEADERS)
if(headers) if(headers)
# Hack to create the "Headers" symlink in the framework: qt_internal_generate_fake_framework_header(${target})
# Create a fake header file and copy it into the framework by marking it as PUBLIC_HEADER.
# CMake now takes care of creating the symlink.
set(fake_header ${target}_fake_header.h)
qt_internal_get_main_cmake_configuration(main_config)
file(GENERATE OUTPUT ${fake_header} CONTENT "// ignore this file\n"
CONDITION "$<CONFIG:${main_config}>")
string(PREPEND fake_header "${CMAKE_CURRENT_BINARY_DIR}/")
target_sources(${target} PRIVATE ${fake_header})
set_source_files_properties(${fake_header} PROPERTIES GENERATED ON)
set_property(TARGET ${target} APPEND PROPERTY PUBLIC_HEADER ${fake_header})
# Add a target, e.g. Core_framework_headers, that triggers the header copy. # Add a target, e.g. Core_framework_headers, that triggers the header copy.
add_custom_target(${target}_framework_headers DEPENDS ${headers}) add_custom_target(${target}_framework_headers DEPENDS ${headers})

View File

@ -4,26 +4,18 @@
# Add a custom ${module_target}_headersclean_check target that builds each header in # Add a custom ${module_target}_headersclean_check target that builds each header in
# ${module_headers} with a custom set of defines. This makes sure our public headers # ${module_headers} with a custom set of defines. This makes sure our public headers
# are self-contained, and also compile with more strict compiler options. # are self-contained, and also compile with more strict compiler options.
function(qt_internal_add_headersclean_target function(qt_internal_add_headersclean_target module_target module_headers)
module_target get_target_property(has_headers ${module_target} _qt_module_has_headers)
module_include_name if(NOT has_headers)
module_headers) return()
# module_headers is a list of strings of the form endif()
# <headerfile>[:feature]
set(hclean_headers "")
foreach(entry ${module_headers})
string(REPLACE ":" ";" entry_list ${entry})
list(LENGTH entry_list entry_list_length)
list(GET entry_list 0 entry_path)
if (${entry_list_length} EQUAL 2) set(hclean_headers "")
list(GET entry_list 1 entry_feature) foreach(header IN LISTS module_headers)
if (NOT QT_FEATURE_${entry_feature}) get_filename_component(header_name "${header}" NAME)
message(STATUS "headersclean: Ignoring header ${entry_path} because of missing feature ${entry_feature}") if(header_name MATCHES "^q[^_]+\\.h$" AND NOT header_name MATCHES ".*(global|exports)\\.h")
continue() list(APPEND hclean_headers "${header}")
endif()
endif() endif()
list(APPEND hclean_headers ${entry_path})
endforeach() endforeach()
# Make sure that the header compiles with our strict options # Make sure that the header compiles with our strict options
@ -53,6 +45,12 @@ function(qt_internal_add_headersclean_target
set(target_includes_joined_genex set(target_includes_joined_genex
"$<${includes_exist_genex}:-I$<JOIN:${target_includes_genex},;-I>>") "$<${includes_exist_genex}:-I$<JOIN:${target_includes_genex},;-I>>")
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
if(is_multi_config)
list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type)
set(config_suffix "$<$<NOT:$<CONFIG:${first_config_type}>>:-$<CONFIG>>")
endif()
# qmake doesn't seem to add the defines that are set by the header_only_module when checking the # qmake doesn't seem to add the defines that are set by the header_only_module when checking the
# the cleanliness of the module's header files. # the cleanliness of the module's header files.
# This allows us to bypass an error with CMake 3.18 and lower when trying to evaluate # This allows us to bypass an error with CMake 3.18 and lower when trying to evaluate
@ -165,35 +163,23 @@ function(qt_internal_add_headersclean_target
endforeach() endforeach()
endif() endif()
foreach(header ${hclean_headers}) set(compiler_command_line
get_filename_component(input_path "${header}" ABSOLUTE) "${compiler_to_run}" "-c" "${cxx_flags}"
set(artifact_path "header_check/${header}.o") "${target_compile_flags_joined_genex}"
get_filename_component(artifact_directory "${artifact_path}" DIRECTORY) "${target_defines_joined_genex}"
set(comment_header_path "${CMAKE_CURRENT_SOURCE_DIR}/${header}") "${hcleanFLAGS}"
file(RELATIVE_PATH comment_header_path "${PROJECT_SOURCE_DIR}" "${comment_header_path}") "${target_includes_joined_genex}"
"${framework_includes}"
add_custom_command( "${hcleanDEFS}"
OUTPUT "${artifact_path}"
COMMENT "headersclean: Checking header ${comment_header_path}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${artifact_directory}"
COMMAND
${compiler_to_run} -c ${cxx_flags}
"${target_compile_flags_joined_genex}"
"${target_defines_joined_genex}"
${hcleanFLAGS}
"${target_includes_joined_genex}"
${framework_includes}
${hcleanDEFS}
-xc++ "${input_path}"
-o${artifact_path}
IMPLICIT_DEPENDS CXX
VERBATIM
COMMAND_EXPAND_LISTS
DEPENDS "${input_path}"
)
list(APPEND hclean_artifacts "${artifact_path}")
endforeach()
)
string(JOIN " " compiler_command_line_variables
"-xc++"
"\${INPUT_HEADER_FILE}"
"-o"
"\${OUTPUT_ARTIFACT}"
)
set(input_header_path_type ABSOLUTE)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# -Za would enable strict standards behavior, but we can't add it because # -Za would enable strict standards behavior, but we can't add it because
# <windows.h> and <GL.h> violate the standards. # <windows.h> and <GL.h> violate the standards.
@ -202,37 +188,87 @@ function(qt_internal_add_headersclean_target
# cl.exe needs a source path # cl.exe needs a source path
get_filename_component(source_path "${QT_MKSPECS_DIR}/features/data/dummy.cpp" REALPATH) get_filename_component(source_path "${QT_MKSPECS_DIR}/features/data/dummy.cpp" REALPATH)
foreach(header ${hclean_headers}) set(compiler_command_line
# We need realpath here to make sure path starts with drive letter "${compiler_to_run}" "-nologo" "-c" "${CMAKE_CXX_FLAGS}"
get_filename_component(input_path "${header}" REALPATH) "${target_compile_flags_joined_genex}"
set(artifact_path "header_${header}.o") "${target_defines_joined_genex}"
set(comment_header_path "${CMAKE_CURRENT_SOURCE_DIR}/${header}") "${hcleanFLAGS}"
file(RELATIVE_PATH comment_header_path "${PROJECT_SOURCE_DIR}" "${comment_header_path}") "${target_includes_joined_genex}"
"${hcleanDEFS}"
)
string(JOIN " " compiler_command_line_variables
"-FI"
"\${INPUT_HEADER_FILE}"
"-Fo\${OUTPUT_ARTIFACT}"
"${source_path}"
)
add_custom_command( set(input_header_path_type REALPATH)
OUTPUT "${artifact_path}"
COMMENT "headersclean: Checking header ${comment_header_path}"
COMMAND
${compiler_to_run} -nologo -c ${CMAKE_CXX_FLAGS}
"${target_compile_flags_joined_genex}"
"${target_defines_joined_genex}"
${hcleanFLAGS}
"${target_includes_joined_genex}"
${hcleanDEFS}
-FI "${input_path}"
-Fo${artifact_path} "${source_path}"
IMPLICIT_DEPENDS CXX
VERBATIM
COMMAND_EXPAND_LISTS
DEPENDS "${input_path}"
)
list(APPEND hclean_artifacts "${artifact_path}")
endforeach()
else() else()
message(FATAL_ERROR "CMAKE_CXX_COMPILER_ID \"${CMAKE_CXX_COMPILER_ID}\" is not supported" message(FATAL_ERROR "CMAKE_CXX_COMPILER_ID \"${CMAKE_CXX_COMPILER_ID}\" is not supported"
" for the headersclean check.") " for the headersclean check.")
endif() endif()
get_target_property(module_include_name ${target} _qt_module_include_name)
unset(header_check_exceptions)
if(QT_USE_SYNCQT_CPP)
set(header_check_exceptions
"${CMAKE_CURRENT_BINARY_DIR}/${module_include_name}_header_check_exceptions")
endif()
set(headers_check_parameters
"${CMAKE_CURRENT_BINARY_DIR}/${module_target}HeadersCheckParameters${config_suffix}.cmake")
string(JOIN "\n" headers_check_parameters_content
"set(HEADER_CHECK_EXCEPTIONS"
" \"${header_check_exceptions}\")"
"set(HEADER_CHECK_COMPILER_COMMAND_LINE"
" \[\[$<JOIN:${compiler_command_line},\]\]\n \[\[>\]\]\n"
" ${compiler_command_line_variables}"
")"
)
file(GENERATE OUTPUT "${headers_check_parameters}"
CONTENT "${headers_check_parameters_content}")
set(sync_headers_dep "")
if(QT_USE_SYNCQT_CPP)
set(sync_headers_dep "sync_headers")
endif()
foreach(header ${hclean_headers})
# We need realpath here to make sure path starts with drive letter
get_filename_component(input_path "${header}" ${input_header_path_type})
get_filename_component(input_file_name ${input_path} NAME)
set(artifact_path "${CMAKE_CURRENT_BINARY_DIR}/header_check/${input_file_name}.o")
if(input_path MATCHES "${CMAKE_BINARY_DIR}")
set(input_base_dir "${CMAKE_BINARY_DIR}")
elseif(input_path MATCHES "${CMAKE_SOURCE_DIR}")
set(input_base_dir "${CMAKE_SOURCE_DIR}")
endif()
file(RELATIVE_PATH comment_header_path "${input_base_dir}" "${input_path}")
add_custom_command(
OUTPUT "${artifact_path}"
COMMENT "headersclean: Checking header ${comment_header_path}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/header_check"
COMMAND ${CMAKE_COMMAND}
-DINPUT_HEADER_FILE=${input_path}
-DOUTPUT_ARTIFACT=${artifact_path}
-DPARAMETERS=${headers_check_parameters}
-P "${QT_CMAKE_DIR}/QtModuleHeadersCheck.cmake"
IMPLICIT_DEPENDS CXX
VERBATIM
COMMAND_EXPAND_LISTS
DEPENDS
${headers_check_parameters}
${sync_headers_dep}
${input_path}
${header_check_exceptions}
)
list(APPEND hclean_artifacts "${artifact_path}")
endforeach()
add_custom_target(${module_target}_headersclean_check add_custom_target(${module_target}_headersclean_check
COMMENT "headersclean: Checking headers in ${module_include_name}" COMMENT "headersclean: Checking headers in ${module_include_name}"
DEPENDS ${hclean_artifacts} DEPENDS ${hclean_artifacts}

View File

@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.16)
# The PARAMETERS file should specify the following variables for the correct work of
# this script:
# HEADER_CHECK_EXCEPTIONS - path to file that contains exceptions.
# The file is created by syncqt.
#
# HEADER_CHECK_COMPILER_COMMAND_LINE - compiler command line
include("${PARAMETERS}")
if(EXISTS ${HEADER_CHECK_EXCEPTIONS})
file(READ ${HEADER_CHECK_EXCEPTIONS} header_check_exception_list)
endif()
file(TO_CMAKE_PATH "${INPUT_HEADER_FILE}" header)
foreach(exception IN LISTS header_check_exception_list)
file(TO_CMAKE_PATH "${exception}" exception)
if(exception STREQUAL header)
file(WRITE "${OUTPUT_ARTIFACT}" "skipped")
return()
endif()
endforeach()
execute_process(COMMAND ${HEADER_CHECK_COMPILER_COMMAND_LINE}
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_VARIABLE output
)
if(NOT result EQUAL 0)
message(FATAL_ERROR "${INPUT_HEADER_FILE} header check"
" failed: ${HEADER_CHECK_COMPILER_COMMAND_LINE}\n"
" ${output}")
endif()

View File

@ -29,6 +29,7 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi
EXTERNAL_HEADERS_DIR EXTERNAL_HEADERS_DIR
PRIVATE_HEADER_FILTERS PRIVATE_HEADER_FILTERS
QPA_HEADER_FILTERS QPA_HEADER_FILTERS
HEADER_SYNC_SOURCE_DIRECTORY
${__default_target_info_args} ${__default_target_info_args}
) )
set(${multi_args} set(${multi_args}
@ -111,6 +112,12 @@ endfunction()
# QPA_HEADER_FILTERS # QPA_HEADER_FILTERS
# The regular expressions that filter QPA header files out of target sources. # The regular expressions that filter QPA header files out of target sources.
# The value must use the following format 'regex1|regex2|regex3'. # 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) function(qt_internal_add_module target)
qt_internal_get_internal_add_module_keywords( qt_internal_get_internal_add_module_keywords(
module_option_args module_option_args
@ -382,13 +389,18 @@ function(qt_internal_add_module target)
else() else()
set_property(TARGET ${target} APPEND PROPERTY EXPORT_PROPERTIES _qt_module_include_name) set_property(TARGET ${target} APPEND PROPERTY EXPORT_PROPERTIES _qt_module_include_name)
set_target_properties("${target}" PROPERTIES set_target_properties("${target}" PROPERTIES
_qt_module_include_name "${module_include_name}") _qt_module_include_name "${module_include_name}"
_qt_module_has_headers ON
)
# Use QT_BUILD_DIR for the syncqt call. # Need to call qt_ensure_sync_qt to install syncqt.pl script.
# So we either write the generated files into the qtbase non-prefix build root, or the
# module specific build root.
qt_ensure_sync_qt() qt_ensure_sync_qt()
set(syncqt_full_command "${HOST_PERL}" -w "${QT_SYNCQT}" # Repo uses old perl script to sync files.
if(NOT QT_USE_SYNCQT_CPP)
# 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.
set(syncqt_full_command "${HOST_PERL}" -w "${QT_SYNCQT}"
-quiet -quiet
-check-includes -check-includes
-module "${module_include_name}" -module "${module_include_name}"
@ -396,18 +408,24 @@ function(qt_internal_add_module target)
-outdir "${QT_BUILD_DIR}" -outdir "${QT_BUILD_DIR}"
-builddir "${PROJECT_BINARY_DIR}" -builddir "${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}") "${PROJECT_SOURCE_DIR}")
message(STATUS "Running syncqt for module: '${module_include_name}' ") message(STATUS "Running syncqt for module: '${module_include_name}' ")
execute_process(COMMAND ${syncqt_full_command} RESULT_VARIABLE syncqt_ret) execute_process(COMMAND ${syncqt_full_command} RESULT_VARIABLE syncqt_ret)
if(NOT syncqt_ret EQUAL 0) if(NOT syncqt_ret EQUAL 0)
message(FATAL_ERROR "Failed to run syncqt, return code: ${syncqt_ret}") message(FATAL_ERROR "Failed to run syncqt, return code: ${syncqt_ret}")
endif()
### FIXME: Can we replace headers.pri?
qt_read_headers_pri("${module_build_interface_include_dir}" "module_headers")
set_property(TARGET ${target} APPEND PROPERTY
_qt_module_timestamp_dependencies "${module_headers_generated}")
else()
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_target_properties(${target} PROPERTIES
_qt_sync_source_directory "${sync_source_directory}")
endif() 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")
# We should not generate export headers if module is defined as pure STATIC. # 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 # Static libraries don't need to export their symbols, and corner cases when sources are
# also used in shared libraries, should be handled manually. # also used in shared libraries, should be handled manually.
@ -428,6 +446,9 @@ function(qt_internal_add_module target)
set(module_depends_header set(module_depends_header
"${module_build_interface_include_dir}/${module_include_name}Depends") "${module_build_interface_include_dir}/${module_include_name}Depends")
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}) if(NOT ${arg_HEADER_MODULE})
set(module_header "${module_build_interface_include_dir}/${module_include_name}") set(module_header "${module_build_interface_include_dir}/${module_include_name}")
set_property(TARGET "${target}" PROPERTY MODULE_HEADER set_property(TARGET "${target}" PROPERTY MODULE_HEADER
@ -455,15 +476,17 @@ function(qt_internal_add_module target)
DESTINATION "${module_install_interface_include_dir}" DESTINATION "${module_install_interface_include_dir}"
) )
else() else()
if(arg_EXTERNAL_HEADERS) if(NOT QT_USE_SYNCQT_CPP)
set(module_headers_public "${arg_EXTERNAL_HEADERS}") if(arg_EXTERNAL_HEADERS)
set(module_headers_public "${arg_EXTERNAL_HEADERS}")
endif()
qt_internal_install_module_headers(${target}
PUBLIC
${module_headers_public}
"${module_depends_header}"
"${module_header}"
)
endif() endif()
qt_internal_install_module_headers(${target}
PUBLIC
${module_headers_public}
"${module_depends_header}"
"${module_header}"
)
endif() endif()
endif() endif()
@ -650,7 +673,7 @@ function(qt_internal_add_module target)
) )
endif() endif()
if(NOT arg_HEADER_MODULE) if(NOT arg_HEADER_MODULE AND NOT QT_USE_SYNCQT_CPP)
if(DEFINED module_headers_private) if(DEFINED module_headers_private)
qt_internal_add_linker_version_script("${target}" PRIVATE_HEADERS ${module_headers_private} ${module_headers_qpa}) qt_internal_add_linker_version_script("${target}" PRIVATE_HEADERS ${module_headers_private} ${module_headers_qpa})
else() else()
@ -671,7 +694,7 @@ function(qt_internal_add_module target)
string(APPEND final_injections "${extra_library_injections} ") string(APPEND final_injections "${extra_library_injections} ")
endif() endif()
if(final_injections) if(final_injections AND NOT QT_USE_SYNCQT_CPP)
qt_install_injections(${target} "${QT_BUILD_DIR}" "${QT_INSTALL_DIR}" ${final_injections}) qt_install_injections(${target} "${QT_BUILD_DIR}" "${QT_INSTALL_DIR}" ${final_injections})
endif() endif()
@ -853,10 +876,9 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")")
endif() endif()
endif() endif()
if(QT_FEATURE_headersclean AND NOT arg_NO_MODULE_HEADERS) if(QT_FEATURE_headersclean AND NOT arg_NO_MODULE_HEADERS AND NOT QT_USE_SYNCQT_CPP)
qt_internal_add_headersclean_target( qt_internal_add_headersclean_target(
${target} ${target}
"${module_include_name}"
"${module_headers_clean}") "${module_headers_clean}")
endif() endif()
@ -890,16 +912,29 @@ endfunction()
function(qt_finalize_module target) function(qt_finalize_module target)
qt_internal_collect_module_headers(module_headers ${target}) qt_internal_collect_module_headers(module_headers ${target})
set_property(TARGET ${target} APPEND PROPERTY
_qt_module_timestamp_dependencies "${module_headers_public}")
# qt_internal_install_module_headers needs to be called before # qt_internal_install_module_headers needs to be called before
# qt_finalize_framework_headers_copy, because the last uses the QT_COPIED_FRAMEWORK_HEADERS # 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. # property which supposed to be updated inside every qt_internal_install_module_headers
qt_internal_install_module_headers(${target} # call.
PRIVATE ${module_headers_private} if(QT_USE_SYNCQT_CPP)
QPA ${module_headers_qpa} if(QT_FEATURE_headersclean)
) qt_internal_add_headersclean_target(${target} "${module_headers_public}")
endif()
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}
)
else()
qt_internal_install_module_headers(${target}
PRIVATE ${module_headers_private}
QPA ${module_headers_qpa}
)
endif()
qt_finalize_framework_headers_copy(${target}) qt_finalize_framework_headers_copy(${target})
qt_generate_prl_file(${target} "${INSTALL_LIBDIR}") qt_generate_prl_file(${target} "${INSTALL_LIBDIR}")
@ -1098,6 +1133,13 @@ function(qt_internal_generate_cpp_global_exports target module_define_infix)
set(${out_public_header} "${generated_header_path}" PARENT_SCOPE) set(${out_public_header} "${generated_header_path}" PARENT_SCOPE)
target_sources(${target} PRIVATE "${generated_header_path}") target_sources(${target} PRIVATE "${generated_header_path}")
set_source_files_properties("${generated_header_path}" PROPERTIES GENERATED TRUE)
if(NOT QT_USE_SYNCQT_CPP)
qt_internal_install_module_headers(${target}
PUBLIC
"${generated_header_path}"
)
endif()
if(arg_GENERATE_PRIVATE_CPP_EXPORTS) if(arg_GENERATE_PRIVATE_CPP_EXPORTS)
set(generated_private_header_path set(generated_private_header_path
@ -1110,35 +1152,7 @@ function(qt_internal_generate_cpp_global_exports target module_define_infix)
set(${out_private_header} "${generated_private_header_path}" PARENT_SCOPE) set(${out_private_header} "${generated_private_header_path}" PARENT_SCOPE)
target_sources(${target} PRIVATE "${generated_private_header_path}") target_sources(${target} PRIVATE "${generated_private_header_path}")
endif() set_source_files_properties("${generated_private_header_path}" PROPERTIES GENERATED TRUE)
get_target_property(is_framework ${target} FRAMEWORK)
get_target_property(target_type ${target} TYPE)
set(is_interface_lib 0)
if(target_type STREQUAL "INTERFACE_LIBRARY")
set(is_interface_lib 1)
endif()
set_property(TARGET ${target} APPEND PROPERTY
_qt_module_timestamp_dependencies "${generated_header_path}")
if(is_framework)
if(NOT is_interface_lib)
qt_copy_framework_headers(${target} PUBLIC "${generated_header_path}")
if(arg_GENERATE_PRIVATE_CPP_EXPORTS)
qt_copy_framework_headers(${target} PRIVATE "${generated_private_header_path}")
endif()
endif()
else()
qt_install(FILES "${generated_header_path}"
DESTINATION "${module_install_interface_include_dir}")
if(arg_GENERATE_PRIVATE_CPP_EXPORTS)
qt_install(FILES "${generated_private_header_path}"
DESTINATION "${module_install_interface_private_include_dir}")
endif()
endif() endif()
endfunction() endfunction()
@ -1180,10 +1194,9 @@ function(qt_internal_install_module_headers target)
qt_install(FILES ${arg_PRIVATE} qt_install(FILES ${arg_PRIVATE}
DESTINATION "${module_install_interface_private_include_dir}") DESTINATION "${module_install_interface_private_include_dir}")
endif() endif()
endif() if(arg_QPA)
qt_install(FILES ${arg_QPA} DESTINATION "${module_install_interface_qpa_include_dir}")
if(arg_QPA) endif()
qt_install(FILES ${arg_QPA} DESTINATION "${module_install_interface_qpa_include_dir}")
endif() endif()
endfunction() endfunction()
@ -1191,6 +1204,7 @@ function(qt_internal_collect_module_headers out_var target)
set(${out_var}_public "") set(${out_var}_public "")
set(${out_var}_private "") set(${out_var}_private "")
set(${out_var}_qpa "") set(${out_var}_qpa "")
set(${out_var}_all "")
qt_internal_get_target_sources(sources ${target}) qt_internal_get_target_sources(sources ${target})
@ -1203,6 +1217,7 @@ function(qt_internal_collect_module_headers out_var target)
if(NOT file_name MATCHES ".+\\.h$") if(NOT file_name MATCHES ".+\\.h$")
continue() continue()
endif() endif()
get_source_file_property(is_generated "${file_path}" GENERATED)
get_filename_component(file_path "${file_path}" ABSOLUTE) get_filename_component(file_path "${file_path}" ABSOLUTE)
get_filename_component(file_path "${file_path}" REALPATH) get_filename_component(file_path "${file_path}" REALPATH)
list(APPEND ${out_var}_all "${file_path}") list(APPEND ${out_var}_all "${file_path}")
@ -1213,6 +1228,9 @@ function(qt_internal_collect_module_headers out_var target)
elseif(NOT public_filter OR file_name MATCHES "${public_filter}") elseif(NOT public_filter OR file_name MATCHES "${public_filter}")
list(APPEND ${out_var}_public "${file_path}") list(APPEND ${out_var}_public "${file_path}")
endif() endif()
if(is_generated)
list(APPEND ${out_var}_generated "${file_path}")
endif()
endforeach() endforeach()
set(header_types public private qpa) set(header_types public private qpa)
@ -1226,6 +1244,8 @@ function(qt_internal_collect_module_headers out_var target)
set(${out_var}_${header_type} "${${out_var}_${header_type}}" PARENT_SCOPE) set(${out_var}_${header_type} "${${out_var}_${header_type}}" PARENT_SCOPE)
endforeach() endforeach()
set(${out_var}_all "${${out_var}_all}" PARENT_SCOPE)
set(${out_var}_generated "${${out_var}_generated}" PARENT_SCOPE)
if(has_header_types_properties) if(has_header_types_properties)
set_target_properties(${target} PROPERTIES ${has_header_types_properties}) set_target_properties(${target} PROPERTIES ${has_header_types_properties})

View File

@ -276,6 +276,8 @@ function(qt_internal_add_plugin target)
) )
endif() endif()
endif() endif()
qt_internal_add_autogen_sync_header_dependencies(${target} ${qt_module_target})
endif() endif()
# Change the configuration file install location for qml plugins into the Qml package location. # Change the configuration file install location for qml plugins into the Qml package location.

View File

@ -1,8 +1,9 @@
# Copyright (C) 2022 The Qt Company Ltd. # Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause # SPDX-License-Identifier: BSD-3-Clause
function(qt_internal_write_depends_file target module_include_name) function(qt_internal_write_depends_file target)
set(outfile "${QT_BUILD_DIR}/include/${module_include_name}/${module_include_name}Depends") get_target_property(module_depends_header ${target} _qt_module_depends_header)
set(outfile "${module_depends_header}")
set(contents "/* This file was generated by cmake with the info from ${target} target. */\n") set(contents "/* This file was generated by cmake with the info from ${target} target. */\n")
string(APPEND contents "#ifdef __cplusplus /* create empty PCH in C mode */\n") string(APPEND contents "#ifdef __cplusplus /* create empty PCH in C mode */\n")
foreach (m ${ARGN}) foreach (m ${ARGN})
@ -249,8 +250,7 @@ function(qt_internal_create_module_depends_file target)
get_target_property(hasModuleHeaders "${target}" _qt_module_has_headers) get_target_property(hasModuleHeaders "${target}" _qt_module_has_headers)
if (${hasModuleHeaders}) if (${hasModuleHeaders})
get_target_property(module_include_name "${target}" _qt_module_include_name) qt_internal_write_depends_file(${target} ${qtdeps})
qt_internal_write_depends_file(${target} ${module_include_name} ${qtdeps})
endif() endif()
if(third_party_deps OR main_module_tool_deps OR target_deps) if(third_party_deps OR main_module_tool_deps OR target_deps)

View File

@ -206,3 +206,269 @@ function(qt_compute_injection_forwarding_header target)
string(APPEND ${arg_OUT_VAR} " ${relpath}:${fwd}") string(APPEND ${arg_OUT_VAR} " ${relpath}:${fwd}")
set(${arg_OUT_VAR} ${${arg_OUT_VAR}} PARENT_SCOPE) set(${arg_OUT_VAR} ${${arg_OUT_VAR}} PARENT_SCOPE)
endfunction() endfunction()
# The function generates the Qt module header structure in build directory and creates install
# rules. Apart the lists of header files the function takes into account
# QT_REPO_PUBLIC_NAMESPACE_REGEX cache variable, that can be set by repository in .cmake.conf file.
# The variable tells the syncqt program, what namespaces are treated as public. Symbols in public
# namespaces are considered when generating CaMeL case header files.
function(qt_internal_target_sync_headers target module_headers module_headers_generated)
if(NOT TARGET ${QT_CMAKE_EXPORT_NAMESPACE}::syncqt)
message(FATAL_ERROR "${QT_CMAKE_EXPORT_NAMESPACE}::syncqt is not a target.")
endif()
get_target_property(has_headers ${target} _qt_module_has_headers)
if(NOT has_headers)
return()
endif()
qt_internal_module_info(module "${target}")
get_target_property(sync_source_directory ${target} _qt_sync_source_directory)
set(syncqt_timestamp "${CMAKE_CURRENT_BINARY_DIR}/${target}_syncqt_timestamp")
set(syncqt_outputs "${syncqt_timestamp}")
set(is_interface_lib FALSE)
get_target_property(type ${target} TYPE)
if(type STREQUAL "INTERFACE_LIBRARY")
set(is_interface_lib TRUE)
endif()
set(version_script_private_content_file "")
if(NOT is_interface_lib)
list(APPEND syncqt_outputs
"${module_build_interface_include_dir}/${module}Version"
"${module_build_interface_include_dir}/qt${module_lower}version.h")
if(TEST_ld_version_script)
set(version_script_private_content_file
"${CMAKE_CURRENT_BINARY_DIR}/${target}.version.private_content")
set(version_script_args
"-versionScript" "${version_script_private_content_file}")
list(APPEND syncqt_outputs "${version_script_private_content_file}")
qt_internal_add_linker_version_script(${target}
PRIVATE_CONTENT_FILE "${version_script_private_content_file}")
endif()
endif()
# Check for _qt_module_is_3rdparty_header_library flag to detect non-Qt modules and
# indicate this to syncqt.
get_target_property(is_3rd_party_library ${target} _qt_module_is_3rdparty_header_library)
set(non_qt_module_argument "")
if(is_3rd_party_library)
set(non_qt_module_argument "-nonQt")
else()
list(APPEND syncqt_outputs "${module_build_interface_include_dir}/${module}")
if(QT_FEATURE_headersclean)
list(APPEND syncqt_outputs
"${CMAKE_CURRENT_BINARY_DIR}/${module}_header_check_exceptions")
endif()
endif()
set(is_framework FALSE)
if(NOT is_interface_lib)
get_target_property(is_framework ${target} FRAMEWORK)
if(is_framework)
qt_internal_get_framework_info(fw ${target})
get_target_property(fw_output_base_dir ${target} LIBRARY_OUTPUT_DIRECTORY)
set(framework_args "-framework"
"-frameworkIncludeDir" "${fw_output_base_dir}/${fw_versioned_header_dir}"
)
endif()
endif()
qt_internal_get_qt_all_known_modules(known_modules)
get_target_property(is_internal_module ${target} _qt_is_internal_module)
set(internal_module_argument "")
if(is_internal_module)
set(internal_module_argument "-internal")
endif()
get_target_property(qpa_filter_regex ${target} _qt_module_qpa_headers_filter_regex)
get_target_property(private_filter_regex ${target} _qt_module_private_headers_filter_regex)
# We need to use the real paths since otherwise it may lead to the invalid work of the
# std::filesystem API
get_filename_component(source_dir_real "${sync_source_directory}" REALPATH)
get_filename_component(binary_dir_real "${CMAKE_CURRENT_BINARY_DIR}" REALPATH)
if(QT_REPO_PUBLIC_NAMESPACE_REGEX)
set(public_namespaces_filter -publicNamespaceFilter "${QT_REPO_PUBLIC_NAMESPACE_REGEX}")
endif()
if(qpa_filter_regex)
set(qpa_filter_argument
-qpaHeadersFilter "${qpa_filter_regex}"
)
endif()
set(common_syncqt_arguments
-module "${module}"
-sourceDir "${source_dir_real}"
-binaryDir "${binary_dir_real}"
-privateHeadersFilter "${private_filter_regex}"
-includeDir "${module_build_interface_include_dir}"
-privateIncludeDir "${module_build_interface_private_include_dir}"
-qpaIncludeDir "${module_build_interface_qpa_include_dir}"
${qpa_filter_argument}
${public_namespaces_filter}
${non_qt_module_argument}
${internal_module_argument}
)
if(QT_INTERNAL_ENABLE_SYNCQT_DEBUG_OUTPUT)
list(APPEND common_syncqt_arguments -debug)
endif()
if(is_framework)
list(REMOVE_ITEM module_headers "${CMAKE_CURRENT_BINARY_DIR}/${target}_fake_header.h")
endif()
# Filter the generated ui_ header files and header files located in the 'doc/' subdirectory.
list(FILTER module_headers EXCLUDE REGEX
"(.+/(ui_)[^/]+\\.h|${CMAKE_CURRENT_SOURCE_DIR}(/.+)?/doc/+\\.h)")
set(module_headers_rsp "${binary_dir_real}/module_headers")
list(JOIN module_headers "\n" module_headers_string)
qt_configure_file_v2(OUTPUT "${module_headers_rsp}" CONTENT "${module_headers_string}")
set(module_headers_generated_rsp "${binary_dir_real}/module_headers_generated")
list(JOIN module_headers_generated "\n" module_headers_generated_string)
qt_configure_file_v2(OUTPUT "${module_headers_generated_rsp}" CONTENT
"${module_headers_generated_string}")
set(syncqt_staging_dir "${module_build_interface_include_dir}/.syncqt_staging")
add_custom_command(
OUTPUT
${syncqt_outputs}
COMMAND
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
${common_syncqt_arguments}
-headers "@${module_headers_rsp}"
-generatedHeaders "@${module_headers_generated_rsp}"
-stagingDir "${syncqt_staging_dir}"
-knownModules ${known_modules}
${framework_args}
${version_script_args}
COMMAND
${CMAKE_COMMAND} -E touch "${syncqt_timestamp}"
DEPENDS
${module_headers_rsp}
${module_headers_generated_rsp}
${module_headers}
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
COMMENT
"Running syncqt.cpp for module: ${module}"
VERBATIM
)
add_custom_target(${target}_sync_headers
DEPENDS
${syncqt_outputs}
)
add_dependencies(sync_headers ${target}_sync_headers)
# This target is required when building docs, to make all header files and their aliases
# available for qdoc.
# ${target}_sync_headers is added as dependency to make sure that
# ${target}_sync_all_public_headers is running after ${target}_sync_headers, when building docs.
add_custom_target(${target}_sync_all_public_headers
COMMAND
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
${common_syncqt_arguments}
-all
DEPENDS
${module_headers}
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
${target}_sync_headers
VERBATIM
)
if(NOT TARGET sync_all_public_headers)
add_custom_target(sync_all_public_headers)
endif()
add_dependencies(sync_all_public_headers ${target}_sync_all_public_headers)
if(NOT is_3rd_party_library AND NOT is_framework)
# Install all the CaMeL style aliases of header files from the staging directory in one rule
qt_install(DIRECTORY "${syncqt_staging_dir}/"
DESTINATION "${module_install_interface_include_dir}"
)
endif()
if(NOT is_interface_lib)
set_property(TARGET ${target}
APPEND PROPERTY AUTOGEN_TARGET_DEPENDS "${target}_sync_headers")
endif()
add_dependencies(${target} "${target}_sync_headers")
get_target_property(private_module_target ${target} _qt_private_module_target_name)
if(private_module_target)
add_dependencies(${private_module_target} "${target}_sync_headers")
endif()
# Run sync Qt first time at configure step to make all header files available for the code model
# of IDEs.
get_property(synced_modules GLOBAL PROPERTY _qt_synced_modules)
if(NOT "${module}" IN_LIST synced_modules)
message(STATUS "Running syncqt.cpp for module: ${module}")
get_target_property(syncqt_location ${QT_CMAKE_EXPORT_NAMESPACE}::syncqt LOCATION)
execute_process(
COMMAND
${syncqt_location}
${common_syncqt_arguments}
-headers "@${module_headers_rsp}"
-generatedHeaders "@${module_headers_generated_rsp}"
-stagingDir "${syncqt_staging_dir}"
-knownModules ${known_modules}
${framework_args}
RESULT_VARIABLE syncqt_result
OUTPUT_VARIABLE syncqt_output
ERROR_VARIABLE syncqt_output
)
if(NOT syncqt_result EQUAL 0)
message(FATAL_ERROR
"Unable to execute syncqt.cpp for module ${target}: ${syncqt_output}")
endif()
set_property(GLOBAL APPEND PROPERTY _qt_synced_modules ${module})
endif()
endfunction()
function(qt_internal_collect_sync_header_dependencies out_var skip_non_existing)
if(NOT QT_USE_SYNCQT_CPP)
set(${out_var} "" PARENT_SCOPE)
return()
endif()
list(LENGTH ARGN sync_headers_target_count)
if(sync_headers_target_count EQUAL 0)
message(FATAL_ERROR "Invalid use of qt_internal_collect_sync_header_dependencies,"
" dependencies are not specified")
endif()
set(${out_var} "")
foreach(sync_headers_target IN LISTS ARGN)
set(sync_headers_target "${sync_headers_target}_sync_headers")
if(NOT skip_non_existing OR TARGET ${sync_headers_target})
list(APPEND ${out_var} ${sync_headers_target})
endif()
endforeach()
list(REMOVE_DUPLICATES ${out_var})
set(${out_var} "${${out_var}}" PARENT_SCOPE)
endfunction()
function(qt_internal_add_sync_header_dependencies target)
qt_internal_collect_sync_header_dependencies(sync_headers_targets FALSE ${ARGN})
if(sync_headers_targets)
add_dependencies(${target} ${sync_headers_targets})
endif()
endfunction()
function(qt_internal_add_autogen_sync_header_dependencies target)
qt_internal_collect_sync_header_dependencies(sync_headers_targets TRUE ${ARGN})
foreach(sync_headers_target IN LISTS sync_headers_targets)
set_property(TARGET ${target} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS
"${sync_headers_target}")
endforeach()
endfunction()

View File

@ -634,10 +634,11 @@ function(qt_internal_add_configure_time_tool target_name)
set(extra_args "INSTALL_DIRECTORY" "${install_dir}") set(extra_args "INSTALL_DIRECTORY" "${install_dir}")
endif() endif()
string(REPLACE "\\\;" "\\\\\\\;" unparsed_arguments "${arg_UNPARSED_ARGUMENTS}")
qt_internal_add_configure_time_executable(${target_name} qt_internal_add_configure_time_executable(${target_name}
OUTPUT_NAME ${name} OUTPUT_NAME ${name}
${extra_args} ${extra_args}
${arg_UNPARSED_ARGUMENTS} ${unparsed_arguments}
) )
if(NOT arg_NO_INSTALL AND arg_TOOLS_TARGET) if(NOT arg_NO_INSTALL AND arg_TOOLS_TARGET)

View File

@ -15,6 +15,9 @@ qt_add_library(QtLibraryInfo OBJECT
propertyprinter.cpp propertyprinter.h propertyprinter.cpp propertyprinter.h
qmakelibraryinfo.cpp qmakelibraryinfo.h qmakelibraryinfo.cpp qmakelibraryinfo.h
) )
qt_internal_add_sync_header_dependencies(QtLibraryInfo Core)
set_target_properties(QtLibraryInfo PROPERTIES set_target_properties(QtLibraryInfo PROPERTIES
COMPILE_OPTIONS $<TARGET_PROPERTY:Qt::Core,INTERFACE_COMPILE_OPTIONS> COMPILE_OPTIONS $<TARGET_PROPERTY:Qt::Core,INTERFACE_COMPILE_OPTIONS>
COMPILE_DEFINITIONS $<TARGET_PROPERTY:Qt::Core,INTERFACE_COMPILE_DEFINITIONS> COMPILE_DEFINITIONS $<TARGET_PROPERTY:Qt::Core,INTERFACE_COMPILE_DEFINITIONS>

View File

@ -70,6 +70,8 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/harfbuzz> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/harfbuzz>
) )
qt_internal_add_sync_header_dependencies(BundledHarfbuzz Core)
# GHS compiler doesn't support the __restrict keyword # GHS compiler doesn't support the __restrict keyword
if(INTEGRITY) if(INTEGRITY)
target_compile_definitions(BundledHarfbuzz PRIVATE __restrict=) target_compile_definitions(BundledHarfbuzz PRIVATE __restrict=)

View File

@ -34,6 +34,8 @@ qt_internal_add_3rdparty_library(BundledZLIB
$<TARGET_PROPERTY:Core,INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:Core,INCLUDE_DIRECTORIES>
) )
qt_internal_add_sync_header_dependencies(BundledZLIB Core)
qt_disable_warnings(BundledZLIB) qt_disable_warnings(BundledZLIB)
qt_set_symbol_visibility_hidden(BundledZLIB) qt_set_symbol_visibility_hidden(BundledZLIB)

View File

@ -15,6 +15,8 @@ if(QT_FEATURE_gui)
qt_feature_evaluate_features("${CMAKE_CURRENT_SOURCE_DIR}/gui/configure.cmake") qt_feature_evaluate_features("${CMAKE_CURRENT_SOURCE_DIR}/gui/configure.cmake")
endif() endif()
add_subdirectory(tools/syncqt)
function(find_or_build_bootstrap_names) function(find_or_build_bootstrap_names)
if (QT_WILL_BUILD_TOOLS) if (QT_WILL_BUILD_TOOLS)
add_subdirectory(tools/bootstrap) # bootstrap library add_subdirectory(tools/bootstrap) # bootstrap library

View File

@ -377,10 +377,15 @@ endif()
# additional json files. # additional json files.
qt6_extract_metatypes(Core ${core_metatype_args}) qt6_extract_metatypes(Core ${core_metatype_args})
set_property(TARGET Core APPEND PROPERTY target_sources(Core PRIVATE
PUBLIC_HEADER "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig.h") "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig.h"
set_property(TARGET Core APPEND PROPERTY "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig_p.h"
PRIVATE_HEADER "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig_p.h") )
set_source_files_properties(
"${CMAKE_CURRENT_BINARY_DIR}/global/qconfig.h"
"${CMAKE_CURRENT_BINARY_DIR}/global/qconfig_p.h"
PROPERTIES GENERATED TRUE
)
# Find ELF interpreter and define a macro for that: # Find ELF interpreter and define a macro for that:
if ((LINUX OR HURD) AND NOT CMAKE_CROSSCOMPILING AND BUILD_SHARED_LIBS) if ((LINUX OR HURD) AND NOT CMAKE_CROSSCOMPILING AND BUILD_SHARED_LIBS)

View File

@ -5,7 +5,10 @@
#define QTCONFIGMACROS_H #define QTCONFIGMACROS_H
#ifdef QT_BOOTSTRAPPED #ifdef QT_BOOTSTRAPPED
#include <QtCore/qconfig-bootstrapped.h> // qconfig-bootstrapped.h is not supposed to be a part of the synced header files. So we find it by
// the include path specified for Bootstrap library in the source tree instead of the build tree as
// it's done for regular header files.
#include "qconfig-bootstrapped.h"
#else #else
#include <QtCore/qconfig.h> #include <QtCore/qconfig.h>
#include <QtCore/qtcore-config.h> #include <QtCore/qtcore-config.h>

View File

@ -10,7 +10,10 @@
#endif #endif
#ifdef QT_BOOTSTRAPPED #ifdef QT_BOOTSTRAPPED
#include <QtCore/qconfig-bootstrapped.h> // qconfig-bootstrapped.h is not supposed to be a part of the synced header files. So we find it by
// the include path specified for Bootstrap library in the source tree instead of the build tree as
// it's done for regular header files.
#include "qconfig-bootstrapped.h"
#else #else
#include <QtCore/qconfig.h> #include <QtCore/qconfig.h>
#include <QtCore/qtcore-config.h> #include <QtCore/qtcore-config.h>

View File

@ -109,6 +109,8 @@ if(WIN32)
target_compile_definitions(EntryPointPrivate INTERFACE QT_NEEDS_QMAIN) target_compile_definitions(EntryPointPrivate INTERFACE QT_NEEDS_QMAIN)
qt_internal_extend_target(EntryPointImplementation DEFINES QT_NEEDS_QMAIN) qt_internal_extend_target(EntryPointImplementation DEFINES QT_NEEDS_QMAIN)
endif() endif()
qt_internal_add_sync_header_dependencies(EntryPointImplementation Core)
endif() endif()
if(CMAKE_SYSTEM_NAME STREQUAL "iOS") if(CMAKE_SYSTEM_NAME STREQUAL "iOS")

View File

@ -887,7 +887,6 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_filesystemmodel
qt_internal_extend_target(Gui CONDITION QT_FEATURE_vulkan qt_internal_extend_target(Gui CONDITION QT_FEATURE_vulkan
SOURCES SOURCES
rhi/qrhivulkan.cpp rhi/qrhivulkan_p.h rhi/qrhivulkan.cpp rhi/qrhivulkan_p.h
rhi/qrhivulkan_p_p.h
rhi/qrhivulkanext_p.h rhi/qrhivulkanext_p.h
vulkan/qbasicvulkanplatforminstance.cpp vulkan/qbasicvulkanplatforminstance_p.h vulkan/qbasicvulkanplatforminstance.cpp vulkan/qbasicvulkanplatforminstance_p.h
vulkan/qplatformvulkaninstance.cpp vulkan/qplatformvulkaninstance.h vulkan/qplatformvulkaninstance.cpp vulkan/qplatformvulkaninstance.h

View File

@ -46,6 +46,8 @@ qt_internal_add_module(EglFSDeviceIntegrationPrivate
Qt::FbSupportPrivate Qt::FbSupportPrivate
Qt::GuiPrivate Qt::GuiPrivate
EGL::EGL # special case EGL::EGL # special case
HEADER_SYNC_SOURCE_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}/api"
) )
#### Keys ignored in scope 2:.:.:eglfsdeviceintegration.pro:<TRUE>: #### Keys ignored in scope 2:.:.:eglfsdeviceintegration.pro:<TRUE>:

View File

@ -11,6 +11,9 @@
# The bootstrap library has a few manual tweaks compared to other # The bootstrap library has a few manual tweaks compared to other
# libraries. # libraries.
qt_add_library(Bootstrap STATIC) qt_add_library(Bootstrap STATIC)
qt_internal_add_sync_header_dependencies(Bootstrap Core)
# special case end # special case end
qt_internal_extend_target(Bootstrap qt_internal_extend_target(Bootstrap
SOURCES SOURCES
@ -104,6 +107,7 @@ qt_internal_extend_target(Bootstrap
../../3rdparty/tinycbor/src ../../3rdparty/tinycbor/src
PUBLIC_INCLUDE_DIRECTORIES # special case PUBLIC_INCLUDE_DIRECTORIES # special case
$<TARGET_PROPERTY:Core,INCLUDE_DIRECTORIES> # special case $<TARGET_PROPERTY:Core,INCLUDE_DIRECTORIES> # special case
../../corelib/global
PUBLIC_LIBRARIES # special case PUBLIC_LIBRARIES # special case
Qt::Platform # special case Qt::Platform # special case
) )

View File

@ -0,0 +1,30 @@
# The tool should be optimized for maximum performance when working.
qt_internal_get_optimize_full_flags(optimize_full_flags)
set(compile_definitions
QT_VERSION_STR="${PROJECT_VERSION}"
QT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
QT_VERSION_MINOR=${PROJECT_VERSION_MINOR}
QT_VERSION_PATCH=${PROJECT_VERSION_PATCH}
QT_NAMESPACE="${QT_NAMESPACE}"
)
if(CMAKE_OSX_ARCHITECTURES)
set(osx_architectures "-DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}")
endif()
qt_get_tool_target_name(target_name syncqt)
qt_internal_add_configure_time_tool(${target_name}
DEFINES ${compile_definitions}
COMPILE_OPTIONS ${optimize_full_flags}
TOOLS_TARGET Core
INSTALL_DIRECTORY "${INSTALL_LIBEXECDIR}"
CMAKE_FLAGS
-DCMAKE_CXX_STANDARD_REQUIRED:BOOL=TRUE
-DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD}
# std::filesystem API is only available in macOS 10.15+
-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.15
"${osx_architectures}"
SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
CONFIG RelWithDebInfo
)

1567
src/tools/syncqt/main.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -145,6 +145,12 @@ if(IOS)
return() return()
endif() endif()
set(is_qt_build_platform TRUE)
# macOS versions less than 10.15 are not supported for building Qt.
if(CMAKE_HOST_APPLE AND CMAKE_HOST_SYSTEM_VERSION VERSION_LESS "19.0.0")
set(is_qt_build_platform FALSE)
endif()
_qt_internal_test_expect_pass(test_umbrella_config) _qt_internal_test_expect_pass(test_umbrella_config)
_qt_internal_test_expect_pass(test_wrap_cpp_and_resources) _qt_internal_test_expect_pass(test_wrap_cpp_and_resources)
if (NOT NO_WIDGETS) if (NOT NO_WIDGETS)
@ -274,21 +280,23 @@ elseif(QT6_INSTALL_BINS)
endif() endif()
# Test building and installing a few dummy Qt modules and plugins. # Test building and installing a few dummy Qt modules and plugins.
set(mockplugins_test_args "") if(is_qt_build_platform)
if(NOT QT_FEATURE_no_prefix) set(mockplugins_test_args "")
list(APPEND mockplugins_test_args if(NOT QT_FEATURE_no_prefix)
BINARY "${CMAKE_COMMAND}" list(APPEND mockplugins_test_args
BINARY_ARGS BINARY "${CMAKE_COMMAND}"
"-DQT_BUILD_DIR=${CMAKE_CURRENT_BINARY_DIR}/mockplugins" BINARY_ARGS
-P "${qt_install_prefix}/${qt_install_bin_dir}/qt-cmake-private-install.cmake" "-DQT_BUILD_DIR=${CMAKE_CURRENT_BINARY_DIR}/mockplugins"
) -P "${qt_install_prefix}/${qt_install_bin_dir}/qt-cmake-private-install.cmake"
endif() )
_qt_internal_test_expect_pass(mockplugins ${mockplugins_test_args}) endif()
set_tests_properties(mockplugins PROPERTIES FIXTURES_SETUP build_mockplugins) _qt_internal_test_expect_pass(mockplugins ${mockplugins_test_args})
set_tests_properties(mockplugins PROPERTIES FIXTURES_SETUP build_mockplugins)
# Test importing the plugins built in the project above. # Test importing the plugins built in the project above.
_qt_internal_test_expect_pass(test_import_plugins BINARY ${CMAKE_CTEST_COMMAND} BINARY_ARGS -V) _qt_internal_test_expect_pass(test_import_plugins BINARY ${CMAKE_CTEST_COMMAND} BINARY_ARGS -V)
set_tests_properties(test_import_plugins PROPERTIES FIXTURES_REQUIRED build_mockplugins) set_tests_properties(test_import_plugins PROPERTIES FIXTURES_REQUIRED build_mockplugins)
endif()
_qt_internal_test_expect_pass(test_versionless_targets) _qt_internal_test_expect_pass(test_versionless_targets)
@ -307,11 +315,13 @@ include(test_plugin_shared_static_flavor.cmake)
_qt_internal_test_expect_pass(tst_qaddpreroutine _qt_internal_test_expect_pass(tst_qaddpreroutine
BINARY tst_qaddpreroutine) BINARY tst_qaddpreroutine)
_qt_internal_test_expect_pass(test_static_resources if(is_qt_build_platform)
BINARY "${CMAKE_CTEST_COMMAND}" _qt_internal_test_expect_pass(test_static_resources
BINARY_ARGS "-V") BINARY "${CMAKE_CTEST_COMMAND}"
BINARY_ARGS "-V")
_qt_internal_test_expect_pass(test_generating_cpp_exports) _qt_internal_test_expect_pass(test_generating_cpp_exports)
endif()
_qt_internal_test_expect_pass(test_qt_extract_metatypes) _qt_internal_test_expect_pass(test_qt_extract_metatypes)

View File

@ -1 +1,3 @@
set(QT_REPO_MODULE_VERSION "6.5.0") set(QT_REPO_MODULE_VERSION "6.5.0")
set(QT_USE_SYNCQT_CPP TRUE)

View File

@ -4,6 +4,7 @@
qt_internal_add_module(MockPlugins1 qt_internal_add_module(MockPlugins1
PLUGIN_TYPES mockplugin PLUGIN_TYPES mockplugin
SOURCES SOURCES
qmockplugin.h
fake.cpp fake.cpp
LIBRARIES LIBRARIES
Qt::CorePrivate Qt::CorePrivate

View File

@ -4,6 +4,7 @@
qt_internal_add_module(MockPlugins3 qt_internal_add_module(MockPlugins3
PLUGIN_TYPES mockauxplugin PLUGIN_TYPES mockauxplugin
SOURCES SOURCES
qmockauxplugin.h
fake.cpp fake.cpp
LIBRARIES LIBRARIES
Qt::CorePrivate Qt::CorePrivate