CMake: Refactor handling of static plugins
Extract common static plugin handling functionality into a separate QtPublicPluginHelpers.cmake file which is loaded by the Qt6 package. Split the code into smaller functions that will be re-used by each templated QtPlugins.cmake.in file, rather than copy pasting the same code into each QtFooPlugins.cmake file. As a drive-by, handle QtFeatures.cmake and QtFeaturesCommon.cmake as public helper files just like QtPublicPluginHelpers.cmake. This makes it clearer that the functions are available outside the internal Qt build and also provides a way for not dumping new helper functions into Qt6CoreMacros.cmake. Task-number: QTBUG-92933 Change-Id: Id816ef009b4fac1cd317d3ef23f21b3530028067 Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
parent
867c0b8d8a
commit
b104bedea1
@ -159,7 +159,9 @@ qt_internal_export_modern_cmake_config_targets_file(TARGETS ${__export_targets}
|
||||
CONFIG_INSTALL_DIR
|
||||
${__GlobalConfig_install_dir})
|
||||
|
||||
## Install some QtBase specific CMake files:
|
||||
# Install internal CMake files.
|
||||
# The functions defined inside can not be used in public projects.
|
||||
# They can only be used while building Qt itself.
|
||||
qt_copy_or_install(FILES
|
||||
cmake/ModuleDescription.json.in
|
||||
cmake/Qt3rdPartyLibraryConfig.cmake.in
|
||||
@ -179,8 +181,6 @@ qt_copy_or_install(FILES
|
||||
cmake/QtDbusHelpers.cmake
|
||||
cmake/QtDocsHelpers.cmake
|
||||
cmake/QtExecutableHelpers.cmake
|
||||
cmake/QtFeature.cmake
|
||||
cmake/QtFeatureCommon.cmake
|
||||
cmake/QtFileConfigure.txt.in
|
||||
cmake/QtFindPackageHelpers.cmake
|
||||
cmake/QtFindWrapConfigExtra.cmake.in
|
||||
@ -237,7 +237,25 @@ qt_copy_or_install(FILES
|
||||
DESTINATION "${__GlobalConfig_install_dir}"
|
||||
)
|
||||
|
||||
file(COPY cmake/QtFeature.cmake DESTINATION "${__GlobalConfig_build_dir}")
|
||||
# Install public CMake files.
|
||||
# The functions defined inside can be used in both public projects and while building Qt.
|
||||
# Usually we put such functions into Qt6CoreMacros.cmake, but that's getting bloated.
|
||||
# These files will be included by Qt6Config.cmake.
|
||||
set(__public_cmake_helpers
|
||||
cmake/QtFeature.cmake
|
||||
cmake/QtFeatureCommon.cmake
|
||||
cmake/QtPublicPluginHelpers.cmake
|
||||
)
|
||||
|
||||
qt_copy_or_install(FILES ${__public_cmake_helpers} DESTINATION "${__GlobalConfig_install_dir}")
|
||||
|
||||
# In prefix builds we also need to copy the files into the build config directory, so that the
|
||||
# build-dir Qt6Config.cmake finds the files when building examples in-tree.
|
||||
if(QT_WILL_INSTALL)
|
||||
foreach(_public_cmake_helper ${__public_cmake_helpers})
|
||||
file(COPY "${_public_cmake_helper}" DESTINATION "${__GlobalConfig_build_dir}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# TODO: Check whether this is the right place to install these
|
||||
qt_copy_or_install(DIRECTORY cmake/3rdparty DESTINATION "${__GlobalConfig_install_dir}")
|
||||
|
@ -507,6 +507,7 @@ set(__qt_internal_add_executable_multi_args
|
||||
|
||||
option(QT_CMAKE_DEBUG_EXTEND_TARGET "Debug extend_target calls in Qt's build system" OFF)
|
||||
|
||||
# Internal helpers available only while building Qt itself.
|
||||
include(Qt3rdPartyLibraryHelpers)
|
||||
include(QtAppHelpers)
|
||||
include(QtAutogenHelpers)
|
||||
@ -544,6 +545,10 @@ if(ANDROID)
|
||||
include(QtAndroidHelpers)
|
||||
endif()
|
||||
|
||||
# Helpers that are available in public projects and while building Qt itself.
|
||||
include(QtPublicPluginHelpers)
|
||||
|
||||
|
||||
# TODO: This block provides support for old variables. It should be removed once
|
||||
# we remove all references to these variables in other Qt module repos.
|
||||
# Prefer to use the provided commands to retrieve the relevant things instead.
|
||||
|
@ -53,6 +53,10 @@ set(QT_ADDITIONAL_PACKAGES_PREFIX_PATH "" CACHE STRING "Additional directories w
|
||||
file(TO_CMAKE_PATH "${QT_ADDITIONAL_PACKAGES_PREFIX_PATH}" _qt_additional_packages_prefix_path)
|
||||
file(TO_CMAKE_PATH "$ENV{QT_ADDITIONAL_PACKAGES_PREFIX_PATH}" _qt_additional_packages_prefix_path_env)
|
||||
|
||||
# Public helpers available to all Qt packages.
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/QtFeature.cmake")
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/QtPublicPluginHelpers.cmake")
|
||||
|
||||
# Find required dependencies, if any.
|
||||
include(CMakeFindDependencyMacro)
|
||||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@Dependencies.cmake")
|
||||
|
@ -91,8 +91,6 @@ if (TARGET @QT_CMAKE_EXPORT_NAMESPACE@::@target@)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/${extra_cmake_include}")
|
||||
endforeach()
|
||||
|
||||
include(${_qt_@PROJECT_VERSION_MAJOR@_config_cmake_dir}/QtFeature.cmake)
|
||||
|
||||
qt_make_features_available(@QT_CMAKE_EXPORT_NAMESPACE@::@target@)
|
||||
|
||||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Plugins.cmake")
|
||||
|
@ -30,123 +30,29 @@ function(__qt_internal_add_static_plugins_once)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_default_plugins_are_enabled "$<NOT:$<STREQUAL:$<GENEX_EVAL:$<TARGET_PROPERTY:QT_DEFAULT_PLUGINS>>,0>>")
|
||||
set(_manual_plugins_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:QT_PLUGINS>>")
|
||||
set(_no_plugins_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:QT_NO_PLUGINS>>")
|
||||
|
||||
# Plugin genex marker for prl processing.
|
||||
set(_is_plugin_marker_genex "$<BOOL:QT_IS_PLUGIN_GENEX>")
|
||||
|
||||
# The code in here uses the properties defined in qt_import_plugins (Qt6CoreMacros.cmake)
|
||||
foreach(target ${_qt_plugins})
|
||||
set(_plugin_target "@INSTALL_CMAKE_NAMESPACE@::${target}")
|
||||
set(_plugin_target_versionless "Qt::${target}")
|
||||
get_target_property(_classname "${_plugin_target}" QT_PLUGIN_CLASS_NAME)
|
||||
if(NOT _classname)
|
||||
message("Warning: plugin ${_plugin_target} has no class name, skipping.")
|
||||
continue()
|
||||
foreach(plugin_target ${_qt_plugins})
|
||||
__qt_internal_plugin_get_plugin_type("${plugin_target}" __has_plugin_type __plugin_type)
|
||||
if(NOT __has_plugin_type)
|
||||
continue()
|
||||
endif()
|
||||
|
||||
get_target_property(_plugin_type "${_plugin_target}" QT_PLUGIN_TYPE)
|
||||
if(NOT _plugin_type)
|
||||
message("Warning: plugin ${_plugin_target} has no type ('${_plugin_type}'), skipping.")
|
||||
continue()
|
||||
__qt_internal_plugin_has_class_name("${plugin_target}" __has_class_name)
|
||||
if(NOT __has_class_name)
|
||||
continue()
|
||||
endif()
|
||||
|
||||
list(APPEND "QT_ALL_PLUGINS_FOUND_BY_FIND_PACKAGE_${_plugin_type}" "${target}")
|
||||
set("QT_ALL_PLUGINS_FOUND_BY_FIND_PACKAGE_${_plugin_type}"
|
||||
"${QT_ALL_PLUGINS_FOUND_BY_FIND_PACKAGE_${_plugin_type}}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
list(APPEND "QT_ALL_PLUGINS_FOUND_BY_FIND_PACKAGE_${__plugin_type}" "${plugin_target}")
|
||||
|
||||
set(_plugin_is_default "$<TARGET_PROPERTY:${_plugin_target},QT_DEFAULT_PLUGIN>")
|
||||
|
||||
# INCLUDE
|
||||
set(_plugin_is_whitelisted "$<IN_LIST:${_plugin_target},${_manual_plugins_genex}>")
|
||||
set(_plugin_versionless_is_whitelisted
|
||||
"$<IN_LIST:${_plugin_target_versionless},${_manual_plugins_genex}>")
|
||||
|
||||
# Note: qt_import_plugins sets the QT_PLUGINS_${_plugin_type} to "-"
|
||||
# when excluding it with EXCLUDE_BY_TYPE,
|
||||
# which ensures that no plug-in will be supported unless explicitly re-added afterwards.
|
||||
string(CONCAT _plugin_is_not_blacklisted
|
||||
"$<AND:"
|
||||
"$<NOT:" # EXCLUDE
|
||||
"$<IN_LIST:${_plugin_target},${_no_plugins_genex}>"
|
||||
">,"
|
||||
"$<NOT:"
|
||||
"$<IN_LIST:${_plugin_target_versionless},${_no_plugins_genex}>"
|
||||
">,"
|
||||
# Excludes both plugins targeted by EXCLUDE_BY_TYPE and not included in
|
||||
# INCLUDE_BY_TYPE.
|
||||
"$<STREQUAL:,$<GENEX_EVAL:$<TARGET_PROPERTY:QT_PLUGINS_${_plugin_type}>>>"
|
||||
">"
|
||||
)
|
||||
|
||||
# Support INCLUDE_BY_TYPE
|
||||
string(CONCAT _plugin_is_in_type_whitelist
|
||||
"$<IN_LIST:"
|
||||
"${_plugin_target},"
|
||||
"$<GENEX_EVAL:"
|
||||
"$<TARGET_PROPERTY:QT_PLUGINS_${_plugin_type}>"
|
||||
">"
|
||||
">"
|
||||
)
|
||||
string(CONCAT _plugin_versionless_is_in_type_whitelist
|
||||
"$<IN_LIST:"
|
||||
"${_plugin_target_versionless},"
|
||||
"$<GENEX_EVAL:"
|
||||
"$<TARGET_PROPERTY:QT_PLUGINS_${_plugin_type}>"
|
||||
">"
|
||||
">"
|
||||
)
|
||||
|
||||
# Complete condition that defines whether a static plugin is linked
|
||||
string(CONCAT _plugin_condition
|
||||
"$<BOOL:$<AND:"
|
||||
"${_is_plugin_marker_genex},"
|
||||
"$<OR:"
|
||||
"${_plugin_is_whitelisted},"
|
||||
"${_plugin_versionless_is_whitelisted},"
|
||||
"${_plugin_is_in_type_whitelist},"
|
||||
"${_plugin_versionless_is_in_type_whitelist},"
|
||||
"$<AND:"
|
||||
"${_default_plugins_are_enabled},"
|
||||
"${_plugin_is_default},"
|
||||
"${_plugin_is_not_blacklisted}"
|
||||
">"
|
||||
">"
|
||||
">>"
|
||||
)
|
||||
|
||||
# If this condition is true, we link against the plug-in
|
||||
set(_plugin_genex "$<${_plugin_condition}:${_plugin_target}>")
|
||||
target_link_libraries(${_module_target} INTERFACE "${_plugin_genex}")
|
||||
|
||||
set(_generated_qt_plugin_file_name
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/qt_@QT_MODULE@_${target}.cpp")
|
||||
set(_generated_qt_plugin_file_content "#include <QtPlugin>\nQ_IMPORT_PLUGIN(${_classname})")
|
||||
|
||||
# Generate a source file to import that plug-in. Be careful not to
|
||||
# update the timestamp of the generated file if we are not going to
|
||||
# change anything. Otherwise we will trigger CMake's autogen to re-run
|
||||
# and executables will then need to at least relink.
|
||||
set(need_write TRUE)
|
||||
if(EXISTS ${_generated_qt_plugin_file_name})
|
||||
file(READ ${_generated_qt_plugin_file_name} old_contents)
|
||||
if(old_contents STREQUAL "${_generated_qt_plugin_file_content}")
|
||||
set(need_write FALSE)
|
||||
endif()
|
||||
endif()
|
||||
if(need_write)
|
||||
file(WRITE "${_generated_qt_plugin_file_name}"
|
||||
"${_generated_qt_plugin_file_content}")
|
||||
endif()
|
||||
|
||||
target_sources(${_module_target} INTERFACE
|
||||
"$<${_plugin_condition}:${_generated_qt_plugin_file_name}>")
|
||||
__qt_internal_add_static_plugin_linkage("${plugin_target}" "${_module_target}")
|
||||
__qt_internal_add_static_plugin_import_macro(
|
||||
"${plugin_target}" ${_module_target} "@QT_MODULE@")
|
||||
endforeach()
|
||||
|
||||
set("QT_ALL_PLUGINS_FOUND_BY_FIND_PACKAGE_${__plugin_type}"
|
||||
"${QT_ALL_PLUGINS_FOUND_BY_FIND_PACKAGE_${__plugin_type}}"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set_target_properties(${_module_target} PROPERTIES __qt_internal_plugins_added TRUE)
|
||||
endfunction()
|
||||
|
||||
|
156
cmake/QtPublicPluginHelpers.cmake
Normal file
156
cmake/QtPublicPluginHelpers.cmake
Normal file
@ -0,0 +1,156 @@
|
||||
function(__qt_internal_plugin_get_plugin_type
|
||||
plugin_target
|
||||
out_var_has_plugin_type
|
||||
out_var_plugin_type)
|
||||
set(has_plugin_type TRUE)
|
||||
|
||||
set(plugin_target_versioned "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}")
|
||||
|
||||
get_target_property(_plugin_type "${plugin_target_versioned}" QT_PLUGIN_TYPE)
|
||||
if(NOT _plugin_type)
|
||||
message("Warning: plugin ${plugin_target_versioned} has no plugin type set, skipping.")
|
||||
set(has_plugin_type FALSE)
|
||||
else()
|
||||
set(${out_var_plugin_type} "${_plugin_type}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
set(${out_var_has_plugin_type} "${has_plugin_type}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(__qt_internal_plugin_has_class_name plugin_target out_var)
|
||||
|
||||
set(plugin_target_versioned "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}")
|
||||
|
||||
get_target_property(classname "${plugin_target_versioned}" QT_PLUGIN_CLASS_NAME)
|
||||
if(NOT classname)
|
||||
message("Warning: plugin ${plugin_target_versioned} has no class name, skipping.")
|
||||
endif()
|
||||
|
||||
# If unset, it will be -NOTFOUND and still evaluate to false.
|
||||
set(${out_var} "${classname}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(__qt_internal_get_static_plugin_condition_genex
|
||||
plugin_target_unprefixed
|
||||
out_var)
|
||||
|
||||
set(plugin_target "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target_unprefixed}")
|
||||
set(plugin_target_versionless "Qt::${plugin_target_unprefixed}")
|
||||
|
||||
get_target_property(_plugin_type "${plugin_target}" QT_PLUGIN_TYPE)
|
||||
|
||||
set(_default_plugins_are_enabled
|
||||
"$<NOT:$<STREQUAL:$<GENEX_EVAL:$<TARGET_PROPERTY:QT_DEFAULT_PLUGINS>>,0>>")
|
||||
set(_manual_plugins_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:QT_PLUGINS>>")
|
||||
set(_no_plugins_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:QT_NO_PLUGINS>>")
|
||||
|
||||
# Plugin genex marker for prl processing.
|
||||
set(_is_plugin_marker_genex "$<BOOL:QT_IS_PLUGIN_GENEX>")
|
||||
|
||||
# The code in here uses the properties defined in qt_import_plugins (Qt6CoreMacros.cmake)
|
||||
set(_plugin_is_default "$<TARGET_PROPERTY:${plugin_target},QT_DEFAULT_PLUGIN>")
|
||||
|
||||
# INCLUDE
|
||||
set(_plugin_is_whitelisted "$<IN_LIST:${plugin_target},${_manual_plugins_genex}>")
|
||||
set(_plugin_versionless_is_whitelisted
|
||||
"$<IN_LIST:${plugin_target_versionless},${_manual_plugins_genex}>")
|
||||
|
||||
# Note: qt_import_plugins sets the QT_PLUGINS_${_plugin_type} to "-"
|
||||
# when excluding it with EXCLUDE_BY_TYPE,
|
||||
# which ensures that no plug-in will be supported unless explicitly re-added afterwards.
|
||||
string(CONCAT _plugin_is_not_blacklisted
|
||||
"$<AND:"
|
||||
"$<NOT:" # EXCLUDE
|
||||
"$<IN_LIST:${plugin_target},${_no_plugins_genex}>"
|
||||
">,"
|
||||
"$<NOT:"
|
||||
"$<IN_LIST:${plugin_target_versionless},${_no_plugins_genex}>"
|
||||
">,"
|
||||
# Excludes both plugins targeted by EXCLUDE_BY_TYPE and not included in
|
||||
# INCLUDE_BY_TYPE.
|
||||
"$<STREQUAL:,$<GENEX_EVAL:$<TARGET_PROPERTY:QT_PLUGINS_${_plugin_type}>>>"
|
||||
">"
|
||||
)
|
||||
|
||||
# Support INCLUDE_BY_TYPE
|
||||
string(CONCAT _plugin_is_in_type_whitelist
|
||||
"$<IN_LIST:"
|
||||
"${plugin_target},"
|
||||
"$<GENEX_EVAL:"
|
||||
"$<TARGET_PROPERTY:QT_PLUGINS_${_plugin_type}>"
|
||||
">"
|
||||
">"
|
||||
)
|
||||
string(CONCAT _plugin_versionless_is_in_type_whitelist
|
||||
"$<IN_LIST:"
|
||||
"${plugin_target_versionless},"
|
||||
"$<GENEX_EVAL:"
|
||||
"$<TARGET_PROPERTY:QT_PLUGINS_${_plugin_type}>"
|
||||
">"
|
||||
">"
|
||||
)
|
||||
|
||||
# Complete condition that defines whether a static plugin is linked
|
||||
string(CONCAT _plugin_condition
|
||||
"$<BOOL:$<AND:"
|
||||
"${_is_plugin_marker_genex},"
|
||||
"$<OR:"
|
||||
"${_plugin_is_whitelisted},"
|
||||
"${_plugin_versionless_is_whitelisted},"
|
||||
"${_plugin_is_in_type_whitelist},"
|
||||
"${_plugin_versionless_is_in_type_whitelist},"
|
||||
"$<AND:"
|
||||
"${_default_plugins_are_enabled},"
|
||||
"${_plugin_is_default},"
|
||||
"${_plugin_is_not_blacklisted}"
|
||||
">"
|
||||
">"
|
||||
">>"
|
||||
)
|
||||
|
||||
set(${out_var} "${_plugin_condition}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(__qt_internal_add_static_plugin_linkage plugin_target qt_module_target)
|
||||
__qt_internal_get_static_plugin_condition_genex("${plugin_target}" plugin_condition)
|
||||
|
||||
set(plugin_target "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}")
|
||||
|
||||
# If this condition is true, we link against the plug-in
|
||||
set(plugin_genex "$<${plugin_condition}:${plugin_target}>")
|
||||
target_link_libraries(${qt_module_target} INTERFACE "${plugin_genex}")
|
||||
endfunction()
|
||||
|
||||
function(__qt_internal_add_static_plugin_import_macro
|
||||
plugin_target
|
||||
qt_module_target
|
||||
qt_module_unprefixed)
|
||||
set(_generated_qt_plugin_file_name
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/qt_${qt_module_unprefixed}_${plugin_target}.cpp")
|
||||
|
||||
set(plugin_target_versioned "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}")
|
||||
get_target_property(class_name "${plugin_target_versioned}" QT_PLUGIN_CLASS_NAME)
|
||||
|
||||
set(_generated_qt_plugin_file_content "#include <QtPlugin>\nQ_IMPORT_PLUGIN(${class_name})")
|
||||
|
||||
# Generate a source file to import that plug-in. Be careful not to
|
||||
# update the timestamp of the generated file if we are not going to
|
||||
# change anything. Otherwise we will trigger CMake's autogen to re-run
|
||||
# and executables will then need to at least relink.
|
||||
set(need_write TRUE)
|
||||
if(EXISTS ${_generated_qt_plugin_file_name})
|
||||
file(READ ${_generated_qt_plugin_file_name} old_contents)
|
||||
if(old_contents STREQUAL "${_generated_qt_plugin_file_content}")
|
||||
set(need_write FALSE)
|
||||
endif()
|
||||
endif()
|
||||
if(need_write)
|
||||
file(WRITE "${_generated_qt_plugin_file_name}"
|
||||
"${_generated_qt_plugin_file_content}")
|
||||
endif()
|
||||
|
||||
__qt_internal_get_static_plugin_condition_genex("${plugin_target}" plugin_condition)
|
||||
|
||||
target_sources(${qt_module_target} INTERFACE
|
||||
"$<${plugin_condition}:${_generated_qt_plugin_file_name}>")
|
||||
endfunction()
|
Loading…
Reference in New Issue
Block a user