Match qt_import_plugin API with qt5's

Some work was needed to make the plug-in types,
and which plug-ins are available for each type
in client code.

Change-Id: Ib71feca31069deca3d3f54c8613054f5f8ae410c
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Qt CMake Build Bot
This commit is contained in:
Jean-Michaël Celerier 2019-09-23 16:57:06 +02:00 committed by Alexandru Croitor
parent b7adc85642
commit d1542e8a73
5 changed files with 148 additions and 25 deletions

View File

@ -159,8 +159,32 @@ macro(qt_internal_set_qt_known_plugins)
set(QT_KNOWN_PLUGINS ${ARGN} CACHE INTERNAL "Known Qt plugins" FORCE)
endmacro()
### Global plug-in types handling ###
# QT_REPO_KNOWN_PLUGIN_TYPES and QT_ALL_PLUGIN_TYPES_FOUND_VIA_FIND_PACKAGE
# hold a list of plug-in types (e.G. "imageformats;bearer")
function(qt_internal_clear_qt_repo_known_plugin_types)
set(QT_REPO_KNOWN_PLUGIN_TYPES "" CACHE INTERNAL "Known current repo Qt plug-in types" FORCE)
endfunction()
function(qt_internal_add_qt_repo_known_plugin_types)
set(QT_REPO_KNOWN_PLUGIN_TYPES ${QT_REPO_KNOWN_PLUGIN_TYPES} ${ARGN}
CACHE INTERNAL "Known current repo Qt plug-in types" FORCE)
endfunction()
function(qt_internal_get_qt_repo_known_plugin_types out_var)
set("${out_var}" "${QT_REPO_KNOWN_PLUGIN_TYPES}" PARENT_SCOPE)
endfunction()
function(qt_internal_get_qt_all_known_plugin_types out_var)
qt_internal_get_qt_repo_known_plugin_types(repo_known_plugin_types)
set(known ${QT_ALL_PLUGIN_TYPES_FOUND_VIA_FIND_PACKAGE} ${repo_known_plugin_types})
list(REMOVE_DUPLICATES known)
set("${out_var}" "${known}" PARENT_SCOPE)
endfunction()
# Reset:
qt_internal_clear_qt_repo_known_modules("")
qt_internal_clear_qt_repo_known_modules()
qt_internal_clear_qt_repo_known_plugin_types()
qt_internal_set_qt_known_plugins("")
set(QT_KNOWN_MODULES_WITH_TOOLS "" CACHE INTERNAL "Known Qt modules with tools" FORCE)
@ -1342,7 +1366,14 @@ function(add_qt_module target)
if(NOT arg_HEADER_MODULE)
# Plugin types associated to a module
if(NOT "x${arg_PLUGIN_TYPES}" STREQUAL "x")
set_target_properties("${target}" PROPERTIES MODULE_PLUGIN_TYPES "${arg_PLUGIN_TYPES}")
# Reset the variable containing the list of plugins for the given plugin type
foreach(plugin_type ${arg_PLUGIN_TYPES})
# Used to handle some edge cases such as platforms/darwin
string(REGEX REPLACE "[-/]" "_" plugin_type "${plugin_type}")
set_property(TARGET "${target}" APPEND PROPERTY MODULE_PLUGIN_TYPES "${plugin_type}")
qt_internal_add_qt_repo_known_plugin_types("${plugin_type}")
endforeach()
endif()
set_target_properties("${target}" PROPERTIES
@ -1806,7 +1837,7 @@ function(add_qt_plugin target)
endif()
set_property(TARGET "${target}" PROPERTY QT_DEFAULT_PLUGIN "${_default_plugin}")
set_property(TARGET "${target}" APPEND PROPERTY EXPORT_PROPERTIES "QT_PLUGIN_CLASS_NAME;QT_MODULE;QT_DEFAULT_PLUGIN")
set_property(TARGET "${target}" APPEND PROPERTY EXPORT_PROPERTIES "QT_PLUGIN_CLASS_NAME;QT_PLUGIN_TYPE;QT_MODULE;QT_DEFAULT_PLUGIN")
set(private_includes
"${CMAKE_CURRENT_SOURCE_DIR}"
@ -1909,6 +1940,9 @@ function(add_qt_plugin target)
DESTINATION "${config_install_dir}"
)
# Store the plug-in type in the target property
set_property(TARGET "${target}" PROPERTY QT_PLUGIN_TYPE "${arg_TYPE}")
### fixme: cmake is missing a built-in variable for this. We want to apply it only to modules and plugins
# that belong to Qt.
qt_internal_add_link_flags_no_undefined("${target}")

View File

@ -40,3 +40,8 @@ endif()
unset(_QT_NEED_TO_INCLUDE_PLUGINS_@target@)
list(APPEND QT_ALL_MODULES_FOUND_VIA_FIND_PACKAGE "@target@")
get_target_property(_qt_module_plugin_types @INSTALL_CMAKE_NAMESPACE@::@target@ MODULE_PLUGIN_TYPES)
if(_qt_module_plugin_types)
list(APPEND QT_ALL_PLUGIN_TYPES_FOUND_VIA_FIND_PACKAGE "${_qt_module_plugin_types}")
endif()

View File

@ -10,13 +10,14 @@ if(NOT @BUILD_SHARED_LIBS@)
endif()
unset(_aliased_target)
set(_default_plugins_are_enabled "$<GENEX_EVAL:$<TARGET_PROPERTY:QT_DEFAULT_PLUGINS>>")
set(_default_plugins_are_enabled "$<NOT:$<STREQUAL:$<GENEX_EVAL:$<TARGET_PROPERTY:QT_DEFAULT_PLUGINS>>,0>>")
# Make sure to boolify the result of the expression, in case if the returned property value
# is empty.
set(_default_plugins_are_enabled_wrapped "$<BOOL:${_default_plugins_are_enabled}>")
set(_manual_plugins_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:QT_PLUGINS>>")
set(_no_plugins_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:QT_NO_PLUGINS>>")
# 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}")
get_target_property(_classname "${_plugin_target}" QT_PLUGIN_CLASS_NAME)
@ -25,22 +26,60 @@ if(NOT @BUILD_SHARED_LIBS@)
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()
endif()
list(APPEND "QT_ALL_PLUGINS_FOUND_BY_FIND_PACKAGE_${_plugin_type}" "${target}")
set(_plugin_is_default "$<TARGET_PROPERTY:${_plugin_target},QT_DEFAULT_PLUGIN>")
set(_plugin_is_not_blacklisted "$<NOT:$<IN_LIST:${_plugin_target},${_no_plugins_genex}>>")
# INCLUDE
set(_plugin_is_whitelisted "$<IN_LIST:${_plugin_target},${_manual_plugins_genex}>")
string(CONCAT _plugin_condition
"$<BOOL:$<OR:"
"${_plugin_is_whitelisted},"
"$<AND:"
"${_default_plugins_are_enabled_wrapped},"
"${_plugin_is_default},"
"${_plugin_is_not_blacklisted}"
">"
">>"
# 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}>"
">,"
# 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}>"
">"
">"
)
# Complete condition that defines whether a static plugin is linked
string(CONCAT _plugin_condition
"$<BOOL:$<OR:"
"${_plugin_is_whitelisted},"
"${_plugin_is_in_type_whitelist},"
"$<AND:"
"${_default_plugins_are_enabled_wrapped},"
"${_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}")
# Generate a source file to import that plug-in
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/qt_@QT_MODULE@_${target}.cpp"
CONTENT "#include <QtPlugin>\nQ_IMPORT_PLUGIN(${_classname})"

View File

@ -28,6 +28,16 @@ define_property(TARGET
For instance, QICOPlugin for the qico plug-in"
)
define_property(TARGET
PROPERTY
QT_PLUGIN_TYPE
BRIEF_DOCS
"Type of the Qt plug-in"
FULL_DOCS
"This is a property on Qt plug-ins.
For example, the value of the QT_PLUGIN_TYPE property on the qico plugin is \"imageformats\""
)
define_property(TARGET
PROPERTY
QT_MODULE

View File

@ -430,35 +430,70 @@ macro(_qt_import_plugin target plugin)
get_target_property(plugin_class_name "${plugin}" QT_PLUGIN_CLASS_NAME)
if(plugin_class_name)
set_property(TARGET "${target}" APPEND PROPERTY QT_PLUGINS "${plugin}")
# TODO mark it for installation
# TODO also in shared builds
endif()
endmacro()
# This function is used to indicate which plug-ins are going to be
# used by a given target.
# This allows both automatic static linking, and automatic installation of relevant
# plug-ins.
# This allows static linking to a correct set of plugins.
# Options :
# NO_DEFAULT: won't link against any plug-in by default for that target, e.g. no platform plug-in.
# INCLUDE: list of additional plug-ins to be linked against.
# EXCLUDE: list of plug-ins to be removed from the default set.
# NO_DEFAULT: disable linking against any plug-in by default for that target, e.g. no platform plug-in.
# INCLUDE <list of additional plug-ins to be linked against>
# EXCLUDE <list of plug-ins to be removed from the default set>
# INCLUDE_BY_TYPE <type> <included plugins>
# EXCLUDE_BY_TYPE <type to be excluded>
#
# Example :
# qt_import_plugins(myapp
# INCLUDE Qt::QCocoaIntegrationPlugin
# EXCLUDE Qt::QMinimalIntegrationPlugin
# INCLUDE_BY_TYPE imageformats Qt::QGifPlugin Qt::QJpegPlugin
# EXCLUDE_BY_TYPE sqldrivers
# )
# TODO : support qml plug-ins.
function(qt_import_plugins target)
cmake_parse_arguments(arg "NO_DEFAULT" "" "INCLUDE;EXCLUDE" ${ARGN})
cmake_parse_arguments(arg "NO_DEFAULT" "" "INCLUDE;EXCLUDE;INCLUDE_BY_TYPE;EXCLUDE_BY_TYPE" ${ARGN})
# Handle NO_DEFAULT
if(${arg_NO_DEFAULT})
set_target_properties(${target} PROPERTIES QT_DEFAULT_PLUGINS 0)
else()
set_target_properties(${target} PROPERTIES QT_DEFAULT_PLUGINS 1)
endif()
# Handle INCLUDE
foreach(plugin ${arg_INCLUDE})
_qt_import_plugin("${target}" "${plugin}")
endforeach()
# Handle EXCLUDE
foreach(plugin ${arg_EXCLUDE})
set_property(TARGET "${target}" APPEND PROPERTY QT_NO_PLUGINS "${plugin}")
endforeach()
endfunction()
# Handle INCLUDE_BY_TYPE
set(_current_type "")
foreach(_arg ${arg_INCLUDE_BY_TYPE})
string(REGEX REPLACE "[-/]" "_" _plugin_type "${_arg}")
list(FIND QT_ALL_PLUGIN_TYPES_FOUND_VIA_FIND_PACKAGE "${_plugin_type}" _has_plugin_type)
if(${_has_plugin_type} GREATER_EQUAL 0)
set(_current_type "${_plugin_type}")
else()
if("${_current_type}" STREQUAL "")
message(FATAL_ERROR "qt_import_plugins: invalid syntax for INCLUDE_BY_TYPE")
endif()
if(TARGET "${_arg}")
set_property(TARGET "${target}" APPEND PROPERTY "QT_PLUGINS_${_current_type}" "${_arg}")
else()
message("Warning: plug-in ${_arg} is not known to the current Qt installation.")
endif()
endif()
endforeach()
# Handle EXCLUDE_BY_TYPE
foreach(_arg ${arg_EXCLUDE_BY_TYPE})
string(REGEX REPLACE "[-/]" "_" _plugin_type "${_arg}")
set_property(TARGET "${target}" PROPERTY "QT_PLUGINS_${_plugin_type}" "-")
endforeach()
endfunction()