aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/Qt6QmlMacros.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/Qt6QmlMacros.cmake')
-rw-r--r--src/qml/Qt6QmlMacros.cmake256
1 files changed, 172 insertions, 84 deletions
diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake
index a75a8e794b..bda7b9b83a 100644
--- a/src/qml/Qt6QmlMacros.cmake
+++ b/src/qml/Qt6QmlMacros.cmake
@@ -412,19 +412,7 @@ function(qt6_add_qml_module target)
endif()
endforeach()
- # Make the prefix conform to the following:
- # - Starts with a "/"
- # - Does not end with a "/" unless the prefix is exactly "/"
- if(NOT arg_RESOURCE_PREFIX)
- set(arg_RESOURCE_PREFIX "/")
- endif()
- if(NOT arg_RESOURCE_PREFIX MATCHES "^/")
- string(PREPEND arg_RESOURCE_PREFIX "/")
- endif()
- if(arg_RESOURCE_PREFIX MATCHES [[(.+)/$]])
- set(arg_RESOURCE_PREFIX "${CMAKE_MATCH_1}")
- endif()
-
+ _qt_internal_canonicalize_resource_path("${arg_RESOURCE_PREFIX}" arg_RESOURCE_PREFIX)
if(arg_NO_RESOURCE_TARGET_PATH)
set(qt_qml_module_resource_prefix "${arg_RESOURCE_PREFIX}")
else()
@@ -532,21 +520,19 @@ function(qt6_add_qml_module target)
PROPERTIES QT_RESOURCE_ALIAS "qmldir"
)
- if(NOT ANDROID)
- foreach(prefix IN LISTS prefixes)
- set(resource_targets)
- qt6_add_resources(${target} ${qmldir_resource_name}
- FILES ${arg_OUTPUT_DIRECTORY}/qmldir
- PREFIX "${prefix}"
- OUTPUT_TARGETS resource_targets
- )
- list(APPEND output_targets ${resource_targets})
- # If we are adding the same file twice, we need a different resource
- # name for the second one. It has the same QT_RESOURCE_ALIAS but a
- # different prefix, so we can't put it in the same resource.
- string(APPEND qmldir_resource_name "_copy")
- endforeach()
- endif()
+ foreach(prefix IN LISTS prefixes)
+ set(resource_targets)
+ qt6_add_resources(${target} ${qmldir_resource_name}
+ FILES ${arg_OUTPUT_DIRECTORY}/qmldir
+ PREFIX "${prefix}"
+ OUTPUT_TARGETS resource_targets
+ )
+ list(APPEND output_targets ${resource_targets})
+ # If we are adding the same file twice, we need a different resource
+ # name for the second one. It has the same QT_RESOURCE_ALIAS but a
+ # different prefix, so we can't put it in the same resource.
+ string(APPEND qmldir_resource_name "_copy")
+ endforeach()
endif()
if(NOT arg_NO_PLUGIN AND NOT arg_NO_CREATE_PLUGIN_TARGET)
@@ -634,6 +620,22 @@ if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
endfunction()
endif()
+# Make the prefix conform to the following:
+# - Starts with a "/"
+# - Does not end with a "/" unless the prefix is exactly "/"
+function(_qt_internal_canonicalize_resource_path path out_var)
+ if(NOT path)
+ set(path "/")
+ endif()
+ if(NOT path MATCHES "^/")
+ string(PREPEND path "/")
+ endif()
+ if(path MATCHES [[(.+)/$]])
+ set(path "${CMAKE_MATCH_1}")
+ endif()
+ set(${out_var} "${path}" PARENT_SCOPE)
+endfunction()
+
function(_qt_internal_get_escaped_uri uri out_var)
string(REGEX REPLACE "[^A-Za-z0-9]" "_" escaped_uri "${uri}")
set(${out_var} "${escaped_uri}" PARENT_SCOPE)
@@ -658,6 +660,20 @@ macro(_qt_internal_genex_getoption var target property)
set(${var} "$<BOOL:$<TARGET_PROPERTY:${target},${property}>>")
endmacro()
+function(_qt_internal_extend_qml_import_paths import_paths_var)
+ set(local_var ${${import_paths_var}})
+
+ # prepend extra import path which is a current module's build dir: we need
+ # this to ensure correct importing of QML modules when having a prefix-build
+ # with QLibraryInfo::path(QLibraryInfo::QmlImportsPath) pointing to the
+ # install location
+ if(QT_BUILDING_QT AND QT_WILL_INSTALL)
+ list(PREPEND local_var -I "${QT_BUILD_DIR}/${INSTALL_QMLDIR}")
+ endif()
+
+ set(${import_paths_var} ${local_var} PARENT_SCOPE)
+endfunction()
+
function(_qt_internal_target_enable_qmllint target)
set(lint_target ${target}_qmllint)
if(TARGET ${lint_target})
@@ -706,6 +722,8 @@ function(_qt_internal_target_enable_qmllint target)
list(APPEND import_args -I "${QT_QML_OUTPUT_DIRECTORY}")
endif()
+ _qt_internal_extend_qml_import_paths(import_args)
+
set(cmd
${QT_TOOL_COMMAND_WRAPPER_PATH}
${QT_CMAKE_EXPORT_NAMESPACE}::qmllint
@@ -926,8 +944,12 @@ function(_qt_internal_target_generate_qmldir target)
string(APPEND content "optional ")
endif()
- _qt_internal_get_qml_plugin_basename(plugin_basename ${plugin_target})
- string(APPEND content "plugin ${plugin_basename}\n")
+ get_target_property(target_path ${target} QT_QML_MODULE_TARGET_PATH)
+ _qt_internal_get_qml_plugin_output_name(plugin_output_name ${plugin_target}
+ TARGET_PATH "${target_path}"
+ URI "${uri}"
+ )
+ string(APPEND content "plugin ${plugin_output_name}\n")
_qt_internal_qmldir_item(classname QT_QML_MODULE_CLASS_NAME)
endif()
@@ -1140,32 +1162,15 @@ function(qt6_add_qml_plugin target)
)
endif()
- if (ANDROID)
- # Adjust Qml plugin names on Android similar to qml_plugin.prf which calls
- # $$qt5LibraryTarget($$TARGET, "qml/$$TARGETPATH/").
- # Example plugin names:
- # qtdeclarative
- # TARGET_PATH: QtQml/Models
- # file name: libqml_QtQml_Models_modelsplugin_arm64-v8a.so
- # qtquickcontrols2
- # TARGET_PATH: QtQuick/Controls.2/Material
- # file name:
- # libqml_QtQuick_Controls.2_Material_qtquickcontrols2materialstyleplugin_arm64-v8a.so
- if(NOT arg_TARGET_PATH AND TARGET "${arg_BACKING_TARGET}")
- get_target_property(arg_TARGET_PATH ${arg_BACKING_TARGET} QT_QML_MODULE_TARGET_PATH)
- endif()
- if(arg_TARGET_PATH)
- string(REPLACE "/" "_" android_plugin_name_infix_name "${arg_TARGET_PATH}")
- else()
- string(REPLACE "." "_" android_plugin_name_infix_name "${arg_URI}")
- endif()
-
- _qt_internal_get_qml_plugin_basename(plugin_basename ${target})
- set(final_android_qml_plugin_name
- "qml_${android_plugin_name_infix_name}_${plugin_basename}")
+ if(ANDROID)
+ _qt_internal_get_qml_plugin_output_name(plugin_output_name ${target}
+ BACKING_TARGET "${arg_BACKING_TARGET}"
+ TARGET_PATH "${arg_TARGET_PATH}"
+ URI "${arg_URI}"
+ )
set_target_properties(${target}
PROPERTIES
- LIBRARY_OUTPUT_NAME "${final_android_qml_plugin_name}"
+ LIBRARY_OUTPUT_NAME "${plugin_output_name}"
)
qt6_android_apply_arch_suffix(${target})
endif()
@@ -1319,7 +1324,8 @@ function(qt6_target_qml_sources target)
)
endif()
endif()
- if(NOT arg_PREFIX MATCHES [[/$]])
+ _qt_internal_canonicalize_resource_path("${arg_PREFIX}" arg_PREFIX)
+ if(NOT arg_PREFIX STREQUAL "/")
string(APPEND arg_PREFIX "/")
endif()
@@ -1367,6 +1373,7 @@ function(qt6_target_qml_sources target)
# The application binary directory is part of the default import path.
list(APPEND import_paths -I "$<TARGET_PROPERTY:${target},BINARY_DIR>")
endif()
+ _qt_internal_extend_qml_import_paths(import_paths)
set(cachegen_args
${import_paths}
"$<${have_types_file}:-i$<SEMICOLON>${types_file}>"
@@ -1451,7 +1458,6 @@ function(qt6_target_qml_sources target)
get_filename_component(file_absolute ${qml_file_src} ABSOLUTE)
__qt_get_relative_resource_path_for_file(file_resource_path ${qml_file_src})
- set(qml_file_out ${output_dir}/${file_resource_path})
# For the tooling steps below, run the tools on the copied qml file in
# the build directory, not the source directory. This is required
@@ -1467,7 +1473,7 @@ function(qt6_target_qml_sources target)
# The set of qml files to run qmllint on may be a subset of the
# full set of files, so record these in a separate property.
_qt_internal_target_enable_qmllint(${target})
- set_property(TARGET ${target} APPEND PROPERTY QT_QML_LINT_FILES ${qml_file_src})
+ set_property(TARGET ${target} APPEND PROPERTY QT_QML_LINT_FILES ${file_absolute})
endif()
# Add qml file's type to qmldir
@@ -1476,17 +1482,16 @@ function(qt6_target_qml_sources target)
get_source_file_property(qml_file_typename ${qml_file_src} QT_QML_SOURCE_TYPENAME)
if (NOT qml_file_typename)
get_filename_component(qml_file_ext ${qml_file_src} EXT)
- if (NOT qml_file_ext STREQUAL ".js" AND NOT qml_file_ext STREQUAL ".mjs")
- get_filename_component(qml_file_typename ${qml_file_src} NAME_WE)
- endif()
+ get_filename_component(qml_file_typename ${qml_file_src} NAME_WE)
endif()
# Do not add qmldir entries for lowercase names. Those are not components.
if (qml_file_typename AND qml_file_typename MATCHES "^[A-Z]")
- if (qml_file_ext AND NOT qml_file_ext STREQUAL ".qml" AND NOT qml_file_ext STREQUAL ".ui.qml")
+ if (qml_file_ext AND NOT qml_file_ext STREQUAL ".qml" AND NOT qml_file_ext STREQUAL ".ui.qml"
+ AND NOT qml_file_ext STREQUAL ".js" AND NOT qml_file_ext STREQUAL ".mjs")
message(AUTHOR_WARNING
- "${qml_file_src} has a file extension different from .qml and .ui.qml. "
- "This leads to unexpected component names."
+ "${qml_file_src} has a file extension different from .qml, .ui.qml, .js, "
+ "and .mjs. This leads to unexpected component names."
)
endif()
@@ -1805,6 +1810,11 @@ function(_qt_internal_qml_type_registration target)
if (TARGET ${target}Private)
list(APPEND cmd_args --private-includes)
+ else()
+ string(REGEX MATCH "Private$" privateSuffix ${target})
+ if (privateSuffix)
+ list(APPEND cmd_args --private-includes)
+ endif()
endif()
get_target_property(target_metatypes_json_file ${target} INTERFACE_QT_META_TYPES_BUILD_FILE)
@@ -1877,10 +1887,12 @@ function(_qt_internal_qml_type_registration target)
endif()
add_dependencies(all_qmltyperegistrations ${target}_qmltyperegistration)
+ # Both ${target} (via target_sources) and ${target}_qmltyperegistration (via add_custom_target
+ # DEPENDS option) depend on ${type_registration_cpp_file}.
# The new Xcode build system requires a common target to drive the generation of files,
# otherwise project configuration fails.
- # Make the ${target}_qmltyperegistration the common target, by adding it as a dependency for
- # ${target} itself.
+ # Make ${target} the common target, by adding it as a dependency for
+ # ${target}_qmltyperegistration.
# The consequence is that the ${target}_qmllint target will now first build ${target} when using
# the Xcode generator (mostly only relevant for projects using Qt for iOS).
# See QTBUG-95763.
@@ -1993,10 +2005,24 @@ but this file does not exist. Possible reasons include:
")
endif()
- # Find location of qml dir.
- # TODO: qt.prf implies that there might be more than one qml import path to
- # pass to qmlimportscanner.
- set(qml_path "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_QML}")
+ # Find Qt provided QML import paths.
+ if("${_qt_additional_packages_prefix_paths}" STREQUAL "")
+ # We have one installation prefix for all Qt modules. Add the "<prefix>/qml" directory.
+ set(qml_import_paths "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_QML}")
+ else()
+ # We have multiple installation prefixes: one per Qt repository (conan). Add those that have
+ # a "qml" subdirectory.
+ set(qml_import_paths)
+ __qt_internal_prefix_paths_to_roots(
+ additional_root_paths "${_qt_additional_packages_prefix_paths}")
+ foreach(root IN ITEMS ${QT6_INSTALL_PREFIX} ${additional_root_paths})
+ set(candidate "${root}/${QT6_INSTALL_QML}")
+ if(IS_DIRECTORY "${candidate}")
+ list(APPEND qml_import_paths "${candidate}")
+ endif()
+ endforeach()
+ endif()
+
# Small macro to avoid duplicating code in two different loops.
macro(_qt6_QmlImportScanner_parse_entry)
@@ -2020,21 +2046,35 @@ but this file does not exist. Possible reasons include:
set(cmd_args
-rootPath "${arg_PATH_TO_SCAN}"
-cmake-output
- -importPath "${qml_path}"
)
get_target_property(qml_import_path ${target} QT_QML_IMPORT_PATH)
-
- if (qml_import_path)
- list(APPEND cmd_args ${qml_import_path})
+ if(qml_import_path)
+ list(APPEND qml_import_paths ${qml_import_path})
endif()
# Facilitate self-import so we can find the qmldir file
- list(APPEND cmd_args "${CMAKE_CURRENT_BINARY_DIR}")
+ get_target_property(module_out_dir ${target} QT_QML_MODULE_OUTPUT_DIRECTORY)
+ if(module_out_dir)
+ list(APPEND qml_import_paths "${module_out_dir}")
+ endif()
- if(NOT "${QT_QML_OUTPUT_DIRECTORY}" STREQUAL "" AND EXISTS "${QT_QML_OUTPUT_DIRECTORY}")
- list(APPEND cmd_args "${QT_QML_OUTPUT_DIRECTORY}")
+ # Find qmldir files we copied to the build directory
+ if(NOT "${QT_QML_OUTPUT_DIRECTORY}" STREQUAL "")
+ if(EXISTS "${QT_QML_OUTPUT_DIRECTORY}")
+ list(APPEND qml_import_paths "${QT_QML_OUTPUT_DIRECTORY}")
+ endif()
+ else()
+ list(APPEND qml_import_paths "${CMAKE_CURRENT_BINARY_DIR}")
endif()
+ # Construct the -importPath arguments.
+ set(import_path_arguments)
+ foreach(path IN LISTS qml_import_paths)
+ list(APPEND import_path_arguments -importPath ${path})
+ endforeach()
+
+ list(APPEND cmd_args ${import_path_arguments})
+
# All of the module's .qml files will be listed in one of the generated
# .qrc files, so there's no need to list the files individually. We provide
# the .qrc files instead because they have the additional information for
@@ -2255,17 +2295,65 @@ function(_qt_internal_add_static_qml_plugin_dependencies plugin_target backing_t
endif()
endfunction()
-# The function returns the base output name of a qml plugin that will be used as library output
-# name and in a qmldir file as the 'plugin <plugin_basename>' record.
-function(_qt_internal_get_qml_plugin_basename out_var plugin_target)
- set(plugin_basename)
+# The function returns the output name of a qml plugin that will be used as library output
+# name and in a qmldir file as the 'plugin <plugin_output_name>' record.
+function(_qt_internal_get_qml_plugin_output_name out_var plugin_target)
+ cmake_parse_arguments(arg
+ ""
+ "BACKING_TARGET;TARGET_PATH;URI"
+ ""
+ ${ARGN}
+ )
+ set(plugin_name)
if(TARGET ${plugin_target})
- get_target_property(plugin_basename ${plugin_target} OUTPUT_NAME)
+ get_target_property(plugin_name ${plugin_target} OUTPUT_NAME)
endif()
- if(NOT plugin_basename)
- set(plugin_basename "${plugin_target}")
+ if(NOT plugin_name)
+ set(plugin_name "${plugin_target}")
endif()
- set(${out_var} "${plugin_basename}" PARENT_SCOPE)
+
+ if(ANDROID)
+ # In Android all plugins are stored in directly the /libs directory. This means that plugin
+ # names must be unique in scope of apk. To make this work we prepend uri-based prefix to
+ # each qml plugin in case if users don't use the manually written qmldir files.
+ get_target_property(no_generate_qmldir ${target} QT_QML_MODULE_NO_GENERATE_QMLDIR)
+ if(TARGET "${arg_BACKING_TARGET}")
+ get_target_property(no_generate_qmldir ${arg_BACKING_TARGET}
+ QT_QML_MODULE_NO_GENERATE_QMLDIR)
+
+ # Adjust Qml plugin names on Android similar to qml_plugin.prf which calls
+ # $$qt5LibraryTarget($$TARGET, "qml/$$TARGETPATH/").
+ # Example plugin names:
+ # qtdeclarative
+ # TARGET_PATH: QtQml/Models
+ # file name: libqml_QtQml_Models_modelsplugin_x86_64.so
+ # qtquickcontrols2
+ # TARGET_PATH: QtQuick/Controls.2/Material
+ # file name:
+ # libqml_QtQuick_Controls.2_Material_qtquickcontrols2materialstyleplugin_x86_64.so
+ if(NOT arg_TARGET_PATH)
+ get_target_property(arg_TARGET_PATH ${arg_BACKING_TARGET}
+ QT_QML_MODULE_TARGET_PATH)
+ endif()
+ endif()
+ if(arg_TARGET_PATH)
+ string(REPLACE "/" "_" android_plugin_name_infix_name "${arg_TARGET_PATH}")
+ else()
+ string(REPLACE "." "_" android_plugin_name_infix_name "${arg_URI}")
+ endif()
+
+ # If plugin supposed to use manually written qmldir file we don't prepend the uri-based
+ # prefix to the plugin output name. User should keep the file name of a QML plugin in
+ # qmldir the same as the name of plugin on a file system. Exception is the
+ # ABI-/platform-specific suffix that has the separate processing and should not be
+ # a part of plugin name in qmldir.
+ if(NOT no_generate_qmldir)
+ set(plugin_name
+ "qml_${android_plugin_name_infix_name}_${plugin_name}")
+ endif()
+ endif()
+
+ set(${out_var} "${plugin_name}" PARENT_SCOPE)
endfunction()
# Used to add extra dependencies between ${target} and ${dep_target} qml plugins in a static