diff options
author | Joerg Bornemann <joerg.bornemann@qt.io> | 2020-04-22 21:01:32 +0200 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@qt.io> | 2020-05-19 13:26:53 +0200 |
commit | 759da6742a513fa3fb85bb6db569cff5a53a47d6 (patch) | |
tree | e3f45a31991eac56b6ac699a6ebb8678ff168780 /cmake | |
parent | aed7a65b8b0870d8a019f7917888587de2a66303 (diff) |
CMake: Generate information about 3rdparty libs in module .pri files
For modules that are not yet ported to CMake and that use
QMAKE_USE += libfoo
we need to provide the information about libfoo in the qt_lib_XXX.pri
files.
Also, we now generate qt_ext_XXX.pri files for bundled 3rdparty libs.
Task-number: QTBUG-75666
Change-Id: I9e4b057a197554ecb37c294c0bf09e2a2b3aa053
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 | 153 | ||||
-rw-r--r-- | cmake/QtGenerateExtPri.cmake | 47 |
3 files changed, 198 insertions, 3 deletions
diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index ea765847eb..366b23c6c1 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -321,6 +321,7 @@ qt_copy_or_install(FILES cmake/QtFindWrapHelper.cmake cmake/QtFindWrapConfigExtra.cmake.in cmake/QtFileConfigure.txt.in + cmake/QtGenerateExtPri.cmake cmake/QtPlatformSupport.cmake cmake/QtPlatformAndroid.cmake cmake/QtPostProcess.cmake diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 7b4ca49f97..f8f7169f97 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -604,6 +604,88 @@ function(qt_is_imported_target target out_var) set(${out_var} "${is_imported}" PARENT_SCOPE) endfunction() +# Creates a regular expression that exactly matches the given string +# Found in https://gitlab.kitware.com/cmake/cmake/issues/18580 +function(qt_re_escape out_var str) + string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" regex "${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}. +# +# 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) + set(content "") + + # Set up a regular expression that matches all implicit include dirs + set(implicit_include_dirs_regex "") + foreach(dir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) + qt_re_escape(regex "${dir}") + list(APPEND implicit_include_dirs_regex ${regex}) + endforeach() + list(JOIN implicit_include_dirs_regex "|" implicit_include_dirs_regex) + + foreach(lib ${QT_QMAKE_LIBS_FOR_${module_name}}) + set(lib_targets ${QT_QMAKE_LIB_TARGETS_${lib}}) + string(TOUPPER ${lib} uclib) + set(lib_defines "") + set(lib_incdir "") + set(lib_libdir "") + set(lib_libs "") + while(lib_targets) + list(POP_BACK lib_targets lib_target) + if(TARGET ${lib_target}) + get_target_property(lib_target_type ${lib_target} TYPE) + if(lib_target_type STREQUAL "INTERFACE_LIBRARY") + get_target_property(iface_libs ${lib_target} INTERFACE_LINK_LIBRARIES) + if(iface_libs) + list(PREPEND lib_targets ${iface_libs}) + endif() + else() + list(APPEND lib_libs "$<TARGET_LINKER_FILE:${lib_target}>") + endif() + list(APPEND lib_libdir "$<TARGET_PROPERTY:${lib_target},INTERFACE_LINK_DIRECTORIES>") + list(APPEND lib_incdir "$<TARGET_PROPERTY:${lib_target},INTERFACE_INCLUDE_DIRECTORIES>") + list(APPEND lib_defines "$<TARGET_PROPERTY:${lib_target},INTERFACE_COMPILE_DEFINITIONS>") + else() + list(APPEND lib_libs "${lib_target}") + endif() + endwhile() + + # Wrap in $<REMOVE_DUPLICATES:...> but not the libs, because + # we would have to preserve the right order for the linker. + foreach(sfx libdir incdir defines) + string(PREPEND lib_${sfx} "$<REMOVE_DUPLICATES:") + string(APPEND lib_${sfx} ">") + endforeach() + + # Filter out implicit include directories + 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} +") + 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} +") + endif() + endforeach() + set(${out_var} "${content}" PARENT_SCOPE) +endfunction() + # Generates module .pri files for consumption by qmake function(qt_generate_module_pri_file target target_path config_module_name pri_files_var) set(flags INTERNAL_MODULE HEADER_MODULE) @@ -703,6 +785,8 @@ QT_MODULES += ${config_module_name} qt_path_join(private_pri_file "${target_path}" "qt_lib_${config_module_name}_private.pri") list(APPEND pri_files "${private_pri_file}") + qt_get_qmake_libraries_pri_content(libraries_content ${config_module_name}) + file(GENERATE OUTPUT "${private_pri_file}" CONTENT @@ -717,12 +801,54 @@ 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}" ) set("${pri_files_var}" "${pri_files}" PARENT_SCOPE) endfunction() +# Generates qt_ext_XXX.pri files for consumption by qmake +function(qt_generate_3rdparty_lib_pri_file target lib pri_file_var) + if(NOT lib) + # Don't write a pri file for projects that don't set QMAKE_LIB_NAME yet. + return() + endif() + + if(QT_GENERATOR_IS_MULTI_CONFIG) + set(configs ${CMAKE_CONFIGURATION_TYPES}) + else() + set(configs ${CMAKE_BUILD_TYPE}) + endif() + + file(GENERATE + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/qt_ext_${lib}.cmake" + CONTENT "set(cfg $<CONFIG>) +set(incdir $<TARGET_PROPERTY:${target},INTERFACE_INCLUDE_DIRECTORIES>) +set(defines $<TARGET_PROPERTY:${target},INTERFACE_COMPILE_DEFINITIONS>) +set(libs $<TARGET_FILE:${target}>) +") + + set(inputs "") + foreach(cfg ${configs}) + list(APPEND inputs "${CMAKE_CURRENT_BINARY_DIR}/${cfg}/qt_ext_${lib}.cmake") + endforeach() + + qt_path_join(pri_target_path ${QT_BUILD_DIR} ${INSTALL_MKSPECSDIR}/modules) + qt_path_join(pri_file "${pri_target_path}" "qt_ext_${lib}.pri") + qt_path_join(qt_build_libdir ${QT_BUILD_DIR} ${INSTALL_LIBDIR}) + add_custom_command( + OUTPUT "${pri_file}" + DEPENDS ${inputs} + COMMAND ${CMAKE_COMMAND} "-DIN_FILES=${inputs}" "-DOUT_FILE=${pri_file}" -DLIB=${lib} + "-DCONFIGS=${configs}" + "-DQT_BUILD_LIBDIR=${qt_build_libdir}" + -P "${QT_CMAKE_DIR}/QtGenerateExtPri.cmake" + VERBATIM) + add_custom_target(${target}_ext_pri DEPENDS "${pri_file}") + add_dependencies(${target} ${target}_ext_pri) + set(${pri_file_var} ${pri_file} PARENT_SCOPE) +endfunction() + function(qt_cmake_build_type_to_qmake_build_config out_var build_type) if(build_type STREQUAL "Debug") set(cfg debug) @@ -893,6 +1019,9 @@ 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}") + file(GENERATE OUTPUT "${qmodule_pri_target_path}" CONTENT "${content}" @@ -3661,7 +3790,7 @@ function(qt_add_3rdparty_library target) # Process arguments: qt_parse_all_arguments(arg "qt_add_3rdparty_library" "SHARED;MODULE;STATIC;INTERFACE;EXCEPTIONS;INSTALL;SKIP_AUTOMOC" - "OUTPUT_DIRECTORY" + "OUTPUT_DIRECTORY;QMAKE_LIB_NAME" "${__default_private_args};${__default_public_args}" ${ARGN} ) @@ -3738,6 +3867,11 @@ function(qt_add_3rdparty_library target) qt_internal_set_no_exceptions_flags("${target}") endif() + qt_generate_3rdparty_lib_pri_file("${target}" "${arg_QMAKE_LIB_NAME}" pri_file) + if(pri_file) + qt_install(FILES "${pri_file}" DESTINATION "${INSTALL_MKSPECSDIR}/modules") + endif() + qt_extend_target("${target}" SOURCES ${arg_SOURCES} INCLUDE_DIRECTORIES @@ -4398,7 +4532,7 @@ endfunction() macro(qt_find_package) # Get the target names we expect to be provided by the package. set(options CONFIG NO_MODULE MODULE REQUIRED) - set(oneValueArgs) + set(oneValueArgs MODULE_NAME QMAKE_LIB) set(multiValueArgs PROVIDED_TARGETS COMPONENTS) cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -4519,9 +4653,22 @@ macro(qt_find_package) endif() endforeach() + + if(arg_MODULE_NAME AND arg_QMAKE_LIB + AND (NOT arg_QMAKE_LIB IN_LIST QT_QMAKE_LIBS_FOR_${arg_MODULE_NAME})) + set(QT_QMAKE_LIBS_FOR_${arg_MODULE_NAME} + ${QT_QMAKE_LIBS_FOR_${arg_MODULE_NAME}};${arg_QMAKE_LIB} CACHE INTERNAL "") + set(QT_QMAKE_LIB_TARGETS_${arg_QMAKE_LIB} ${arg_PROVIDED_TARGETS} CACHE INTERNAL "") + endif() endif() endmacro() +macro(qt_add_qmake_lib_dependency lib dep) + string(REPLACE "-" "_" dep ${dep}) + string(TOUPPER "${dep}" ucdep) + list(APPEND QT_QMAKE_LIB_DEPS_${lib} ${ucdep}) +endmacro() + macro(qt_find_apple_system_frameworks) if(APPLE) find_library(FWAppKit AppKit) diff --git a/cmake/QtGenerateExtPri.cmake b/cmake/QtGenerateExtPri.cmake new file mode 100644 index 0000000000..02ac675d4e --- /dev/null +++ b/cmake/QtGenerateExtPri.cmake @@ -0,0 +1,47 @@ +# Generate a qt_ext_XXX.pri file. +# +# - Replaces occurrences of the build libdir with $$[QT_INSTALL_LIBDIR/get]. +# +# This file is to be used in CMake script mode with the following variables set: +# IN_FILES: path to the qt_ext_XXX.cmake files +# OUT_FILE: path to the generated qt_ext_XXX.pri file +# QT_BUILD_LIBDIR: path to Qt's libdir when building (those paths get replaced) +set(content "") +string(TOUPPER "${LIB}" uclib) +set(first_iteration TRUE) +list(LENGTH CONFIGS number_of_configs) +foreach(in_file ${IN_FILES}) + include(${in_file}) + if(first_iteration) + # Add configuration-independent variables + set(first_iteration FALSE) + list(JOIN incdir " " incdir) + list(JOIN defines " " defines) + string(APPEND content "QMAKE_INCDIR_${uclib} = ${incdir} +QMAKE_DEFINES_${uclib} = ${defines} +") + endif() + set(config_suffix "") + if(number_of_configs GREATER "1") + # We're in multi-config mode. Use a _DEBUG or _RELEASE suffix for libs. + # qmake_use.prf does not support other configurations. + string(TOUPPER "${cfg}" config_suffix) + if(config_suffix STREQUAL "DEBUG") + set(config_suffix _DEBUG) + else() + set(config_suffix _RELEASE) + endif() + endif() + + # Replace the build libdir + set(fixed_libs "") + foreach(lib ${libs}) + string(REPLACE "${QT_BUILD_LIBDIR}" "$$[QT_INSTALL_LIBS/get]" lib "${lib}") + list(APPEND fixed_libs "${lib}") + endforeach() + + list(JOIN fixed_libs " " libs) + string(APPEND content "QMAKE_LIBS_${uclib}${config_suffix} = ${libs} +") +endforeach() +file(WRITE "${OUT_FILE}" "${content}") |