CMake: Create plugin initializers for static user plugins

Previously we only created object library static plugin initializers
for Qt plugins only, not user-project plugins.

The reason was that if a user tried to install the plugin target via
an export set, CMake would error out saying that the _init library is
not part of the same export set.

Introduce an OUTPUT_TARGETS option that would allow projects to get
the name of the generated _init target, so they can install it if
needed.
This was already done for qt6_add_qml_module, so we just introduce the
same option for qt6_add_plugin.

Now user static plugins will have an _init target created, which will
be propagated to consumers whenever the consumers link against the
plugin itself.

We also need an internal option to disable this propagation, because
it's handled a bit differently for Qt plugins which can be linked
either via finalizers or via usage requirements.

Amends 91c65dd80c

As a result of the implementation change, cleanup example projects
to ensure that they build successfully (the important part is
specifying the CLASS_NAME).

Only plugandpaint works properly with both shared and static Qt
builds.

echoplugin works with a shared Qt build, but not a static one due to
some assumptions in the C++ code about shared plugins.

styleplugin doesn't seem to work properly neither with shared Qt
builds nor static Qt builds, at least on macOS. But it builds fine.
For some reason even if the plugin is found, the style is not applied.

Amends 4caac1feea

Pick-to: 6.2
Task-number: QTBUG-80863
Task-number: QTBUG-92933
Change-Id: I6f631cda9566229b7a63992b23d7d7fa50303eeb
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Alexandru Croitor 2021-08-19 11:42:12 +02:00
parent 511bbbdfc0
commit 3c1125d9fe
13 changed files with 92 additions and 138 deletions

View File

@ -76,6 +76,14 @@ function(qt_internal_add_plugin target)
ARGS
${ARGN}
)
# When creating a static plugin, retrieve the plugin initializer target name, but don't
# automatically propagate the plugin initializer.
list(APPEND plugin_args
__QT_INTERNAL_NO_PROPAGATE_PLUGIN_INITIALIZER
OUTPUT_TARGETS plugin_init_target
)
qt6_add_plugin(${target} ${plugin_args})
qt_internal_mark_as_internal_library(${target})
@ -334,7 +342,6 @@ function(qt_internal_add_plugin target)
endforeach()
qt_register_target_dependencies("${target}" "${arg_PUBLIC_LIBRARIES}" "${qt_libs_private}")
set(plugin_init_target "")
if (NOT BUILD_SHARED_LIBS)
# There's no point in generating pri files for qml plugins. We didn't do it in Qt5 times.
@ -343,7 +350,6 @@ function(qt_internal_add_plugin target)
endif()
if(qt_module_target)
__qt_internal_add_static_plugin_init_object_library("${target}" plugin_init_target)
qt_internal_link_internal_platform_for_object_library("${plugin_init_target}")
endif()
endif()

View File

@ -1,4 +1,15 @@
# Generated from echoplugin.pro.
cmake_minimum_required(VERSION 3.16)
project(plugandpaint LANGUAGES CXX)
qt_internal_add_example(echowindow)
qt_internal_add_example(plugin)
find_package(Qt6 COMPONENTS Core Gui Widgets)
set(CMAKE_AUTOMOC ON)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tools/echoplugin")
add_subdirectory(plugin)
add_subdirectory(echowindow)

View File

@ -1,41 +1,25 @@
# Generated from echowindow.pro.
cmake_minimum_required(VERSION 3.16)
project(echoplugin LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tools/echoplugin")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
find_package(Qt6 COMPONENTS Widgets)
qt_add_executable(echopluginwindow # special case: renamed target
qt_add_executable(echopluginwindow
echointerface.h
echowindow.cpp echowindow.h
main.cpp
)
set_target_properties(echopluginwindow PROPERTIES # special case
set_target_properties(echopluginwindow PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(echopluginwindow PUBLIC # special case
target_link_libraries(echopluginwindow PRIVATE
Qt::Core
Qt::Gui
Qt::Widgets
)
install(TARGETS echopluginwindow # special case: renamed target
if(NOT QT6_IS_SHARED_LIBS_BUILD)
target_link_libraries(echopluginwindow PRIVATE
echoplugin
)
endif()
install(TARGETS echopluginwindow
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -1,31 +1,11 @@
# Generated from plugin.pro.
cmake_minimum_required(VERSION 3.16)
project(echoplugin LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tools/echoplugin/plugins")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
find_package(Qt6 COMPONENTS Widgets)
qt_add_plugin(echoplugin)
qt_add_plugin(echoplugin
CLASS_NAME EchoPlugin
)
target_sources(echoplugin PRIVATE
echoplugin.cpp echoplugin.h
)
set_target_properties(echoplugin PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/echowindow"
)
target_include_directories(echoplugin PUBLIC
../echowindow
@ -39,6 +19,5 @@ target_link_libraries(echoplugin PUBLIC
install(TARGETS echoplugin
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -1,5 +1,3 @@
# Generated from plugandpaint.pro.
# special case skip regeneration
cmake_minimum_required(VERSION 3.16)
project(plugandpaint LANGUAGES CXX)

View File

@ -1,6 +1,3 @@
# Generated from app.pro.
# special case skip regeneration
qt_add_executable(plugandpaint
interfaces.h
main.cpp
@ -12,13 +9,18 @@ set_target_properties(plugandpaint PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(plugandpaint PUBLIC
target_link_libraries(plugandpaint PRIVATE
Qt::Widgets
pnp_basictools
)
if(NOT QT6_IS_SHARED_LIBS_BUILD)
target_link_libraries(plugandpaint PRIVATE
pnp_extrafilters
)
endif()
install(TARGETS plugandpaint
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -1,4 +1,2 @@
# Generated from plugins.pro.
add_subdirectory(basictools)
add_subdirectory(extrafilters)

View File

@ -1,19 +1,15 @@
# Generated from basictools.pro.
# special case skip regeneration
qt_add_plugin(pnp_basictools STATIC)
qt_add_plugin(pnp_basictools
STATIC
CLASS_NAME BasicToolsPlugin
)
target_sources(pnp_basictools PRIVATE
basictoolsplugin.cpp basictoolsplugin.h
)
set_target_properties(pnp_basictools PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_include_directories(pnp_basictools PUBLIC
../../app
)
target_link_libraries(pnp_basictools PUBLIC
target_link_libraries(pnp_basictools PRIVATE
Qt::Core
Qt::Gui
Qt::Widgets

View File

@ -1,19 +1,17 @@
# Generated from extrafilters.pro.
# special case skip regeneration
qt_add_plugin(pnp_extrafilters)
qt_add_plugin(pnp_extrafilters
CLASS_NAME ExtraFiltersPlugin
)
target_sources(pnp_extrafilters PRIVATE
extrafiltersplugin.cpp extrafiltersplugin.h
)
set_target_properties(pnp_extrafilters PROPERTIES
MACOSX_BUNDLE TRUE
LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/app"
)
target_include_directories(pnp_extrafilters PUBLIC
../../app
)
target_link_libraries(pnp_extrafilters PUBLIC
target_link_libraries(pnp_extrafilters PRIVATE
Qt::Core
Qt::Gui
Qt::Widgets

View File

@ -1,19 +1,15 @@
# Generated from styleplugin.pro.
# special case begin
cmake_minimum_required(VERSION 3.16)
project(styleplugin LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(Qt6 COMPONENTS Widgets)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(INSTALL_EXAMPLEDIR "examples")
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
find_package(Qt6 COMPONENTS Widgets)
# special case end
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tools/styleplugin")
add_subdirectory(stylewindow)
add_subdirectory(plugin)

View File

@ -1,34 +1,14 @@
# Generated from plugin.pro.
cmake_minimum_required(VERSION 3.16)
project(simplestyleplugin LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tools/styleplugin/styles")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
find_package(Qt6 COMPONENTS Widgets)
qt_add_plugin(simplestyleplugin)
qt_add_plugin(simplestyleplugin
CLASS_NAME SimpleStylePlugin
)
target_sources(simplestyleplugin PRIVATE
simplestyle.cpp simplestyle.h
simplestyleplugin.cpp simplestyleplugin.h
)
set_target_properties(simplestyleplugin PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/stylewindow/styles"
)
target_link_libraries(simplestyleplugin PUBLIC
target_link_libraries(simplestyleplugin PRIVATE
Qt::Core
Qt::Gui
Qt::Widgets
@ -36,6 +16,5 @@ target_link_libraries(simplestyleplugin PUBLIC
install(TARGETS simplestyleplugin
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -1,24 +1,3 @@
# Generated from stylewindow.pro.
cmake_minimum_required(VERSION 3.16)
project(styleplugin LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tools/styleplugin")
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
find_package(Qt6 COMPONENTS Widgets)
qt_add_executable(styleplugin
main.cpp
stylewindow.cpp stylewindow.h
@ -27,14 +6,18 @@ set_target_properties(styleplugin PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(styleplugin PUBLIC
target_link_libraries(styleplugin PRIVATE
Qt::Core
Qt::Gui
Qt::Widgets
)
if(NOT QT6_IS_SHARED_LIBS_BUILD)
target_link_libraries(styleplugin PRIVATE
simplestyleplugin
)
endif()
install(TARGETS styleplugin
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -1833,6 +1833,7 @@ macro(_qt_internal_get_add_plugin_keywords option_args single_args multi_args)
set(${option_args}
STATIC
SHARED
__QT_INTERNAL_NO_PROPAGATE_PLUGIN_INITIALIZER
)
set(${single_args}
# TODO: For backward compatibility / transitional use only, remove once all repos no longer
@ -1842,6 +1843,7 @@ macro(_qt_internal_get_add_plugin_keywords option_args single_args multi_args)
PLUGIN_TYPE
CLASS_NAME
OUTPUT_NAME
OUTPUT_TARGETS
)
set(${multi_args})
endmacro()
@ -1951,6 +1953,28 @@ function(qt6_add_plugin target)
set_target_properties(${target} PROPERTIES QT_PLUGIN_CLASS_NAME "${plugin_class_name}")
# Create a plugin initializer object library for static plugins.
# It contains a Q_IMPORT_PLUGIN(QT_PLUGIN_CLASS_NAME) call.
# Project targets will automatically link to the plugin initializer whenever they link to the
# plugin target.
# The plugin init target name is stored in OUTPUT_TARGETS, so projects may install them.
# Qml plugin inits are handled in Qt6QmlMacros.
if(NOT "${arg_PLUGIN_TYPE}" STREQUAL "qml_plugin"
AND target_type STREQUAL "STATIC_LIBRARY")
__qt_internal_add_static_plugin_init_object_library("${target}" plugin_init_target)
if(arg_OUTPUT_TARGETS)
set(${arg_OUTPUT_TARGETS} ${plugin_init_target} PARENT_SCOPE)
endif()
# We don't automatically propagate the plugin init library for Qt provided plugins, because
# there are 2 other code paths that take care of that, one involving finalizers and the
# other regular usage requirements.
if(NOT arg___QT_INTERNAL_NO_PROPAGATE_PLUGIN_INITIALIZER)
__qt_internal_propagate_object_library("${target}" "${plugin_init_target}")
endif()
endif()
target_compile_definitions(${target} PRIVATE
QT_PLUGIN
QT_DEPRECATED_WARNINGS