diff options
Diffstat (limited to 'src/qml/Qt6QmlBuildInternals.cmake')
-rw-r--r-- | src/qml/Qt6QmlBuildInternals.cmake | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/src/qml/Qt6QmlBuildInternals.cmake b/src/qml/Qt6QmlBuildInternals.cmake new file mode 100644 index 0000000000..7b181fabde --- /dev/null +++ b/src/qml/Qt6QmlBuildInternals.cmake @@ -0,0 +1,470 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# +# QtDeclarative Specific extensions +# + +include_guard(GLOBAL) + +macro(qt_internal_get_internal_add_qml_module_keywords + option_args single_args multi_args + internal_option_args internal_single_args internal_multi_args) + set(${option_args} + DESIGNER_SUPPORTED + FOLLOW_FOREIGN_VERSIONING + NO_PLUGIN + NO_PLUGIN_OPTIONAL + NO_CREATE_PLUGIN_TARGET + NO_GENERATE_PLUGIN_SOURCE + NO_GENERATE_QMLTYPES + NO_GENERATE_QMLDIR + NO_LINT + NO_CACHEGEN + ENABLE_TYPE_COMPILER + __QT_INTERNAL_STATIC_MODULE + __QT_INTERNAL_SYSTEM_MODULE + ) + set(${single_args} + URI + VERSION + PLUGIN_TARGET + TYPEINFO + CLASS_NAME + TYPE_COMPILER_NAMESPACE + ) + set(${multi_args} + QML_FILES + RESOURCES + IMPORTS + IMPORT_PATH + OPTIONAL_IMPORTS + DEFAULT_IMPORTS + DEPENDENCIES + PAST_MAJOR_VERSIONS + ) + # Args used by qt_internal_add_qml_module directly, which should not be passed to any other + # functions. + # + # INSTALL_SOURCE_QMLTYPES takes a path to an existing plugins.qmltypes file that should be + # installed. + # + # INSTALL_SOURCE_QMLDIR takes a path to an existing qmldir file that should be installed. + set(${internal_option_args} + ) + set(${internal_single_args} + INSTALL_SOURCE_QMLTYPES + INSTALL_SOURCE_QMLDIR + ) + set(${internal_multi_args} + ) + +endmacro() + +# This function is essentially a wrapper around qt6_add_qml_module(). +# It creates the targets explicitly and sets up internal properties before +# passing those targets to qt6_add_qml_module() for further updates. +# All keywords supported by qt_internal_add_module() can be used, as can most +# keywords for qt6_add_qml_module() except RESOURCE_PREFIX and +# OUTPUT_TARGETS. +# +# OUTPUT_DIRECTORY and INSTALL_DIRECTORY will be given more appropriate defaults +# if not provided by the caller. The defaults are usually what you want to use. +# +# - SOURCES is only passed through to qt_internal_add_plugin() or +# qt_internal_add_module() but not to qt6_add_qml_module(). +# +# See qt_internal_add_plugin() and qt6_add_qml_module() for the full set of +# supported keywords. +function(qt_internal_add_qml_module target) + + qt_internal_get_internal_add_module_keywords( + module_option_args + module_single_args + module_multi_args + ) + + qt_internal_get_internal_add_qml_module_keywords( + qml_module_option_args + qml_module_single_args + qml_module_multi_args + qml_module_internal_option_args + qml_module_internal_single_args + qml_module_internal_multi_args + ) + # TODO: Remove these once all repos have been updated to not use them + set(ignore_option_args + PLUGIN_OPTIONAL # Now the default + GENERATE_QMLTYPES # Now the default + INSTALL_QMLTYPES # Now the default + ) + + set(option_args + ${module_option_args} + ${qml_module_option_args} + ${ignore_option_args} + ${qml_module_internal_option_args} + ) + set(single_args + ${module_single_args} + ${qml_module_single_args} + ${qml_module_internal_single_args} + ) + set(multi_args + ${module_multi_args} + ${qml_module_multi_args} + ${qml_module_internal_multi_args} + ) + + cmake_parse_arguments(PARSE_ARGV 1 arg + "${option_args}" + "${single_args}" + "${multi_args}" + ) + _qt_internal_validate_all_args_are_parsed(arg) + + set(QT_QML_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_QMLDIR}") + string(REPLACE "." "/" target_path ${arg_URI}) + if(NOT arg_OUTPUT_DIRECTORY) + set(arg_OUTPUT_DIRECTORY "${QT_QML_OUTPUT_DIRECTORY}/${target_path}") + endif() + if(NOT arg_INSTALL_DIRECTORY) + set(arg_INSTALL_DIRECTORY "${INSTALL_QMLDIR}/${target_path}") + endif() + if(arg_NO_PLUGIN) + unset(arg_PLUGIN_TARGET) + elseif(NOT arg_PLUGIN_TARGET) + set(arg_PLUGIN_TARGET ${target}plugin) + endif() + + set(plugin_args "") + if(arg_NO_PLUGIN OR NOT arg_PLUGIN_TARGET STREQUAL target) + # Allow using an existing backing target. + if(NOT TARGET ${target}) + # Create the backing target now to handle module-related things + qt_remove_args(module_args + ARGS_TO_REMOVE + ${ignore_option_args} + ${qml_module_option_args} + ${qml_module_single_args} + ${qml_module_multi_args} + ${qml_module_internal_option_args} + ${qml_module_internal_single_args} + ${qml_module_internal_multi_args} + OUTPUT_DIRECTORY + INSTALL_DIRECTORY + ALL_ARGS + ${option_args} + ${single_args} + ${multi_args} + ARGS + ${ARGN} + ) + qt_internal_add_module(${target} ${module_args}) + elseif(arg_SOURCES) + # If a module target was pre-created, we still need to pass the additional sources. + target_sources(${target} PRIVATE ${arg_SOURCES}) + endif() + else() + # Since we are not creating a separate backing target, we have to pass + # through the default args to the plugin target creation instead + qt_internal_get_internal_add_plugin_keywords( + plugin_option_args plugin_single_args plugin_multi_args + ) + set(args_to_remove ${option_args} ${single_args} ${multi_args}) + list(REMOVE_ITEM args_to_remove + ${plugin_option_args} + ${plugin_single_args} + ${plugin_multi_args} + ) + qt_remove_args(plugin_args + ARGS_TO_REMOVE + ${args_to_remove} + DEFAULT_IF + OUTPUT_DIRECTORY + INSTALL_DIRECTORY + CLASS_NAME + ALL_ARGS + ${option_args} + ${single_args} + ${multi_args} + ARGS + ${ARGN} + ) + endif() + + set(add_qml_module_args "") + + if(NOT arg_NO_PLUGIN AND NOT arg_NO_CREATE_PLUGIN_TARGET) + # If the qt_internal_add_qml_module call didn't specify a CLASS_NAME, we need to pre-compute + # it here and pass it along to qt_internal_add_plugin -> qt_add_plugin so that + # qt_add_qml_plugin does not complain about differing class names (the default pre-computed + # class name of a regular plugin and qml plugin are different). + if(NOT arg_CLASS_NAME) + _qt_internal_compute_qml_plugin_class_name_from_uri("${arg_URI}" arg_CLASS_NAME) + endif() + + # Create plugin target now so we can set internal things + list(APPEND plugin_args + PLUGIN_TYPE qml_plugin + DEFAULT_IF FALSE + OUTPUT_DIRECTORY ${arg_OUTPUT_DIRECTORY} + INSTALL_DIRECTORY ${arg_INSTALL_DIRECTORY} + CLASS_NAME ${arg_CLASS_NAME} + ) + + qt_internal_add_plugin(${arg_PLUGIN_TARGET} ${plugin_args}) + + # Use the plugin target name as the main part of the plugin basename. + set(plugin_basename "${arg_PLUGIN_TARGET}") + + # If the target name already ends with a "plugin" suffix, remove it and re-add it to the end + # of the base name after the infix. + if(plugin_basename MATCHES "(.+)plugin$") + set(plugin_basename "${CMAKE_MATCH_1}") + endif() + + # Add a the infix if Qt was configured with one. + if(QT_LIBINFIX) + string(APPEND plugin_basename "${QT_LIBINFIX}") + endif() + + # Add the "plugin" suffix after the infix. + string(APPEND plugin_basename "plugin") + + # Lowercase the whole thing and use it as the basename of the plugin library. + string(TOLOWER "${plugin_basename}" plugin_basename) + set_target_properties(${arg_PLUGIN_TARGET} PROPERTIES + OUTPUT_NAME "${plugin_basename}" + ) + + get_target_property(export_name ${arg_PLUGIN_TARGET} EXPORT_NAME) + if(export_name) + list(APPEND add_qml_module_args + INSTALLED_PLUGIN_TARGET "${QT_CMAKE_EXPORT_NAMESPACE}::${export_name}" + ) + else() + list(APPEND add_qml_module_args + INSTALLED_PLUGIN_TARGET "${QT_CMAKE_EXPORT_NAMESPACE}::${arg_PLUGIN_TARGET}" + ) + endif() + + if(NOT arg_PLUGIN_TARGET STREQUAL target) + get_target_property(lib_type ${arg_PLUGIN_TARGET} TYPE) + if(lib_type STREQUAL "STATIC_LIBRARY") + # This is needed so that the dependency on the backing target + # is included in the plugin's find_package() support. + # The naming of backing targets and plugins don't typically + # follow the pattern of other plugins with regard to Private + # suffixes, so the dependency logic in qt_internal_add_plugin() + # doesn't find these. For non-static builds, the private + # dependency doesn't get exposed to find_package(), so we don't + # have to make the dependency known for that case. + set_property(TARGET ${arg_PLUGIN_TARGET} APPEND PROPERTY + _qt_target_deps "${INSTALL_CMAKE_NAMESPACE}${target}\;${PROJECT_VERSION}" + ) + endif() + endif() + endif() + + # TODO: Check if we need arg_SOURCES in this condition + if (arg_SOURCES AND NOT arg_TYPEINFO) + set(arg_TYPEINFO "plugins.qmltypes") + endif() + + # Pass through options if given (these are present/absent, not true/false) + foreach(opt IN LISTS qml_module_option_args) + if(arg_${opt}) + list(APPEND add_qml_module_args ${opt}) + endif() + endforeach() + + # Pass through single and multi-value args as provided. + foreach(arg IN LISTS qml_module_single_args qml_module_multi_args) + if(DEFINED arg_${arg}) + list(APPEND add_qml_module_args ${arg} ${arg_${arg}}) + endif() + endforeach() + + if (arg_FOLLOW_FOREIGN_VERSIONING) + message(FATAL_ERROR "Do not set FOLLOW_FOREIGN_VERSIONING for module ${target}. It is already set by default for internal modules.") + endif() + + get_target_property(qt_namespace ${QT_CMAKE_EXPORT_NAMESPACE}::Core _qt_namespace) + if(qt_namespace) + list(APPEND add_qml_module_args NAMESPACE ${qt_namespace}) + endif() + + if (arg_ENABLE_TYPE_COMPILER AND NOT arg_TYPE_COMPILER_NAMESPACE) + # if qmltc namespace is not specified explicitly, use Qt's namespace + list(APPEND add_qml_module_args TYPE_COMPILER_NAMESPACE ${qt_namespace}) + endif() + + # Update the backing and plugin targets with qml-specific things. + qt6_add_qml_module(${target} + ${add_qml_module_args} + OUTPUT_DIRECTORY ${arg_OUTPUT_DIRECTORY} + RESOURCE_PREFIX "/qt-project.org/imports" + OUTPUT_TARGETS output_targets + FOLLOW_FOREIGN_VERSIONING + ) + + if(TARGET "${target}" AND NOT target STREQUAL "Qml") + qt_internal_add_autogen_sync_header_dependencies(${target} Qml) + endif() + if(TARGET "${arg_PLUGIN_TARGET}" AND NOT target STREQUAL arg_PLUGIN_TARGET) + qt_internal_add_autogen_sync_header_dependencies(${arg_PLUGIN_TARGET} Qml) + endif() + + if(output_targets) + set(plugin_export_targets) + set(backing_lib_export_targets) + + # Separate which output target should go to which export set. + # The plugin initializer library should go to the plugin export set, the rest should go to + # the backing lib export set. + # In the case when the plugin target is the same as the backing lib target, all of the + # output targets will go to the plugin export set. + + foreach(output_target IN LISTS output_targets) + get_target_property(is_plugin_init ${output_target} _is_qt_plugin_init_target) + if(is_plugin_init) + list(APPEND plugin_export_targets ${output_target}) + + # Plugin initializers associated with an internal module need the internal + # platform flags. + qt_internal_link_internal_platform_for_object_library("${output_target}") + else() + list(APPEND backing_lib_export_targets ${output_target}) + endif() + endforeach() + + if(backing_lib_export_targets) + qt_install(TARGETS ${backing_lib_export_targets} + EXPORT "${INSTALL_CMAKE_NAMESPACE}${target}Targets" + DESTINATION "${arg_INSTALL_DIRECTORY}" + ) + qt_internal_record_rcc_object_files(${target} "${backing_lib_export_targets}" + INSTALL_DIRECTORY "${arg_INSTALL_DIRECTORY}" + ) + + qt_internal_add_targets_to_additional_targets_export_file( + TARGETS ${backing_lib_export_targets} + EXPORT_NAME_PREFIX "${INSTALL_CMAKE_NAMESPACE}${target}" + ) + endif() + + if(arg_PLUGIN_TARGET AND plugin_export_targets) + qt_install(TARGETS ${plugin_export_targets} + EXPORT "${INSTALL_CMAKE_NAMESPACE}${arg_PLUGIN_TARGET}Targets" + DESTINATION "${arg_INSTALL_DIRECTORY}" + ) + + qt_internal_add_targets_to_additional_targets_export_file( + TARGETS ${plugin_export_targets} + EXPORT_NAME_PREFIX "${INSTALL_CMAKE_NAMESPACE}${arg_PLUGIN_TARGET}" + ) + endif() + endif() + + if(DEFINED arg_QML_FILES OR DEFINED arg_RESOURCES) + foreach(resource_file IN LISTS arg_QML_FILES arg_RESOURCES) + __qt_get_relative_resource_path_for_file(file_resource_path ${resource_file}) + get_filename_component(resource_dir ${file_resource_path} DIRECTORY) + get_filename_component(resource_name ${file_resource_path} NAME) + if(resource_dir) + set(dest "${arg_INSTALL_DIRECTORY}/${resource_dir}") + else() + set(dest "${arg_INSTALL_DIRECTORY}") + endif() + qt_install( + FILES ${resource_file} + DESTINATION ${dest} + RENAME ${resource_name} + ) + endforeach() + endif() + + if(NOT arg_NO_GENERATE_QMLTYPES) + qt_install( + FILES ${arg_OUTPUT_DIRECTORY}/$<TARGET_PROPERTY:${target},QT_QML_MODULE_TYPEINFO> + DESTINATION "${arg_INSTALL_DIRECTORY}" + ) + + # Assign the install time metatypes file of the backing library to the plugin. + # Only do it if the backing library is different from the plugin and we do generate + # qml types. + # The install time metatypes only apply to Qt's own qml plugins, not to user project + # qml plugins. + if(arg_PLUGIN_TARGET AND + TARGET "${arg_PLUGIN_TARGET}" AND NOT target STREQUAL arg_PLUGIN_TARGET) + _qt_internal_get_metatypes_install_dir( + "" + "${INSTALL_ARCHDATADIR}" + install_dir + ) + + _qt_internal_assign_install_metatypes_files_and_properties( + "${arg_PLUGIN_TARGET}" + INSTALL_DIR "${install_dir}" + ) + endif() + endif() + + if(NOT arg_NO_GENERATE_QMLDIR) + qt_install( + FILES ${arg_OUTPUT_DIRECTORY}/qmldir + DESTINATION "${arg_INSTALL_DIRECTORY}" + ) + + get_target_property(extra_qmldirs ${target} _qt_internal_extra_qmldirs) + if(extra_qmldirs) + foreach(extra_qmldir IN LISTS extra_qmldirs) + __qt_get_relative_resource_path_for_file(qmldir_resource_path ${extra_qmldir}) + get_filename_component(qmldir_dir ${qmldir_resource_path} DIRECTORY) + qt_install( + FILES ${extra_qmldir} + DESTINATION "${arg_INSTALL_DIRECTORY}/${qmldir_dir}" + ) + endforeach() + endif() + endif() + + if(arg_INSTALL_SOURCE_QMLTYPES) + message(AUTHOR_WARNING + "INSTALL_SOURCE_QMLTYPES option is deprecated and should not be used. " + "Please port your module to use declarative type registration.") + + set(files ${arg_INSTALL_SOURCE_QMLTYPES}) + if(QT_WILL_INSTALL) + install( + FILES ${files} + DESTINATION "${arg_INSTALL_DIRECTORY}" + ) + else() + file( + COPY ${files} + DESTINATION "${arg_OUTPUT_DIRECTORY}" + ) + endif() + endif() + + if(arg_INSTALL_SOURCE_QMLDIR) + message(AUTHOR_WARNING + "INSTALL_SOURCE_QMLDIR option is deprecated and should not be used. " + "Please port your module to use declarative type registration.") + + set(files ${arg_INSTALL_SOURCE_QMLDIR}) + if(QT_WILL_INSTALL) + install( + FILES ${files} + DESTINATION "${arg_INSTALL_DIRECTORY}" + ) + else() + file( + COPY ${files} + DESTINATION "${arg_OUTPUT_DIRECTORY}" + ) + endif() + endif() +endfunction() |