aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2022-07-01 15:53:48 +0200
committerAndrei Golubev <andrei.golubev@qt.io>2022-07-26 10:34:49 +0200
commit9ec46f271a7adbc2d9f943695d9705fbd6afd393 (patch)
treebd0ea58d5cd06a52a80df53bd00683ffe8e8c65e /src
parentca68b0cde7a3b9bad468dfae1935d5886f461499 (diff)
Revise build to source dir mapping for QML tooling
Instead of doing build file path to source file path mapping for each QML file, we could store qml module prefix to qml module output directory mapping instead. This reduces the produced qrc size and makes it more convenient to work with Do a clean separation at the QQmlJSImporter level to prevent using resource file mapper for build directory path resolution Amends 7f567e6a424a3919337aad498543d58c1252df62 Change-Id: If984abada1d39c386af5712af778eb29956e0537 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/Qt6QmlMacros.cmake36
-rw-r--r--src/qml/Qt6QmlModuleDirMappingTemplate.qrc.in2
-rw-r--r--src/qmlcompiler/qqmljsimporter_p.h6
-rw-r--r--src/qmlcompiler/qqmljsutils.cpp44
-rw-r--r--src/qmlcompiler/qqmljsutils_p.h4
5 files changed, 67 insertions, 25 deletions
diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake
index 91087da66f..e0ee5d34c9 100644
--- a/src/qml/Qt6QmlMacros.cmake
+++ b/src/qml/Qt6QmlMacros.cmake
@@ -609,11 +609,10 @@ function(qt6_add_qml_module target)
# QML tooling might need to map build dir paths to source dir paths. Create
# a mapping file before qt6_target_qml_sources() to be able to use it
- if(arg_ENABLE_TYPE_COMPILER)
- # But: for now, only enable this when dealing with qmltc
- _qt_internal_qml_map_build_files(${target} "${arg_QML_FILES}" dir_map_qrc)
- set_property(TARGET ${target} APPEND PROPERTY _qt_generated_qrc_files "${dir_map_qrc}")
- endif()
+ _qt_internal_qml_map_build_files(${target} ${qt_qml_module_resource_prefix} dir_map_qrc)
+ # use different property from _qt_generated_qrc_files since this qrc is
+ # special (and is not a real resource file)
+ set_property(TARGET ${target} APPEND PROPERTY _qt_qml_meta_qrc_files "${dir_map_qrc}")
set(cache_target)
qt6_target_qml_sources(${target}
@@ -1150,7 +1149,7 @@ endfunction()
# creates a QRC mapping between QML files in build directory and QML files in
# source directory
-function(_qt_internal_qml_map_build_files target qml_files qrc_file_out_var)
+function(_qt_internal_qml_map_build_files target qml_module_prefix qrc_file_out_var)
get_target_property(output_dir ${target} QT_QML_MODULE_OUTPUT_DIRECTORY)
if(NOT output_dir)
# TODO: we might want to support non-qml modules here (think QML
@@ -1161,14 +1160,7 @@ function(_qt_internal_qml_map_build_files target qml_files qrc_file_out_var)
endif()
set(qrcContents "")
-
- foreach(qml_file IN LISTS qml_files)
- get_filename_component(src_dir_path ${qml_file} ABSOLUTE)
- # Note: follow the logic of cloning the QML file over to build dir
- __qt_get_relative_resource_path_for_file(file_resource_path ${qml_file})
- set(build_dir_path "${output_dir}/${file_resource_path}")
- string(APPEND qrcContents " <file alias=\"${src_dir_path}\">${build_dir_path}</file>\n")
- endforeach()
+ string(APPEND qrcContents " <file alias=\"${qml_module_prefix}\">${output_dir}</file>\n")
# dump the contents into the .qrc file
set(template_file "${__qt_qml_macros_module_base_dir}/Qt6QmlModuleDirMappingTemplate.qrc.in")
@@ -1236,15 +1228,6 @@ function(_qt_internal_target_enable_qmltc target)
message(FATAL_ERROR "\"${target}\" is not a known target")
endif()
- get_target_property(prefix ${target} QT_QML_MODULE_RESOURCE_PREFIX)
- if (NOT prefix)
- message(FATAL_ERROR
- "Target is not a QML module? QT_QML_MODULE_RESOURCE_PREFIX is unspecified")
- endif()
- if(NOT prefix MATCHES [[/$]])
- string(APPEND prefix "/")
- endif()
-
get_target_property(target_source_dir ${target} SOURCE_DIR)
get_target_property(target_binary_dir ${target} BINARY_DIR)
@@ -1341,6 +1324,12 @@ function(_qt_internal_target_enable_qmltc target)
_qt_internal_genex_getjoinedproperty(qrc_args ${target}
_qt_generated_qrc_files "--resource$<SEMICOLON>" "$<SEMICOLON>"
)
+ # qmltc also needs meta data qrc files when importing types from own module
+ _qt_internal_genex_getjoinedproperty(metadata_qrc_args ${target}
+ _qt_qml_meta_qrc_files "--meta-resource$<SEMICOLON>" "$<SEMICOLON>"
+ )
+ list(APPEND qrc_args ${metadata_qrc_args})
+
# NB: pass qml files variable as string to preserve its list nature
# (otherwise we lose all but first element of the list inside a function)
_qt_internal_qml_add_qmltc_file_mapping_resource(
@@ -1388,6 +1377,7 @@ function(_qt_internal_target_enable_qmltc target)
"${file_absolute}"
${qml_module_files}
$<TARGET_PROPERTY:${target},_qt_generated_qrc_files>
+ $<TARGET_PROPERTY:${target},_qt_qml_meta_qrc_files>
${qmltc_file_map_qrc}
COMMENT "Compiling ${qml_file_src} with qmltc"
VERBATIM
diff --git a/src/qml/Qt6QmlModuleDirMappingTemplate.qrc.in b/src/qml/Qt6QmlModuleDirMappingTemplate.qrc.in
index 3cbe0acea0..e7e376bcb2 100644
--- a/src/qml/Qt6QmlModuleDirMappingTemplate.qrc.in
+++ b/src/qml/Qt6QmlModuleDirMappingTemplate.qrc.in
@@ -1,5 +1,5 @@
<RCC>
- <qresource prefix="/qt_qml_module_dir_mapping/">
+ <qresource prefix="/">
@qt_qml_module_dir_mapping_contents@
</qresource>
</RCC>
diff --git a/src/qmlcompiler/qqmljsimporter_p.h b/src/qmlcompiler/qqmljsimporter_p.h
index 45e527b967..6aec963586 100644
--- a/src/qmlcompiler/qqmljsimporter_p.h
+++ b/src/qmlcompiler/qqmljsimporter_p.h
@@ -34,9 +34,12 @@ public:
QQmlJSImporter(const QStringList &importPaths, QQmlJSResourceFileMapper *mapper,
bool useOptionalImports = false);
- QQmlJSResourceFileMapper *resourceFileMapper() { return m_mapper; }
+ QQmlJSResourceFileMapper *resourceFileMapper() const { return m_mapper; }
void setResourceFileMapper(QQmlJSResourceFileMapper *mapper) { m_mapper = mapper; }
+ QQmlJSResourceFileMapper *metaDataMapper() const { return m_metaDataMapper; }
+ void setMetaDataMapper(QQmlJSResourceFileMapper *mapper) { m_metaDataMapper = mapper; }
+
ImportedTypes importBuiltins();
void importQmldirs(const QStringList &qmltypesFiles);
@@ -143,6 +146,7 @@ private:
QList<QQmlJS::DiagnosticMessage> m_warnings;
AvailableTypes m_builtins;
QQmlJSResourceFileMapper *m_mapper = nullptr;
+ QQmlJSResourceFileMapper *m_metaDataMapper = nullptr;
bool m_useOptionalImports;
ImportVisitorCreator m_createImportVisitor = nullptr;
diff --git a/src/qmlcompiler/qqmljsutils.cpp b/src/qmlcompiler/qqmljsutils.cpp
index c07c0b6845..548c86eb67 100644
--- a/src/qmlcompiler/qqmljsutils.cpp
+++ b/src/qmlcompiler/qqmljsutils.cpp
@@ -146,3 +146,47 @@ std::optional<FixSuggestion> QQmlJSUtils::didYouMean(const QString &userInput,
return {};
}
}
+
+/*! \internal
+
+ Returns a corresponding source directory path for \a buildDirectoryPath
+ Returns empty string on error
+*/
+std::variant<QString, QQmlJS::DiagnosticMessage>
+QQmlJSUtils::sourceDirectoryPath(const QQmlJSImporter *importer, const QString &buildDirectoryPath)
+{
+ const auto makeError = [](const QString &msg) {
+ return QQmlJS::DiagnosticMessage { msg, QtWarningMsg, QQmlJS::SourceLocation() };
+ };
+
+ if (!importer->metaDataMapper())
+ return makeError(u"QQmlJSImporter::metaDataMapper() is nullptr"_s);
+
+ // for now, meta data contains just a single entry
+ QQmlJSResourceFileMapper::Filter matchAll { QString(), QStringList(),
+ QQmlJSResourceFileMapper::Directory
+ | QQmlJSResourceFileMapper::Recurse };
+ QQmlJSResourceFileMapper::Entry entry = importer->metaDataMapper()->entry(matchAll);
+ if (!entry.isValid())
+ return makeError(u"Failed to find meta data entry in QQmlJSImporter::metaDataMapper()"_s);
+ if (!buildDirectoryPath.startsWith(entry.filePath)) // assume source directory path already
+ return makeError(u"The module output directory does not match the build directory path"_s);
+
+ QString qrcPath = buildDirectoryPath;
+ qrcPath.remove(0, entry.filePath.size());
+ qrcPath.prepend(entry.resourcePath);
+ qrcPath.remove(0, 1); // remove extra "/"
+
+ const QStringList sourceDirPaths = importer->resourceFileMapper()->filePaths(
+ QQmlJSResourceFileMapper::resourceFileFilter(qrcPath));
+ if (sourceDirPaths.size() != 1) {
+ const QString matchedPaths =
+ sourceDirPaths.isEmpty() ? u"<none>"_s : sourceDirPaths.join(u", ");
+ return makeError(
+ QStringLiteral("QRC path %1 (deduced from %2) has unexpected number of mappings "
+ "(%3). File paths that matched:\n%4")
+ .arg(qrcPath, buildDirectoryPath, QString::number(sourceDirPaths.size()),
+ matchedPaths));
+ }
+ return sourceDirPaths[0];
+}
diff --git a/src/qmlcompiler/qqmljsutils_p.h b/src/qmlcompiler/qqmljsutils_p.h
index 3698d3861b..ab3dbd9745 100644
--- a/src/qmlcompiler/qqmljsutils_p.h
+++ b/src/qmlcompiler/qqmljsutils_p.h
@@ -29,6 +29,7 @@
#include <optional>
#include <functional>
#include <type_traits>
+#include <variant>
QT_BEGIN_NAMESPACE
@@ -333,6 +334,9 @@ struct Q_QMLCOMPILER_PRIVATE_EXPORT QQmlJSUtils
static std::optional<FixSuggestion> didYouMean(const QString &userInput,
QStringList candidates,
QQmlJS::SourceLocation location);
+
+ static std::variant<QString, QQmlJS::DiagnosticMessage>
+ sourceDirectoryPath(const QQmlJSImporter *importer, const QString &buildDirectoryPath);
};
QT_END_NAMESPACE