aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-03-25 14:13:50 +0100
committerUlf Hermann <ulf.hermann@qt.io>2024-04-03 20:37:18 +0200
commit6314d305ee0d9064ca848980ef2dab1793c191b8 (patch)
tree9b0b471a41a3171e7938c0e99842aa12404105e4 /src/qml
parentaa2e2333376cefd1c7b8c3931097eb6dd4b96dd9 (diff)
Generate qmldir files for extra directories with QML files
Those qmldir files contain only a prefer directive for the canonical resource location of the module. This way, any time another component from the implicit import is requested, it will not be located in the extra directory (where it probably doesn't exist), but instead in the canonical location. Since people may have manually written qmldir files with different content in those places, or worse, relied on the other components to be inaccessible, we need a new policy to opt into this. Fixes: QTBUG-111763 Change-Id: If236feb7dd7c8d704b813ea56482ff758799d0a7 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/CMakeLists.txt3
-rw-r--r--src/qml/Qt6QmlBuildInternals.cmake12
-rw-r--r--src/qml/Qt6QmlMacros.cmake54
-rw-r--r--src/qml/doc/src/cmake/policy/qtp0004.qdoc34
-rw-r--r--src/qml/doc/src/cmake/qt_add_qml_module.qdoc6
5 files changed, 105 insertions, 4 deletions
diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt
index cdd6017c63..fa672d3d6c 100644
--- a/src/qml/CMakeLists.txt
+++ b/src/qml/CMakeLists.txt
@@ -501,8 +501,9 @@ qt_internal_add_qml_module(Qml
"${INSTALL_CMAKE_NAMESPACE}QmlFindQmlscInternal.cmake"
${extra_cmake_includes}
GENERATE_CPP_EXPORTS
- POLICIES
+ POLICIES
QTP0001
+ QTP0004
)
_qt_internal_add_qml_deploy_info_finalizer(Qml)
diff --git a/src/qml/Qt6QmlBuildInternals.cmake b/src/qml/Qt6QmlBuildInternals.cmake
index 03db29b8db..418b552692 100644
--- a/src/qml/Qt6QmlBuildInternals.cmake
+++ b/src/qml/Qt6QmlBuildInternals.cmake
@@ -417,6 +417,18 @@ function(qt_internal_add_qml_module target)
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)
diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake
index 8106e9e1a1..3161ec18e7 100644
--- a/src/qml/Qt6QmlMacros.cmake
+++ b/src/qml/Qt6QmlMacros.cmake
@@ -2487,6 +2487,7 @@ function(qt6_target_qml_sources target)
endforeach()
set(generated_sources_other_scope)
+ set(extra_qmldirs)
foreach(qml_file_src IN LISTS arg_QML_FILES)
# This is to facilitate updating code that used the earlier tech preview
# API function qt6_target_qml_files()
@@ -2507,6 +2508,11 @@ 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})
+ get_filename_component(qml_file_resource_dir ${file_resource_path} DIRECTORY)
+ if(qml_file_resource_dir)
+ list(APPEND extra_qmldirs "${output_dir}/${qml_file_resource_dir}/qmldir")
+ endif()
+
# For the tooling steps below, run the tools on the copied qml file in
# the build directory, not the source directory. This is required
# because the tools may need to reference imported modules from
@@ -2742,8 +2748,7 @@ function(qt6_target_qml_sources target)
FILES ${arg_QML_FILES} ${arg_RESOURCES}
OUTPUT_TARGETS resource_targets
)
- math(EXPR counter "${counter} + 1")
- set_target_properties(${target} PROPERTIES QT_QML_MODULE_RAW_QML_SETS ${counter})
+ list(APPEND output_targets ${resource_targets})
# Save the resource name in a property so we can reference it later in a qml plugin
# constructor, to avoid discarding the resource if it's in a static library.
@@ -2752,7 +2757,50 @@ function(qt6_target_qml_sources target)
set_property(TARGET ${target}
APPEND PROPERTY _qt_qml_module_sanitized_resource_names "${sanitized_resource_name}")
- list(APPEND output_targets ${resource_targets})
+ if(extra_qmldirs)
+ list(REMOVE_DUPLICATES extra_qmldirs)
+ __qt_internal_setup_policy(QTP0004 "6.8.0"
+"You need qmldir files for each extra directory that contains .qml files for your module. \
+Check https://doc.qt.io/qt-6/qt-cmake-policy-qtp0004.html for policy details."
+ )
+ qt6_policy(GET QTP0004 generate_extra_qmldirs_policy)
+ if ("${generate_extra_qmldirs_policy}" STREQUAL "NEW")
+ foreach(extra_qmldir IN LISTS extra_qmldirs)
+ set(__qt_qmldir_content "prefer :${arg_PREFIX}")
+ configure_file(
+ ${__qt_qml_macros_module_base_dir}/Qt6qmldirTemplate.cmake.in
+ "${extra_qmldir}"
+ @ONLY
+ )
+
+ set_source_files_properties("${extra_qmldir}"
+ PROPERTIES GENERATED TRUE
+ )
+ endforeach()
+
+ set(extra_qmldirs_targets)
+ qt6_add_resources(${target} "${resource_name}_extra_qmldirs"
+ PREFIX ${arg_PREFIX}
+ FILES ${extra_qmldirs}
+ BASE ${output_dir}
+ OUTPUT_TARGETS extra_qmldirs_targets
+ )
+ list(APPEND output_targets ${extra_qmldirs_targets})
+
+ set_property(TARGET ${target} PROPERTY _qt_internal_extra_qmldirs ${extra_qmldirs})
+
+ # Save the resource name in a property so we can reference it later in a qml plugin
+ # constructor, to avoid discarding the resource if it's in a static library.
+ __qt_internal_sanitize_resource_name(
+ sanitized_extra_qmldirs_resource_name "${resource_name}_extra_qmldirs")
+ set_property(TARGET ${target}
+ APPEND PROPERTY _qt_qml_module_sanitized_resource_names
+ "${sanitized_extra_qmldirs_resource_name}")
+ endif()
+ endif()
+
+ math(EXPR counter "${counter} + 1")
+ set_target_properties(${target} PROPERTIES QT_QML_MODULE_RAW_QML_SETS ${counter})
if(arg_OUTPUT_TARGETS)
set(${arg_OUTPUT_TARGETS} ${output_targets} PARENT_SCOPE)
diff --git a/src/qml/doc/src/cmake/policy/qtp0004.qdoc b/src/qml/doc/src/cmake/policy/qtp0004.qdoc
new file mode 100644
index 0000000000..9d3428e52b
--- /dev/null
+++ b/src/qml/doc/src/cmake/policy/qtp0004.qdoc
@@ -0,0 +1,34 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+\page qt-cmake-policy-qtp0004.html
+\ingroup qt-cmake-policies
+
+\title QTP0004
+\keyword qt_cmake_policy_qtp0004
+
+\summary {Extra directories with QML files in a QML module need extra qmldir files.}
+
+This policy was introduced in Qt 6.8. It causes the build system to generate
+an extra qmldir file for each additional directory that contains QML files in
+a QML module.
+
+Enabling this policy ensures that the implicit import of each of the QML
+components in your module is the same as the module itself. This means that
+all the components can see each other without explicitly importing the module.
+
+The \c OLD behavior of this policy is that a qmldir file is only generated for
+the root directory of a module.
+
+The \c NEW behavior of this policy is that for each directory with QML files in
+a module a separate qmldir file is generated.
+
+Qt 6.8 issues warnings if you do not explicitly set the policy.
+
+\qtpolicydeprecatedbehavior
+
+\sa qt_policy, {qt6_standard_project_setup}{qt_standard_project_setup()},
+ qt_cmake_policies, qt_add_qml_module
+
+*/
diff --git a/src/qml/doc/src/cmake/qt_add_qml_module.qdoc b/src/qml/doc/src/cmake/qt_add_qml_module.qdoc
index 94a7a9d67f..4ca7635b9c 100644
--- a/src/qml/doc/src/cmake/qt_add_qml_module.qdoc
+++ b/src/qml/doc/src/cmake/qt_add_qml_module.qdoc
@@ -171,6 +171,12 @@ The \l OUTPUT_DIRECTORY argument determines where the \c qmldir and typeinfo
files will be written to. If the QML module has a plugin, that plugin will also
be created in the same directory as the \c qmldir file.
+If \l{QTP0004} policy is set to \c NEW, for each further directory that contains
+\c{.qml} files another \c qmldir file is generated. These extra \c qmldir files
+merely redirect to the module's base directory via a \c prefer directive. This
+is so that all the QML components in a module can access each other, no matter
+which directory they are stored in.
+
If using a statically built Qt, the backing target's \c{.qml} files will be
scanned during the CMake configure run to determine the imports used by the
module and to set up linking relationships (the \c{NO_IMPORT_SCAN} keyword