Warning, /frameworks/extra-cmake-modules/modules/ECMQmlModule5.cmake is written in an unsupported language. File is not indexed.

0001 #
0002 # SPDX-FileCopyrightText: 2021 Arjen Hiemstra <ahiemstra@heimr.nl>
0003 #
0004 # SPDX-License-Identifier: BSD-3-Clause
0005 
0006 # Qt 5 implementation of ECMQmlModule
0007 
0008 set(_ECM_QMLMODULE_STATIC_QMLONLY_H   "${CMAKE_CURRENT_LIST_DIR}/ECMQmlModule.h.in")
0009 set(_ECM_QMLMODULE_STATIC_QMLONLY_CPP "${CMAKE_CURRENT_LIST_DIR}/ECMQmlModule.cpp.in")
0010 
0011 set(_ECM_QMLMODULE_PROPERTY_URI "_ecm_qml_uri")
0012 set(_ECM_QMLMODULE_PROPERTY_QMLDIR "_ecm_qmldir_file")
0013 set(_ECM_QMLMODULE_PROPERTY_FILES "_ecm_qml_files")
0014 set(_ECM_QMLMODULE_PROPERTY_QMLONLY "_ecm_qml_only")
0015 set(_ECM_QMLMODULE_PROPERTY_VERSION "_ecm_qml_version")
0016 set(_ECM_QMLMODULE_PROPERTY_PRIVATE "_ecm_qml_private")
0017 set(_ECM_QMLMODULE_PROPERTY_PATH "_ecm_qml_path")
0018 set(_ECM_QMLMODULE_PROPERTY_CLASSNAME "_ecm_qml_classname")
0019 set(_ECM_QMLMODULE_PROPERTY_DEPENDS "_ecm_qml_depends")
0020 
0021 macro(_ecm_qmlmodule_verify_qml_target ARG_TARGET)
0022     if (NOT TARGET ${ARG_TARGET})
0023         message(FATAL_ERROR "Target ${ARG_TARGET} does not exist")
0024     endif()
0025     get_target_property(_qml_uri ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_URI})
0026     if ("${_qml_uri}" STREQUAL "" OR "${_qml_uri}" STREQUAL "${_ECM_QMLMODULE_PROPERTY_URI}-NOTFOUND")
0027         message(FATAL_ERROR "Target ${ARG_TARGET} is not a QML plugin target")
0028     endif()
0029 endmacro()
0030 
0031 function(_ecm_qmlmodule_generate_qmldir ARG_TARGET)
0032     get_target_property(_qml_uri ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_URI})
0033     get_target_property(_qml_files ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_FILES})
0034     get_target_property(_qml_only ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_QMLONLY})
0035     get_target_property(_qml_classname ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_CLASSNAME})
0036 
0037     set(_qmldir_template "# This file was automatically generated by ECMQmlModule and should not be modified")
0038 
0039     string(APPEND _qmldir_template "\nmodule ${_qml_uri}")
0040 
0041     if (NOT ${_qml_only})
0042         string(APPEND _qmldir_template "\nplugin ${ARG_TARGET}")
0043 
0044         if ("${_qml_classname}" STREQUAL "")
0045             string(APPEND _qmldir_template "\nclassname ${ARG_TARGET}")
0046         else()
0047             string(APPEND _qmldir_template "\nclassname ${_qml_classname}")
0048         endif()
0049     endif()
0050 
0051     get_target_property(_qml_depends ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_DEPENDS})
0052     if (NOT "${_qml_depends}" STREQUAL "")
0053         foreach(_depends ${_qml_depends})
0054             string(APPEND _qmldir_template "\ndepends ${_depends}")
0055         endforeach()
0056     endif()
0057 
0058     foreach(_file ${_qml_files})
0059         get_filename_component(_filename ${_file} NAME)
0060         get_filename_component(_classname ${_file} NAME_WE)
0061         get_property(_version SOURCE ${_file} PROPERTY ${_ECM_QMLMODULE_PROPERTY_VERSION})
0062         get_property(_private SOURCE ${_file} PROPERTY ${_ECM_QMLMODULE_PROPERTY_PRIVATE})
0063         get_property(_singleton SOURCE ${_file} PROPERTY "QT_QML_SINGLETON_TYPE")
0064         get_property(_path SOURCE ${_file} PROPERTY ${_ECM_QMLMODULE_PROPERTY_PATH})
0065         cmake_path(SET _actual_path "${_path}")
0066         cmake_path(APPEND _actual_path "${_filename}")
0067         if (_singleton)
0068             string(APPEND _qmldir_template "\nsingleton ${_classname} ${_version} ${_actual_path}")
0069         else()
0070             if (NOT _private)
0071                 string(APPEND _qmldir_template "\n${_classname} ${_version} ${_actual_path}")
0072             else()
0073                 string(APPEND _qmldir_template "\ninternal ${_classname} ${_actual_path}")
0074             endif()
0075         endif()
0076     endforeach()
0077     get_target_property(_qml_version ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_VERSION})
0078     string(APPEND _qmldir_template "\n# KDE-qmldir-Version: ${_qml_version}")
0079 
0080     string(APPEND _qmldir_template "\n")
0081 
0082     file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${ARG_TARGET}_qmldir" "${_qmldir_template}")
0083     set_target_properties(${ARG_TARGET} PROPERTIES _ecm_qmldir_file "${CMAKE_CURRENT_BINARY_DIR}/${ARG_TARGET}_qmldir")
0084 endfunction()
0085 
0086 function(_ecm_qmlmodule_generate_qrc ARG_TARGET)
0087     get_target_property(_qml_uri ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_URI})
0088     get_target_property(_qml_files ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_FILES})
0089     get_target_property(_qmldir_file ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_QMLDIR})
0090     get_target_property(_qml_version ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_VERSION})
0091 
0092     _ecm_qmlmodule_uri_to_path(_qml_prefix "${_qml_uri}" "${_qml_version}")
0093 
0094     set(_qrc_template "<!-- This file was automatically generated by ECMQmlModule and should not be modified -->")
0095 
0096     string(APPEND _qrc_template "\n<RCC>\n<qresource prefix=\"/qt-project.org/imports/${_qml_prefix}\">")
0097     string(APPEND _qrc_template "\n<file alias=\"qmldir\">${_qmldir_file}</file>")
0098 
0099     foreach(_file ${_qml_files})
0100         get_filename_component(_filename ${_file} NAME)
0101         get_property(_path SOURCE ${_file} PROPERTY ${_ECM_QMLMODULE_PROPERTY_PATH})
0102 
0103         set(_file_path "${_filename}")
0104         if (NOT "${_path}" STREQUAL "")
0105             set(_file_path "${_path}/${_filename}")
0106         endif()
0107 
0108         string(APPEND _qrc_template "\n<file alias=\"${_file_path}\">${_file}</file>")
0109     endforeach()
0110 
0111     string(APPEND _qrc_template "\n</qresource>\n</RCC>\n")
0112 
0113     file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${ARG_TARGET}.qrc" "${_qrc_template}")
0114     qt_add_resources(_qrc_output "${CMAKE_CURRENT_BINARY_DIR}/${ARG_TARGET}.qrc")
0115 
0116     target_sources(${ARG_TARGET} PRIVATE ${_qrc_output})
0117 endfunction()
0118 
0119 function(ecm_add_qml_module ARG_TARGET)
0120     cmake_parse_arguments(PARSE_ARGV 1 ARG "NO_PLUGIN" "URI;VERSION;CLASSNAME" "")
0121 
0122     if ("${ARG_TARGET}" STREQUAL "")
0123         message(FATAL_ERROR "ecm_add_qml_module called without a valid target name.")
0124     endif()
0125 
0126     if ("${ARG_URI}" STREQUAL "")
0127         message(FATAL_ERROR "ecm_add_qml_module called without a valid module URI.")
0128     endif()
0129 
0130     string(FIND "${ARG_URI}" " " "_space")
0131     if (${_space} GREATER_EQUAL 0)
0132         message(FATAL_ERROR "ecm_add_qml_module called without a valid module URI.")
0133     endif()
0134 
0135     if (${BUILD_SHARED_LIBS} AND ${ARG_NO_PLUGIN})
0136         # CMake doesn't like library targets without sources, so if we have no
0137         # C++ sources, use a plain target that we can add all the install stuff
0138         # to.
0139         add_custom_target(${ARG_TARGET} ALL)
0140     else()
0141         add_library(${ARG_TARGET})
0142     endif()
0143 
0144     if (NOT ARG_VERSION)
0145         set(ARG_VERSION "1.0")
0146     endif()
0147 
0148     set_target_properties(${ARG_TARGET} PROPERTIES
0149         ${_ECM_QMLMODULE_PROPERTY_URI} "${ARG_URI}"
0150         ${_ECM_QMLMODULE_PROPERTY_FILES} ""
0151         ${_ECM_QMLMODULE_PROPERTY_QMLONLY} "${ARG_NO_PLUGIN}"
0152         ${_ECM_QMLMODULE_PROPERTY_VERSION} "${ARG_VERSION}"
0153         ${_ECM_QMLMODULE_PROPERTY_CLASSNAME} "${ARG_CLASSNAME}"
0154         ${_ECM_QMLMODULE_PROPERTY_DEPENDS} ""
0155     )
0156 
0157     # QQmlImportDatabase::resolvePlugin doesn't accept lib prefixes under
0158     # Windows, causing to fail to import when using as a dynamic plugin.
0159     if (MINGW)
0160         set_target_properties(${ARG_TARGET} PROPERTIES PREFIX "")
0161     endif()
0162 
0163     # -Muri is required for static QML plugins to work properly, see
0164     # https://bugreports.qt.io/browse/QTBUG-82598
0165     set_target_properties(${ARG_TARGET} PROPERTIES AUTOMOC_MOC_OPTIONS -Muri=${ARG_URI})
0166 endfunction()
0167 
0168 function(ecm_add_qml_module_dependencies ARG_TARGET)
0169     cmake_parse_arguments(PARSE_ARGV 1 ARG "" "" "DEPENDS")
0170 
0171     _ecm_qmlmodule_verify_qml_target(${ARG_TARGET})
0172 
0173     if ("${ARG_DEPENDS}" STREQUAL "")
0174         message(FATAL_ERROR "ecm_add_qml_module_dependencies called without required argument DEPENDS")
0175     endif()
0176 
0177     set_target_properties(${ARG_TARGET} PROPERTIES ${_ECM_QMLMODULE_PROPERTY_DEPENDS} "${ARG_DEPENDS}")
0178 endfunction()
0179 
0180 function(ecm_target_qml_sources ARG_TARGET)
0181     cmake_parse_arguments(PARSE_ARGV 1 ARG "PRIVATE" "VERSION;PATH" "SOURCES")
0182 
0183     _ecm_qmlmodule_verify_qml_target(${ARG_TARGET})
0184 
0185     if ("${ARG_SOURCES}" STREQUAL "")
0186         message(FATAL_ERROR "ecm_target_qml_sources called without required argument SOURCES")
0187     endif()
0188 
0189     if ("${ARG_VERSION}" STREQUAL "")
0190         get_target_property(ARG_VERSION ${ARG_TARGET} "_ecm_qml_version")
0191     endif()
0192     # In case we have not specified a version in add_qml_module, we use 1.0 as a default for the individual QML files
0193     if (NOT ARG_VERSION)
0194         set(ARG_VERSION "1.0")
0195     endif()
0196 
0197     foreach(_file ${ARG_SOURCES})
0198         # Check if a given file exists, but only for files that are not
0199         # automatically generated.
0200         set(_path "${_file}")
0201         get_source_file_property(_generated ${_file} GENERATED)
0202         if (NOT _generated)
0203             if (IS_ABSOLUTE ${_path})
0204                 # Assume absolute paths are generated, which may not always be
0205                 # true but is fairly likely.
0206                 set(_generated TRUE)
0207             else()
0208                 string(FIND ${_file} ${CMAKE_BINARY_DIR} _in_binary_dir)
0209                 if (${_in_binary_dir} GREATER_EQUAL 0)
0210                     # Assume anything in binary dir is generated.
0211                     set(_generated TRUE)
0212                 else()
0213                     set(_path "${CMAKE_CURRENT_SOURCE_DIR}/${_file}")
0214                 endif()
0215             endif()
0216         endif()
0217 
0218         if (NOT ${_generated} AND NOT EXISTS ${_path})
0219             message(FATAL_ERROR "ecm_target_qml_sources called with nonexistent file ${_file}")
0220         endif()
0221 
0222         set_property(SOURCE ${_file} PROPERTY ${_ECM_QMLMODULE_PROPERTY_VERSION} "${ARG_VERSION}")
0223         if (ARG_PRIVATE)
0224             set_property(SOURCE ${_file} PROPERTY ${_ECM_QMLMODULE_PROPERTY_PRIVATE} TRUE)
0225         endif()
0226         set_property(SOURCE ${_file} PROPERTY ${_ECM_QMLMODULE_PROPERTY_PATH} "${ARG_PATH}")
0227         set_property(TARGET ${ARG_TARGET}
0228             APPEND PROPERTY ${_ECM_QMLMODULE_PROPERTY_FILES} ${_path}
0229         )
0230     endforeach()
0231 endfunction()
0232 
0233 function(ecm_finalize_qml_module ARG_TARGET)
0234     cmake_parse_arguments(PARSE_ARGV 1 ARG "" "DESTINATION" "")
0235 
0236     _ecm_qmlmodule_verify_qml_target(${ARG_TARGET})
0237 
0238     if (NOT ARG_DESTINATION)
0239         set(ARG_DESTINATION "${KDE_INSTALL_QMLDIR}")
0240     endif()
0241     if ("${ARG_DESTINATION}" STREQUAL "")
0242         message(FATAL_ERROR "ecm_finalize_qml_module called without argument DESTINATION and KDE_INSTALL_QMLDIR is not set")
0243     endif()
0244 
0245     get_target_property(_qml_uri ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_URI})
0246     get_target_property(_version ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_VERSION})
0247 
0248     _ecm_qmlmodule_generate_qmldir(${ARG_TARGET})
0249     _ecm_qmlmodule_uri_to_path(_plugin_path "${_qml_uri}" "${_version}")
0250 
0251     get_target_property(_qml_only ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_QMLONLY})
0252 
0253     if (NOT BUILD_SHARED_LIBS)
0254         _ecm_qmlmodule_generate_qrc(${ARG_TARGET})
0255         set(CPP_RESOURCE_INIT "#include <qglobal.h> \n#include <QDebug> \n void initQmlResource${ARG_TARGET}() {Q_INIT_RESOURCE(${ARG_TARGET}); qWarning()<<Q_FUNC_INFO;};")
0256         file(WRITE ${ARG_TARGET}_init.cpp "${CPP_RESOURCE_INIT}")
0257         target_sources(${ARG_TARGET} PRIVATE ${ARG_TARGET}_init.cpp)
0258         target_compile_definitions(${ARG_TARGET} PRIVATE -DQT_PLUGIN_RESOURCE_INIT_FUNCTION=initQmlResource${ARG_TARGET} -DQT_STATICPLUGIN=1)
0259 
0260         if (${_qml_only})
0261             # If we do not have any C++ sources for the target, we need a way to
0262             # compile the generated QRC file. So generate a very plain C++ QML
0263             # plugin that we include in the target.
0264             configure_file(${_ECM_QMLMODULE_STATIC_QMLONLY_H} ${CMAKE_CURRENT_BINARY_DIR}/QmlModule.h @ONLY)
0265             configure_file(${_ECM_QMLMODULE_STATIC_QMLONLY_CPP} ${CMAKE_CURRENT_BINARY_DIR}/QmlModule.cpp @ONLY)
0266 
0267             target_sources(${ARG_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/QmlModule.cpp)
0268             if (TARGET Qt::Qml)
0269                 target_link_libraries(${ARG_TARGET} PRIVATE Qt::Qml)
0270             else()
0271                 target_link_libraries(${ARG_TARGET} PRIVATE Qt5::Qml)
0272             endif()
0273         endif()
0274 
0275         install(TARGETS ${ARG_TARGET} DESTINATION ${ARG_DESTINATION}/${_plugin_path})
0276 
0277         return()
0278     endif()
0279 
0280     get_target_property(_runtime_output_dir ${ARG_TARGET} RUNTIME_OUTPUT_DIRECTORY)
0281     if (NOT ${_runtime_output_dir})
0282         if ("${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" STREQUAL "")
0283             set(_runtime_output_dir ${CMAKE_CURRENT_BINARY_DIR})
0284         else()
0285             set(_runtime_output_dir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
0286         endif()
0287     endif()
0288 
0289     add_custom_command(
0290         TARGET ${ARG_TARGET}
0291         POST_BUILD
0292         WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
0293         COMMAND ${CMAKE_COMMAND} -E make_directory ${_runtime_output_dir}/${_plugin_path}
0294         BYPRODUCTS ${_runtime_output_dir}/${_plugin_path}
0295     )
0296 
0297     get_target_property(_qmldir_file ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_QMLDIR})
0298     install(FILES ${_qmldir_file} DESTINATION ${ARG_DESTINATION}/${_plugin_path} RENAME "qmldir")
0299 
0300     add_custom_command(
0301         TARGET ${ARG_TARGET}
0302         POST_BUILD
0303         WORKING_DIRECTORY ${_runtime_output_dir}
0304         COMMAND ${CMAKE_COMMAND} -E copy ${_qmldir_file} ${_plugin_path}/qmldir
0305     )
0306 
0307     if (NOT ${_qml_only})
0308         install(TARGETS ${ARG_TARGET} DESTINATION ${ARG_DESTINATION}/${_plugin_path})
0309 
0310         add_custom_command(
0311             TARGET ${ARG_TARGET}
0312             POST_BUILD
0313             WORKING_DIRECTORY ${_runtime_output_dir}
0314             COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${ARG_TARGET}> ${_plugin_path}
0315         )
0316     endif()
0317 
0318     get_target_property(_qml_files ${ARG_TARGET} ${_ECM_QMLMODULE_PROPERTY_FILES})
0319     foreach(_file ${_qml_files})
0320         get_filename_component(_filename ${_file} NAME)
0321         get_property(_path SOURCE ${_file} PROPERTY ${_ECM_QMLMODULE_PROPERTY_PATH})
0322 
0323         set(_file_path "${_plugin_path}/")
0324         if (NOT "${_path}" STREQUAL "")
0325             set(_file_path "${_plugin_path}/${_path}/")
0326         endif()
0327 
0328         install(FILES ${_file} DESTINATION ${ARG_DESTINATION}/${_file_path})
0329 
0330         add_custom_command(
0331             TARGET ${ARG_TARGET}
0332             POST_BUILD
0333             WORKING_DIRECTORY ${_runtime_output_dir}
0334             COMMAND ${CMAKE_COMMAND} -E make_directory ${_file_path}
0335             COMMAND ${CMAKE_COMMAND} -E copy ${_file} ${_file_path}
0336             BYPRODUCTS ${_file_path}/${_filename}
0337         )
0338     endforeach()
0339 endfunction()