summaryrefslogtreecommitdiffstats
path: root/cmake
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@qt.io>2020-06-05 10:10:50 +0200
committerJoerg Bornemann <joerg.bornemann@qt.io>2020-06-09 21:04:26 +0200
commit2a767ab4bb7de8c29d2a8365212244ed944e9aeb (patch)
treed02b1d45bb0bcd7a313baaac8c57a86c999ea658 /cmake
parentd2833a3ce5af725d66ef9338f2a61b766dd3cb2d (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.cmake1
-rw-r--r--cmake/QtBuild.cmake113
-rw-r--r--cmake/QtGenerateLibPri.cmake84
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}")