From d0085f26081b62e0d653cd7cacfd1f6ce9074b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Thu, 23 Jan 2025 14:47:01 +0100 Subject: [PATCH] Use qt_add_plugin Among other things that are probably more appropriate for Qt plugins, this changes the plugin's extension on macOS from .so to .dylib, which will hopefully cause it to be automatically shipped by macdeployqt. Based on @Nerixyz's work in https://github.com/jurplel/QtApng/pull/4. Changed target name from qaseprite to AsepriteImagePlugin to match the class name, since the CLASS_NAME parameter wasn't working correctly with qt5_add_plugin. Closes #8 --- CMakeLists.txt | 22 +++++++--- cmake/Qt5Plugin.cmake | 93 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 cmake/Qt5Plugin.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 042fe78..030cba0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -280,13 +280,23 @@ add_subdirectory(aseprite/src/dio EXCLUDE_FROM_ALL) # qaseprite specific setup # ------------------------ -add_library(qaseprite MODULE - qaseprite.cpp - qaseprite.json +if(QT_VERSION_MAJOR EQUAL 5) + include(cmake/Qt5Plugin.cmake) +endif() + +qt_add_plugin(AsepriteImagePlugin SHARED) + +# For Qt 6.0-6.4, qt_add_plugin didn't support adding the sources directly, +# hence we add them using target_sources instead. +target_sources(AsepriteImagePlugin + PRIVATE qaseprite.cpp + qaseprite.json ) -set_target_properties(qaseprite PROPERTIES AUTOMOC ON) -target_link_libraries(qaseprite +set_target_properties(AsepriteImagePlugin PROPERTIES + AUTOMOC ON + LIBRARY_OUTPUT_NAME qaseprite) +target_link_libraries(AsepriteImagePlugin PRIVATE Qt${QT_VERSION_MAJOR}::Gui laf-base dio-lib @@ -318,6 +328,6 @@ if(NOT QT_PLUGIN_PATH) endif() install( - TARGETS qaseprite + TARGETS AsepriteImagePlugin RUNTIME DESTINATION "${QT_PLUGIN_PATH}/imageformats" LIBRARY DESTINATION "${QT_PLUGIN_PATH}/imageformats") diff --git a/cmake/Qt5Plugin.cmake b/cmake/Qt5Plugin.cmake new file mode 100644 index 0000000..9794299 --- /dev/null +++ b/cmake/Qt5Plugin.cmake @@ -0,0 +1,93 @@ +# This file contains the minimal code to compile a shared Qt plugin with CMake. +# It's based on qt6_add_plugin from Qt6 with all code not related to shared +# plugins (module libraries) removed. Internal functions have the prefix +# _qt_wrap instead of _qt. + +function(_qt_wrap_internal_apply_shared_win_prefix_and_suffix target) + if(WIN32 AND NOT MSVC) + set_property(TARGET "${target}" PROPERTY IMPORT_SUFFIX ".a") + set_property(TARGET "${target}" PROPERTY PREFIX "") + set_property(TARGET "${target}" PROPERTY IMPORT_PREFIX "lib") + endif() +endfunction() + +function(_qt_wrap_internal_set_up_static_runtime_library target) + if(QT_FEATURE_static_runtime) + if(MSVC) + set_property(TARGET ${target} PROPERTY + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + elseif(MINGW) + get_target_property(target_type ${target} TYPE) + if(target_type STREQUAL "EXECUTABLE") + set(link_option PRIVATE) + else() + set(link_option INTERFACE) + endif() + if(CLANG) + target_link_options(${target} ${link_option} "LINKER:-Bstatic") + else() + target_link_options(${target} ${link_option} "-static") + endif() + endif() + endif() +endfunction() + +function(qt5_add_plugin target) + cmake_parse_arguments(PARSE_ARGV 1 arg "SHARED" "" "") + + if(NOT arg_SHARED) + message(FATAL_ERROR "Only shared plugins can be built") + endif() + + add_library(${target} MODULE ${arg_UNPARSED_ARGUMENTS}) + _qt_wrap_internal_set_up_static_runtime_library(${target}) + _qt_wrap_internal_apply_shared_win_prefix_and_suffix("${target}") + + if(arg_MODULE AND APPLE) + # CMake defaults to using .so extensions for loadable modules, aka plugins, + # but Qt plugins are actually suffixed with .dylib. + set_property(TARGET "${target}" PROPERTY SUFFIX ".dylib") + endif() + + if(ANDROID) + set_property(TARGET "${target}" PROPERTY SUFFIX "_${CMAKE_ANDROID_ARCH_ABI}.so") + endif() + + set_property(TARGET ${target} PROPERTY _qt_expects_finalization TRUE) + + set(output_name ${target}) + if (arg_OUTPUT_NAME) + set(output_name ${arg_OUTPUT_NAME}) + endif() + set_property(TARGET "${target}" PROPERTY OUTPUT_NAME "${output_name}") + + if (ANDROID) + set_target_properties(${target} + PROPERTIES + LIBRARY_OUTPUT_NAME "plugins_${arg_PLUGIN_TYPE}_${output_name}" + ) + endif() + + # Derive the class name from the target name if it's not explicitly specified. + if (NOT arg_CLASS_NAME) + set(plugin_class_name "${target}") + else() + set(plugin_class_name "${arg_CLASS_NAME}") + endif() + + set_target_properties(${target} PROPERTIES QT_PLUGIN_CLASS_NAME "${plugin_class_name}") + + target_compile_definitions(${target} PRIVATE + QT_PLUGIN + QT_DEPRECATED_WARNINGS + ) + + if(NOT TARGET qt_wrap_internal_plugins) + add_custom_target(qt_wrap_internal_plugins) + endif() + add_dependencies(qt_wrap_internal_plugins ${target}) +endfunction() + +function(qt_add_plugin) + qt5_add_plugin(${ARGV}) +endfunction()