qt5base-lts/cmake/QtPostProcess.cmake
Alexandru Croitor fbddf745e9 Create module tools packages (config files) automatically
Previously you had to make sure to use DISABLE_TOOLS_EXPORT
in an add_qt_module call if the tools are built after the module,
as well as to manually call qt_export_tools after all associated
tools are built.

This was needlessly complex, especially for people that are porting
a repo with tools for the first time.

The tools package creation is now automatically done at QtPostProcess
step, so there is no need to use either DISABLE_TOOLS_EXPORT or
qt_export_tools() manually.

DISABLE_TOOLS_EXPORT is now a no-op, and will be removed once all repos
are updated not to use it.

Change-Id: I965b0d3a8a0cb908afae87b047083ed7bea9f02f
Reviewed-by: Qt CMake Build Bot
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
2019-09-22 10:29:28 +00:00

350 lines
13 KiB
CMake

function(qt_internal_write_depends_file target)
set(module Qt${target})
set(outfile "${QT_BUILD_DIR}/include/${module}/${module}Depends")
message("Generate ${outfile}...")
set(contents "/* This file was generated by cmake with the info from ${module} target. */\n")
string(APPEND contents "#ifdef __cplusplus /* create empty PCH in C mode */\n")
foreach (m ${ARGN})
string(APPEND contents "# include <Qt${m}/Qt${m}>\n")
endforeach()
string(APPEND contents "#endif\n")
file(GENERATE OUTPUT "${outfile}" CONTENT "${contents}")
endfunction()
macro(qt_collect_third_party_deps)
# If we are doing a non-static Qt build, we only want to propagate public dependencies.
# If we are doing a static Qt build, we need to propagate all dependencies.
set(depends_var "public_depends")
if(NOT QT_BUILD_SHARED_LIBS)
set(depends_var "depends")
endif()
foreach(dep ${${depends_var}})
# Gather third party packages that should be found when using the Qt module.
# Also handle nolink target dependencies.
string(REGEX REPLACE "_nolink$" "" base_dep "${dep}")
if(NOT base_dep STREQUAL dep)
# Resets target name like Vulkan_nolink to Vulkan, because we need to call
# find_package(Vulkan).
set(dep ${base_dep})
endif()
if(TARGET ${dep})
list(FIND third_party_deps_seen ${dep} dep_seen)
get_target_property(package_name ${dep} INTERFACE_QT_PACKAGE_NAME)
if(dep_seen EQUAL -1 AND package_name)
list(APPEND third_party_deps_seen ${dep})
get_target_property(package_version ${dep} INTERFACE_QT_PACKAGE_VERSION)
if(NOT package_version)
set(package_version "")
endif()
get_target_property(package_components ${dep} INTERFACE_QT_PACKAGE_COMPONENTS)
if(NOT package_components)
set(package_components "")
endif()
list(APPEND third_party_deps
"${package_name}\;${package_version}\;${package_components}")
endif()
endif()
endforeach()
endmacro()
function(qt_internal_create_module_depends_file target)
get_target_property(target_type "${target}" TYPE)
if(target_type STREQUAL "INTERFACE_LIBRARY")
set(arg_HEADER_MODULE ON)
else()
set(arg_HEADER_MODULE OFF)
endif()
if(NOT arg_HEADER_MODULE)
get_target_property(depends "${target}" LINK_LIBRARIES)
endif()
get_target_property(public_depends "${target}" INTERFACE_LINK_LIBRARIES)
# Used for collecting Qt module dependencies that should be find_package()'d in
# ModuleDependencies.cmake.
get_target_property(target_deps "${target}" _qt_target_deps)
set(target_deps_seen "")
if(NOT arg_HEADER_MODULE)
get_target_property(extra_depends "${target}" QT_EXTRA_PACKAGE_DEPENDENCIES)
endif()
if(NOT extra_depends STREQUAL "${extra_depends}-NOTFOUND")
list(APPEND target_deps ${extra_depends})
endif()
# Used for assembling the content of an include/Module/ModuleDepends.h header.
set(qtdeps "")
# Used for collecting third party dependencies that should be find_package()'d in
# ModuleDependencies.cmake.
set(third_party_deps "")
set(third_party_deps_seen "")
# Used for collecting Qt tool dependencies that should be find_package()'d in
# ModuleToolsDependencies.cmake.
set(tool_deps "")
set(tool_deps_seen "")
# Used for collecting Qt tool dependencies that should be find_package()'d in
# ModuleDependencies.cmake.
set(main_module_tool_deps "")
qt_internal_get_qt_all_known_modules(known_modules)
set(all_depends ${depends} ${public_depends})
foreach (dep ${all_depends})
# Normalize module by stripping leading "Qt::" and trailing "Private"
if (dep MATCHES "Qt::(.*)")
set(dep "${CMAKE_MATCH_1}")
endif()
if (dep MATCHES "(.*)Private")
set(dep "${CMAKE_MATCH_1}")
endif()
list(FIND known_modules "${dep}" _pos)
if (_pos GREATER -1)
list(APPEND qtdeps "${dep}")
# Make the ModuleTool package depend on dep's ModuleTool package.
list(FIND tool_deps_seen ${dep} dep_seen)
if(dep_seen EQUAL -1 AND ${dep} IN_LIST QT_KNOWN_MODULES_WITH_TOOLS)
list(APPEND tool_deps_seen ${dep})
list(APPEND tool_deps
"${INSTALL_CMAKE_NAMESPACE}${dep}Tools\;${PROJECT_VERSION}")
endif()
endif()
endforeach()
qt_collect_third_party_deps()
# Add dependency to the main ModuleTool package to ModuleDependencies file.
if(${target} IN_LIST QT_KNOWN_MODULES_WITH_TOOLS)
set(main_module_tool_deps
"${INSTALL_CMAKE_NAMESPACE}${target}Tools\;${PROJECT_VERSION}")
endif()
# Dirty hack because https://gitlab.kitware.com/cmake/cmake/issues/19200
foreach(dep ${target_deps})
if(dep)
list(FIND target_deps_seen "${dep}" dep_seen)
if(dep_seen EQUAL -1)
list(LENGTH dep len)
if(NOT (len EQUAL 2))
message(FATAL_ERROR "List '${dep}' should look like QtFoo;version")
endif()
list(GET dep 0 dep_name)
list(GET dep 1 dep_ver)
list(APPEND target_deps_seen "${dep_name}\;${dep_ver}")
endif()
endif()
endforeach()
set(target_deps "${target_deps_seen}")
if (DEFINED qtdeps)
list(REMOVE_DUPLICATES qtdeps)
endif()
get_target_property(hasModuleHeaders "${target}" INTERFACE_MODULE_HAS_HEADERS)
if (${hasModuleHeaders})
qt_internal_write_depends_file("${target}" ${qtdeps})
endif()
if(third_party_deps OR main_module_tool_deps OR target_deps)
set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}")
qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix})
qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix})
# Configure and install ModuleDependencies file.
configure_file(
"${QT_CMAKE_DIR}/QtModuleDependencies.cmake.in"
"${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}Dependencies.cmake"
@ONLY
)
qt_install(FILES
"${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}Dependencies.cmake"
DESTINATION "${config_install_dir}"
COMPONENT Devel
)
endif()
if(tool_deps)
set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}Tools")
qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix})
qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix})
# Configure and install ModuleToolDependencies file.
configure_file(
"${QT_CMAKE_DIR}/QtModuleToolsDependencies.cmake.in"
"${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ToolsDependencies.cmake"
@ONLY
)
qt_install(FILES
"${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ToolsDependencies.cmake"
DESTINATION "${config_install_dir}"
COMPONENT Devel
)
endif()
endfunction()
function(qt_internal_create_plugin_depends_file target)
get_target_property(qt_module "${target}" QT_MODULE)
get_target_property(depends "${target}" LINK_LIBRARIES)
get_target_property(public_depends "${target}" INTERFACE_LINK_LIBRARIES)
get_target_property(target_deps "${target}" _qt_target_deps)
set(target_deps_seen "")
qt_collect_third_party_deps()
# Dirty hack because https://gitlab.kitware.com/cmake/cmake/issues/19200
foreach(dep ${target_deps})
if(dep)
list(FIND target_deps_seen "${dep}" dep_seen)
if(dep_seen EQUAL -1)
list(LENGTH dep len)
if(NOT (len EQUAL 2))
message(FATAL_ERROR "List '${dep}' should look like QtFoo;version")
endif()
list(GET dep 0 dep_name)
list(GET dep 1 dep_ver)
list(APPEND target_deps_seen "${dep_name}\;${dep_ver}")
endif()
endif()
endforeach()
set(target_deps "${target_deps_seen}")
if(third_party_deps OR target_deps)
# Setup build and install paths
if(qt_module)
set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${qt_module}")
else()
set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}")
endif()
qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix})
qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix})
# Configure and install ModuleDependencies file.
configure_file(
"${QT_CMAKE_DIR}/QtPluginDependencies.cmake.in"
"${config_build_dir}/${target}Dependencies.cmake"
@ONLY
)
qt_install(FILES
"${config_build_dir}/${target}Dependencies.cmake"
DESTINATION "${config_install_dir}"
COMPONENT Devel
)
endif()
endfunction()
# Create Depends.cmake & Depends.h files for all modules and plug-ins.
function(qt_internal_create_depends_files)
qt_internal_get_qt_repo_known_modules(repo_known_modules)
message("Generating ModuleDepends files and CMake ModuleDependencies files for ${repo_known_modules}...")
foreach (target ${repo_known_modules})
qt_internal_create_module_depends_file(${target})
endforeach()
message("Generating CMake PluginDependencies files for ${QT_KNOWN_PLUGINS}...")
foreach (target ${QT_KNOWN_PLUGINS})
qt_internal_create_plugin_depends_file(${target})
endforeach()
endfunction()
# This function creates the Qt<Module>Plugins.cmake used to list all
# the plug-in target files.
function(qt_internal_create_plugins_files)
# The plugins cmake configuration is only needed for static builds. Dynamic builds don't need
# the application to link against plugins at build time.
if(QT_BUILD_SHARED_LIBS)
return()
endif()
qt_internal_get_qt_repo_known_modules(repo_known_modules)
message("Generating Plugins files for ${repo_known_modules}...")
foreach (QT_MODULE ${repo_known_modules})
get_target_property(target_type "${QT_MODULE}" TYPE)
if(target_type STREQUAL "INTERFACE_LIBRARY")
# No plugins are provided by a header only module.
continue()
endif()
qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${INSTALL_CMAKE_NAMESPACE}${QT_MODULE})
qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${INSTALL_CMAKE_NAMESPACE}${QT_MODULE})
set(QT_MODULE_PLUGIN_INCLUDES "")
get_target_property(qt_plugins "${QT_MODULE}" QT_PLUGINS)
if(qt_plugins)
foreach (pluginTarget ${qt_plugins})
set(QT_MODULE_PLUGIN_INCLUDES "${QT_MODULE_PLUGIN_INCLUDES}include(\"\${CMAKE_CURRENT_LIST_DIR}/${pluginTarget}Config.cmake\")\n")
endforeach()
configure_file(
"${QT_CMAKE_DIR}/QtPlugins.cmake.in"
"${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${QT_MODULE}Plugins.cmake"
@ONLY
)
qt_install(FILES
"${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${QT_MODULE}Plugins.cmake"
DESTINATION "${config_install_dir}"
COMPONENT Devel
)
endif()
endforeach()
endfunction()
function(qt_generate_build_internals_extra_cmake_code)
if(PROJECT_NAME STREQUAL "QtBase")
set(QT_EXTRA_BUILD_INTERNALS_VARS)
foreach(var IN LISTS qt_base_configure_tests_vars_to_export)
string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS "set(${var} \"${${var}}\" CACHE INTERNAL \"\")\n")
endforeach()
set(QT_SOURCE_TREE "${QtBase_SOURCE_DIR}")
qt_path_join(extra_file_path
${QT_CONFIG_BUILD_DIR}
${INSTALL_CMAKE_NAMESPACE}BuildInternals/QtBuildInternalsExtra.cmake)
configure_file(
"${CMAKE_CURRENT_LIST_DIR}/QtBuildInternalsExtra.cmake.in"
"${extra_file_path}"
@ONLY
)
endif()
endfunction()
# For every Qt module check if there any android dependencies that require
# processing.
function(qt_modules_process_android_dependencies)
qt_internal_get_qt_repo_known_modules(repo_known_modules)
foreach (target ${repo_known_modules})
qt_android_dependencies(${target})
endforeach()
endfunction()
function(qt_create_tools_config_files)
# Create packages like Qt6CoreTools/Qt6CoreToolsConfig.cmake.
foreach(module_name ${QT_KNOWN_MODULES_WITH_TOOLS})
qt_export_tools("${module_name}")
endforeach()
endfunction()
qt_create_tools_config_files()
qt_internal_create_depends_files()
qt_generate_build_internals_extra_cmake_code()
qt_internal_create_plugins_files()
if (ANDROID)
qt_modules_process_android_dependencies()
endif()