qt5base-lts/cmake/QtSyncQtHelpers.cmake
Alexandru Croitor 44cce1a2ea CMake: Split QtBuild.cmake into smaller files
QtBuild.cmake is huge. Split it.

Move module, plugin, tools, executables and test related functions out
of QtBuild.cmake into separate files.
Do the same for many other things too.

An additional requirement is that all the new Helpers files only
define functions and macros.
No global variable definitions are allowed, nor execution of commands
with side effects.

Some notes:
qt_install_qml_files is removed because it's dead code.

Some functions still need to be figured out, because they are
interspersed and depend on various global state assignments.

Task-number: QTBUG-86035
Change-Id: I21d79ff02eef923c202eb1000422888727cb0e2c
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
2020-08-14 13:17:11 +02:00

202 lines
9.5 KiB
CMake

function(qt_ensure_perl)
if(DEFINED HOST_PERL)
return()
endif()
find_program(HOST_PERL "perl" DOC "Perl binary")
if (NOT HOST_PERL)
message(FATAL_ERROR "Perl needs to be available to build Qt.")
endif()
endfunction()
function(qt_ensure_sync_qt)
qt_ensure_perl()
if(DEFINED QT_SYNCQT)
return()
endif()
# When building qtbase, use the source syncqt, otherwise use the installed one.
set(SYNCQT_FROM_SOURCE "${QtBase_SOURCE_DIR}/bin/syncqt.pl")
if(NOT ("${QtBase_SOURCE_DIR}" STREQUAL "") AND EXISTS "${SYNCQT_FROM_SOURCE}")
set(QT_SYNCQT "${SYNCQT_FROM_SOURCE}" CACHE FILEPATH "syncqt script")
message(STATUS "Using source syncqt found at: ${QT_SYNCQT}")
qt_path_join(syncqt_install_dir ${QT_INSTALL_DIR} ${INSTALL_LIBEXECDIR})
qt_copy_or_install(PROGRAMS "${SYNCQT_FROM_SOURCE}"
DESTINATION "${syncqt_install_dir}")
qt_path_join(syncqt_install_dir ${QT_INSTALL_DIR} ${INSTALL_BINDIR})
qt_copy_or_install(PROGRAMS "${SYNCQT_FROM_SOURCE}"
DESTINATION "${syncqt_install_dir}")
elseif(QT_HOST_PATH)
get_filename_component(syncqt_absolute_path
"${QT_HOST_PATH}/${INSTALL_LIBEXECDIR}/syncqt.pl"
ABSOLUTE)
set(QT_SYNCQT "${syncqt_absolute_path}" CACHE FILEPATH "syncqt script")
message(STATUS "Using host syncqt found at: ${QT_SYNCQT}")
else()
get_filename_component(syncqt_absolute_path
"${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_LIBEXECDIR}/syncqt.pl"
ABSOLUTE)
set(QT_SYNCQT "${syncqt_absolute_path}" CACHE FILEPATH "syncqt script")
message(STATUS "Using installed syncqt found at: ${QT_SYNCQT}")
endif()
endfunction()
function(qt_install_injections target build_dir install_dir)
set(injections ${ARGN})
set(module "Qt${target}")
get_target_property(target_type ${target} TYPE)
if (target_type STREQUAL "INTERFACE_LIBRARY")
set(is_framework FALSE)
else()
get_target_property(is_framework ${target} FRAMEWORK)
endif()
# examples:
# SYNCQT.INJECTIONS = src/corelib/global/qconfig.h:qconfig.h:QtConfig src/corelib/global/qconfig_p.h:5.12.0/QtCore/private/qconfig_p.h
# SYNCQT.INJECTIONS = src/gui/vulkan/qvulkanfunctions.h:^qvulkanfunctions.h:QVulkanFunctions:QVulkanDeviceFunctions src/gui/vulkan/qvulkanfunctions_p.h:^5.12.0/QtGui/private/qvulkanfunctions_p.h
# The are 3 parts to the assignment, divded by colons ':'.
# The first part contains a path to a generated file in a build folder.
# The second part contains the file name that the forwarding header should have, which points
# to the file in the first part.
# The third part contains multiple UpperCaseFileNames that should be forwarding headers to the
# header specified in the second part.
separate_arguments(injections UNIX_COMMAND "${injections}")
foreach(injection ${injections})
string(REPLACE ":" ";" injection ${injection})
# Part 1.
list(GET injection 0 file)
# Part 2.
list(GET injection 1 destination)
string(REGEX REPLACE "^\\^" "" destination "${destination}")
list(REMOVE_AT injection 0 1)
# Part 3.
set(fwd_hdrs ${injection})
get_filename_component(destinationdir ${destination} DIRECTORY)
get_filename_component(destinationname ${destination} NAME)
get_filename_component(original_file_name ${file} NAME)
# This describes a concrete example for easier comprehension:
# A file 'qtqml-config.h' is generated by qt_internal_feature_write_file into
# ${qtdeclarative_build_dir}/src/{module}/qtqml-config.h (part 1).
#
# Generate a lower case forwarding header (part 2) 'qtqml-config.h' at the following
# location:
# ${some_prefix}/include/${module}/qtqml-config.h.
#
# Inside this file, we #include the originally generated file,
# ${qtdeclarative_build_dir}/src/{module}/qtqml-config.h.
#
# ${some_prefix}'s value depends on the build type.
# If doing a prefix build, it should point to
# ${current_repo_build_dir} which is ${qtdeclarative_build_dir}.
# If doing a non-prefix build, it should point to
# ${qtbase_build_dir}.
#
# In the code below, ${some_prefix} == ${build_dir}.
set(lower_case_forwarding_header_path "${build_dir}/include/${module}")
if(destinationdir)
string(APPEND lower_case_forwarding_header_path "/${destinationdir}")
endif()
set(current_repo_build_dir "${PROJECT_BINARY_DIR}")
file(RELATIVE_PATH relpath
"${lower_case_forwarding_header_path}"
"${current_repo_build_dir}/${file}")
set(main_contents "#include \"${relpath}\"")
qt_configure_file(OUTPUT "${lower_case_forwarding_header_path}/${original_file_name}"
CONTENT "${main_contents}")
if(is_framework)
if(file MATCHES "_p\\.h$")
set(header_type PRIVATE)
else()
set(header_type PUBLIC)
endif()
qt_copy_framework_headers(${target} ${header_type}
${current_repo_build_dir}/${file})
else()
# Copy the actual injected (generated) header file (not the just created forwarding one)
# to its install location when doing a prefix build. In an non-prefix build, the qt_install
# will be a no-op.
qt_path_join(install_destination
${install_dir} ${INSTALL_INCLUDEDIR} ${module} ${destinationdir})
qt_install(FILES ${current_repo_build_dir}/${file}
DESTINATION ${install_destination}
RENAME ${destinationname} OPTIONAL)
endif()
# Generate UpperCaseNamed forwarding headers (part 3).
foreach(fwd_hdr ${fwd_hdrs})
set(upper_case_forwarding_header_path "include/${module}")
if(destinationdir)
string(APPEND upper_case_forwarding_header_path "/${destinationdir}")
endif()
# Generate upper case forwarding header like QVulkanFunctions or QtConfig.
qt_configure_file(OUTPUT "${build_dir}/${upper_case_forwarding_header_path}/${fwd_hdr}"
CONTENT "#include \"${destinationname}\"\n")
if(is_framework)
# Copy the forwarding header to the framework's Headers directory.
qt_copy_framework_headers(${target} PUBLIC
"${build_dir}/${upper_case_forwarding_header_path}/${fwd_hdr}")
else()
# Install the forwarding header.
qt_path_join(install_destination "${install_dir}" "${INSTALL_INCLUDEDIR}" ${module})
qt_install(FILES "${build_dir}/${upper_case_forwarding_header_path}/${fwd_hdr}"
DESTINATION ${install_destination} OPTIONAL)
endif()
endforeach()
endforeach()
endfunction()
function(qt_read_headers_pri module_include_dir resultVarPrefix)
file(STRINGS "${module_include_dir}/headers.pri" headers_pri_contents)
foreach(line ${headers_pri_contents})
if("${line}" MATCHES "SYNCQT.HEADER_FILES = (.*)")
set(public_module_headers "${CMAKE_MATCH_1}")
separate_arguments(public_module_headers UNIX_COMMAND "${public_module_headers}")
elseif("${line}" MATCHES "SYNCQT.PRIVATE_HEADER_FILES = (.*)")
set(private_module_headers "${CMAKE_MATCH_1}")
separate_arguments(private_module_headers UNIX_COMMAND "${private_module_headers}")
elseif("${line}" MATCHES "SYNCQT.GENERATED_HEADER_FILES = (.*)")
set(generated_module_headers "${CMAKE_MATCH_1}")
separate_arguments(generated_module_headers UNIX_COMMAND "${generated_module_headers}")
foreach(generated_header ${generated_module_headers})
list(APPEND public_module_headers "${module_include_dir}/${generated_header}")
endforeach()
elseif("${line}" MATCHES "SYNCQT.INJECTIONS = (.*)")
set(injections "${CMAKE_MATCH_1}")
elseif("${line}" MATCHES "SYNCQT.([A-Z_]+)_HEADER_FILES = (.+)")
set(prefix "${CMAKE_MATCH_1}")
string(TOLOWER "${prefix}" prefix)
set(entries "${CMAKE_MATCH_2}")
separate_arguments(entries UNIX_COMMAND "${entries}")
set("${resultVarPrefix}_${prefix}" "${entries}" PARENT_SCOPE)
endif()
endforeach()
set(${resultVarPrefix}_public "${public_module_headers}" PARENT_SCOPE)
set(${resultVarPrefix}_private "${private_module_headers}" PARENT_SCOPE)
set(${resultVarPrefix}_injections "${injections}" PARENT_SCOPE)
endfunction()
function(qt_compute_injection_forwarding_header target)
qt_parse_all_arguments(arg "qt_compute_injection_forwarding_header"
"PRIVATE" "SOURCE;OUT_VAR" "" ${ARGN})
qt_internal_module_info(module "${target}")
get_filename_component(file_name "${arg_SOURCE}" NAME)
set(source_absolute_path "${CMAKE_CURRENT_BINARY_DIR}/${arg_SOURCE}")
file(RELATIVE_PATH relpath "${PROJECT_BINARY_DIR}" "${source_absolute_path}")
if (arg_PRIVATE)
set(fwd "${PROJECT_VERSION}/${module}/private/${file_name}")
else()
set(fwd "${file_name}")
endif()
string(APPEND ${arg_OUT_VAR} " ${relpath}:${fwd}")
set(${arg_OUT_VAR} ${${arg_OUT_VAR}} PARENT_SCOPE)
endfunction()