diff options
author | Joerg Bornemann <joerg.bornemann@qt.io> | 2020-06-05 10:10:50 +0200 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@qt.io> | 2020-06-09 21:04:26 +0200 |
commit | 2a767ab4bb7de8c29d2a8365212244ed944e9aeb (patch) | |
tree | d02b1d45bb0bcd7a313baaac8c57a86c999ea658 /cmake | |
parent | d2833a3ce5af725d66ef9338f2a61b766dd3cb2d (diff) |
CMake: Fix libraries in qt_lib_XXX_private.pri files for NMC
qmake_use.prf understands the _DEBUG and _RELEASE suffixes for
QMAKE_LIBS_XXX entries. The CMake configuration "Debug" is considered
for the _DEBUG entries, "Release" and "RelWithDebInfo" for _RELEASE.
The qt_lib_XXX_private.pri files are now generated in multiple steps:
1. The QT_LIBS_XXX information is generated per $<CONFIG> and written to
.cmake files.
2. A preliminary qt_lib_XXX_private.pri file is generated, containing
only configuration-independent data.
3. A custom command runs the QtGenerateLibPri.cmake script that combines
the files from step 1 and 2 into the final qt_lib_XXX_private.pri
file.
The same is done for mkspecs/qmodule.pri.
To be able to trigger custom commands from header modules, which are
interface libraries, we introduce one XXX_timestamp ALL target per
header module that creates a timestamp file. To that XXX_timestamp
target we add the pri file generation target as dependency.
Fixes: QTBUG-84348
Change-Id: I610f279e37feeb7eceb9ef20b3ddfecff8cfbf81
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'cmake')
-rw-r--r-- | cmake/QtBaseGlobalTargets.cmake | 1 | ||||
-rw-r--r-- | cmake/QtBuild.cmake | 113 | ||||
-rw-r--r-- | cmake/QtGenerateLibPri.cmake | 84 |
3 files changed, 167 insertions, 31 deletions
diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index a642b08a10..2496cc0d07 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -311,6 +311,7 @@ qt_copy_or_install(FILES cmake/QtFindWrapConfigExtra.cmake.in cmake/QtFileConfigure.txt.in cmake/QtGenerateExtPri.cmake + cmake/QtGenerateLibPri.cmake cmake/QtPlatformSupport.cmake cmake/QtPlatformAndroid.cmake cmake/QtPostProcess.cmake diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 406b88552d..fa977b1016 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -611,12 +611,13 @@ function(qt_re_escape out_var str) set(${out_var} ${regex} PARENT_SCOPE) endfunction() -# Extracts the 3rdparty libraries for the module ${module_name} in module .pri file format -# and stores the content in ${out_var}. +# Extracts the 3rdparty libraries for the module ${module_name} +# and stores the information in cmake language in +# ${output_root_dir}/$<CONFIG>/${output_file_name}. # # This function "follows" INTERFACE_LIBRARY targets to "real" targets # and collects defines, include dirs and lib dirs on the way. -function(qt_get_qmake_libraries_pri_content out_var module_name) +function(qt_generate_qmake_libraries_pri_content module_name output_root_dir output_file_name) set(content "") # Set up a regular expression that matches all implicit include dirs @@ -665,25 +666,24 @@ function(qt_get_qmake_libraries_pri_content out_var module_name) string(PREPEND lib_incdir "$<FILTER:") string(APPEND lib_incdir ",EXCLUDE,${implicit_include_dirs_regex}>") - # Wrap in $<JOIN:..., > to create qmake-style lists. - foreach(sfx libs libdir incdir defines) - string(PREPEND lib_${sfx} "$<JOIN:") - string(APPEND lib_${sfx} ", >") - endforeach() - - string(APPEND content "QMAKE_LIBS_${uclib} = ${lib_libs} -QMAKE_LIBDIR_${uclib} = ${lib_libdir} -QMAKE_INCDIR_${uclib} = ${lib_incdir} -QMAKE_DEFINES_${uclib} = ${lib_defines} + set(uccfg $<UPPER_CASE:$<CONFIG>>) + string(APPEND content "list(APPEND known_libs ${uclib}) +set(QMAKE_LIBS_${uclib}_${uccfg} \"${lib_libs}\") +set(QMAKE_LIBDIR_${uclib}_${uccfg} \"${lib_libdir}\") +set(QMAKE_INCDIR_${uclib}_${uccfg} \"${lib_incdir}\") +set(QMAKE_DEFINES_${uclib}_${uccfg} \"${lib_defines}\") ") if(QT_QMAKE_LIB_DEPS_${lib}) - list(JOIN QT_QMAKE_LIB_DEPS_${lib} " " deps) - string(APPEND content "QMAKE_DEPENDS_${uclib}_CC = ${deps} -QMAKE_DEPENDS_${uclib}_LD = ${deps} + string(APPEND content "set(QMAKE_DEPENDS_${uclib}_CC, ${deps}) +set(QMAKE_DEPENDS_${uclib}_LD, ${deps}) ") endif() endforeach() - set(${out_var} "${content}" PARENT_SCOPE) + + file(GENERATE + OUTPUT "${output_root_dir}/$<CONFIG>/${output_file_name}" + CONTENT "${content}" + ) endfunction() # Retrieves the public Qt module dependencies of the given Qt module or Qt Private module. @@ -849,15 +849,11 @@ QT_MODULES += ${config_module_name} ) endif() - qt_path_join(private_pri_file "${target_path}" "qt_lib_${config_module_name}_private.pri") - list(APPEND pri_files "${private_pri_file}") + set(pri_data_cmake_file "qt_lib_${config_module_name}_private.cmake") + qt_generate_qmake_libraries_pri_content(${config_module_name} "${CMAKE_CURRENT_BINARY_DIR}" + ${pri_data_cmake_file}) - if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config") - ### FIXME QTBUG-84348 - set(libraries_content "") - else() - qt_get_qmake_libraries_pri_content(libraries_content ${config_module_name}) - endif() + set(private_pri_file_name "qt_lib_${config_module_name}_private.pri") set(private_module_dependencies "") if(NOT arg_HEADER_MODULE) @@ -865,8 +861,9 @@ QT_MODULES += ${config_module_name} endif() list(JOIN private_module_dependencies " " private_module_dependencies) + # Generate a preliminary qt_lib_XXX_private.pri file file(GENERATE - OUTPUT "${private_pri_file}" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${private_pri_file_name}" CONTENT "QT.${config_module_name}_private.VERSION = ${PROJECT_VERSION} QT.${config_module_name}_private.name = ${module} @@ -878,10 +875,34 @@ QT.${config_module_name}_private.depends = ${private_module_dependencies} QT.${config_module_name}_private.uses = QT.${config_module_name}_private.module_config = ${joined_module_internal_config} QT.${config_module_name}_private.enabled_features = ${enabled_private_features} -QT.${config_module_name}_private.disabled_features = ${disabled_private_features} -${libraries_content}" +QT.${config_module_name}_private.disabled_features = ${disabled_private_features}" ) + if(QT_GENERATOR_IS_MULTI_CONFIG) + set(configs ${CMAKE_CONFIGURATION_TYPES}) + else() + set(configs ${CMAKE_BUILD_TYPE}) + endif() + set(inputs "${CMAKE_CURRENT_BINARY_DIR}/${private_pri_file_name}") + foreach(cfg ${configs}) + list(APPEND inputs "${CMAKE_CURRENT_BINARY_DIR}/${cfg}/${pri_data_cmake_file}") + endforeach() + + qt_path_join(private_pri_file_path "${target_path}" "${private_pri_file_name}") + list(APPEND pri_files "${private_pri_file_path}") + add_custom_command( + OUTPUT "${private_pri_file_path}" + DEPENDS ${inputs} + COMMAND ${CMAKE_COMMAND} "-DIN_FILES=${inputs}" "-DOUT_FILE=${private_pri_file_path}" + "-DCONFIGS=${configs}" + -P "${QT_CMAKE_DIR}/QtGenerateLibPri.cmake" + VERBATIM) + add_custom_target(${target}_lib_pri DEPENDS "${private_pri_file_path}") + if(arg_HEADER_MODULE) + add_dependencies(${target}_timestamp ${target}_lib_pri) + else() + add_dependencies(${target} ${target}_lib_pri) + endif() qt_install(FILES "${pri_files}" DESTINATION ${INSTALL_MKSPECSDIR}/modules) endfunction() @@ -1145,13 +1166,35 @@ CONFIG += ${private_config_joined} string(REPLACE ";" " " build_parts "${build_parts}") string(APPEND content "QT_BUILD_PARTS = ${build_parts}\n") - qt_get_qmake_libraries_pri_content(libraries_content global) - string(APPEND content "${libraries_content}") + set(preliminary_pri_root "${CMAKE_CURRENT_BINARY_DIR}/mkspecs/preliminary") + set(pri_data_cmake_file "qmodule.cmake") + qt_generate_qmake_libraries_pri_content(global ${preliminary_pri_root} ${pri_data_cmake_file}) + # Generate a preliminary qmodule.pri file + set(preliminary_pri_file_path "${preliminary_pri_root}/qmodule.pri") file(GENERATE - OUTPUT "${qmodule_pri_target_path}" + OUTPUT ${preliminary_pri_file_path} CONTENT "${content}" ) + + if(QT_GENERATOR_IS_MULTI_CONFIG) + set(configs ${CMAKE_CONFIGURATION_TYPES}) + else() + set(configs ${CMAKE_BUILD_TYPE}) + endif() + set(inputs ${preliminary_pri_file_path}) + foreach(cfg ${configs}) + list(APPEND inputs "${preliminary_pri_root}/${cfg}/${pri_data_cmake_file}") + endforeach() + + add_custom_command( + OUTPUT "${qmodule_pri_target_path}" + DEPENDS ${inputs} + COMMAND ${CMAKE_COMMAND} "-DIN_FILES=${inputs}" "-DOUT_FILE=${qmodule_pri_target_path}" + "-DCONFIGS=${configs}" + -P "${QT_CMAKE_DIR}/QtGenerateLibPri.cmake" + VERBATIM) + add_custom_target(qmodule_pri DEPENDS "${qmodule_pri_target_path}") qt_install(FILES "${qmodule_pri_target_path}" DESTINATION ${INSTALL_MKSPECSDIR}) endfunction() @@ -2468,6 +2511,14 @@ function(qt_add_module target) 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 ${module_headers_public} + VERBATIM) + add_custom_target(${target}_timestamp ALL DEPENDS "${timestamp_file}") endif() qt_extend_target("${target}" diff --git a/cmake/QtGenerateLibPri.cmake b/cmake/QtGenerateLibPri.cmake new file mode 100644 index 0000000000..d335924c1d --- /dev/null +++ b/cmake/QtGenerateLibPri.cmake @@ -0,0 +1,84 @@ +# Generate a qt_lib_XXX.pri file. +# +# This file is to be used in CMake script mode with the following variables set: +# IN_FILES: path to the qt_lib_XXX.cmake files +# OUT_FILE: path to the generated qt_lib_XXX.pri file +# CONFIGS: the configurations Qt is being built with +# +# QMAKE_LIBS_XXX values are split into QMAKE_LIBS_XXX_DEBUG and QMAKE_LIBS_XXX_RELEASE if +# debug_and_release was detected. The CMake configuration "Debug" is considered for the _DEBUG +# values. The first config that is not "Debug" is treated as _RELEASE. + +cmake_policy(SET CMP0057 NEW) + +# Create a qmake-style list from the passed arguments and store it in ${out_var}. +function(qmake_list out_var) + set(result "") + + # Surround values that contain spaces with double quotes. + foreach(v ${ARGN}) + if(v MATCHES " ") + set(v "\"${v}\"") + endif() + list(APPEND result ${v}) + endforeach() + + list(JOIN result " " result) + set(${out_var} ${result} PARENT_SCOPE) +endfunction() + +list(POP_FRONT IN_FILES in_pri_file) +file(READ ${in_pri_file} content) +string(APPEND content "\n") +foreach(in_file ${IN_FILES}) + include(${in_file}) +endforeach() +list(REMOVE_DUPLICATES known_libs) + +set(is_debug_and_release FALSE) +if("Debug" IN_LIST CONFIGS AND ("Release" IN_LIST CONFIGS OR "RelWithDebInfo" IN_LIST CONFIGS)) + set(is_debug_and_release TRUE) + set(release_configs ${CONFIGS}) + list(REMOVE_ITEM release_configs "Debug") + list(GET release_configs 0 release_cfg) + string(TOUPPER "${release_cfg}" release_cfg) +endif() + +foreach(lib ${known_libs}) + set(configuration_independent_infixes LIBDIR INCDIR DEFINES) + + if(is_debug_and_release) + set(value_debug ${QMAKE_LIBS_${lib}_DEBUG}) + set(value_release ${QMAKE_LIBS_${lib}_${release_cfg}}) + if(value_debug STREQUAL value_release) + if(value_debug) + qmake_list(value_debug ${value_debug}) + string(APPEND content "QMAKE_LIBS_${lib} = ${value_debug}\n") + endif() + else() + if(value_debug) + qmake_list(value_debug ${value_debug}) + string(APPEND content "QMAKE_LIBS_${lib}_DEBUG = ${value_debug}\n") + endif() + if(value_release) + qmake_list(value_release ${value_release}) + string(APPEND content "QMAKE_LIBS_${lib}_RELEASE = ${value_release}\n") + endif() + endif() + else() + list(APPEND configuration_independent_infixes LIBS) + endif() + + # The remaining values are considered equal for all configurations. + # Pick the first configuration and use its values. + list(GET CONFIGS 0 cfg) + string(TOUPPER ${cfg} cfg) + foreach(infix ${configuration_independent_infixes}) + set(value ${QMAKE_${infix}_${lib}_${cfg}}) + if(value) + qmake_list(value ${value}) + string(APPEND content "QMAKE_${infix}_${lib} = ${value}\n") + endif() + endforeach() +endforeach() +file(WRITE "${OUT_FILE}" "${content}") |