aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2022-01-24 13:46:58 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-02-03 08:46:02 +0000
commit4cbbe17dedd0274e0e46c523d0f868a87ae7e957 (patch)
treeb7394e8e609a453cf0eddaf1571408d40a5a9800
parent1140e5551ebb6f67252ba4af193015e5d4ceaaf0 (diff)
qmltc: Rely on QQmlJSResourceFileMapper
Similarly to qmllint, we should use QQmlJSResourceFileMapper in qmltc. This should in theory allow us to avoid implicit import dir vs qmldir path issues (where the former comes from source dir while the latter comes from build dir) At present, it does not seem to be the case, however. But this is to be addressed separately Task-number: QTBUG-100103 Change-Id: Ie85799cb0a4b8b1620964000bc5939e9d046678e Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> (cherry picked from commit 8a72c684464a48595337b01ada5605f612f7971e) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/qml/Qt6QmlMacros.cmake14
-rw-r--r--tests/auto/qml/qmltc_qprocess/CMakeLists.txt9
-rw-r--r--tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp18
-rw-r--r--tools/qmltc/main.cpp44
4 files changed, 66 insertions, 19 deletions
diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake
index 5cfc44c40e..a9898af84e 100644
--- a/src/qml/Qt6QmlMacros.cmake
+++ b/src/qml/Qt6QmlMacros.cmake
@@ -1073,6 +1073,8 @@ function(qt6_target_compile_qml_to_cpp target)
get_target_property(output_dir ${target} QT_QML_MODULE_OUTPUT_DIRECTORY)
set(qmldir_file ${output_dir}/qmldir)
+ # TODO: we still need to specify the qmldir here for _explicit_ imports of
+ # own module. in theory this could be pushed to the user side
list(APPEND common_args "-i" ${qmldir_file})
foreach(import_path IN LISTS arg_IMPORT_PATHS)
@@ -1130,6 +1132,12 @@ function(qt6_target_compile_qml_to_cpp target)
endif()
endforeach()
+ # qmltc needs qrc files to supply to the QQmlJSResourceFileMapper
+ _qt_internal_genex_getjoinedproperty(qrc_args ${target}
+ _qt_generated_qrc_files "--resource$<SEMICOLON>" "$<SEMICOLON>"
+ )
+ list(APPEND common_args ${qrc_args})
+
foreach(qml_file_src IN LISTS arg_QML_FILES)
if(NOT qml_file_src MATCHES "\\.(qml)$")
list(APPEND non_qml_files ${qml_file_src})
@@ -1137,10 +1145,6 @@ function(qt6_target_compile_qml_to_cpp target)
endif()
get_filename_component(file_absolute ${qml_file_src} ABSOLUTE)
- __qt_get_relative_resource_path_for_file(file_resource_path ${qml_file_src})
-
- # we ensured earlier that prefix always ends with "/"
- file(TO_CMAKE_PATH "${prefix}${file_resource_path}" file_resource_path)
get_filename_component(file_basename ${file_absolute} NAME_WLE) # extension is always .qml
string(REGEX REPLACE "[$#?]+" "_" compiled_file ${file_basename})
@@ -1169,7 +1173,6 @@ function(qt6_target_compile_qml_to_cpp target)
${qmltc_executable}
--header "${compiled_header}"
--impl "${compiled_cpp}"
- --resource-path "${file_resource_path}"
${common_args}
${file_absolute}
COMMAND_EXPAND_LISTS
@@ -1177,6 +1180,7 @@ function(qt6_target_compile_qml_to_cpp target)
${qmltc_executable}
"${file_absolute}"
${qml_module_files}
+ $<TARGET_PROPERTY:${target},_qt_generated_qrc_files>
)
set_source_files_properties(${compiled_header} ${compiled_cpp}
diff --git a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
index e6a031ddcf..46f1d856d3 100644
--- a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
+++ b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
@@ -15,6 +15,15 @@ qt6_add_qml_module(tst_qmltc_qprocess
)
add_dependencies(tst_qmltc_qprocess Qt::qmltc)
+# fetch --resource arguments manually (mimics the logic of qmltc compilation
+# command)
+_qt_internal_genex_getjoinedproperty(qrc_args tst_qmltc_qprocess
+ _qt_generated_qrc_files "" "_::_"
+)
+target_compile_definitions(tst_qmltc_qprocess PRIVATE
+ TST_QMLTC_QPROCESS_RESOURCES="${qrc_args}"
+)
+
qt_internal_extend_target(tst_qmltc_qprocess CONDITION ANDROID OR IOS
DEFINES
QT_QMLTEST_DATADIR=\\\":/data\\\"
diff --git a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
index 6f12e585ba..7ba31fc652 100644
--- a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
+++ b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
@@ -48,7 +48,7 @@ class tst_qmltc_qprocess : public QQmlDataTest
QString m_qmltcPath;
QString m_tmpPath;
- QHash<QString, QString> m_resourcePaths;
+ QStringList m_resources;
QString runQmltc(const QString &inputFile, std::function<void(QProcess &)> handleResult,
const QStringList &extraArgs = {});
@@ -70,6 +70,10 @@ private slots:
void inlineComponent();
};
+#ifndef TST_QMLTC_QPROCESS_RESOURCES
+# error "This test expects TST_QMLTC_QPROCESS_RESOURCES to be defined through CMake."
+#endif
+
void tst_qmltc_qprocess::initTestCase()
{
QQmlDataTest::initTestCase();
@@ -86,8 +90,7 @@ void tst_qmltc_qprocess::initTestCase()
QVERIFY(QDir(m_tmpPath).removeRecursively()); // in case it's already there
QVERIFY(QDir().mkpath(m_tmpPath));
- m_resourcePaths = { { u"dummy.qml"_qs, u"data/dummy.qml"_qs },
- { u"inlineComponent.qml"_qs, u"data/inlineComponent.qml"_qs } };
+ m_resources = QStringLiteral(TST_QMLTC_QPROCESS_RESOURCES).split(u"_::_"_qs);
}
void tst_qmltc_qprocess::cleanupTestCase()
@@ -102,10 +105,8 @@ QString tst_qmltc_qprocess::runQmltc(const QString &inputFile,
QStringList args;
args << (QFileInfo(inputFile).isAbsolute() ? inputFile : testFile(inputFile));
- if (auto it = m_resourcePaths.constFind(inputFile); it != m_resourcePaths.cend()) {
- // otherwise expect resource path to come from extraArgs
- args << u"--resource-path"_qs << it.value();
- }
+ for (const QString &resource : m_resources)
+ args << u"--resource"_qs << resource;
args << u"--header"_qs << (m_tmpPath + u"/"_qs + QFileInfo(inputFile).baseName() + u".h"_qs);
args << u"--impl"_qs << (m_tmpPath + u"/"_qs + QFileInfo(inputFile).baseName() + u".cpp"_qs);
@@ -147,7 +148,8 @@ QString tst_qmltc_qprocess::runQmltc(const QString &inputFile, bool shouldSuccee
void tst_qmltc_qprocess::sanity()
{
- QVERIFY(runQmltc(u"dummy.qml"_qs, true).isEmpty());
+ const auto output = runQmltc(u"dummy.qml"_qs, true);
+ QVERIFY2(output.isEmpty(), qPrintable(output));
}
void tst_qmltc_qprocess::noBuiltins()
diff --git a/tools/qmltc/main.cpp b/tools/qmltc/main.cpp
index 8ae320c79e..5851f0d7ac 100644
--- a/tools/qmltc/main.cpp
+++ b/tools/qmltc/main.cpp
@@ -33,6 +33,7 @@
#include <QtQml/private/qqmlirbuilder_p.h>
#include <private/qqmljscompiler_p.h>
+#include <private/qqmljsresourcefilemapper_p.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qurl.h>
@@ -86,6 +87,7 @@ int main(int argc, char **argv)
QCoreApplication::translate("main", "h path")
};
parser.addOption(outputHOption);
+
QCommandLineOption resourcePathOption {
u"resource-path"_qs,
QCoreApplication::translate(
@@ -93,6 +95,13 @@ int main(int argc, char **argv)
QCoreApplication::translate("main", "resource path")
};
parser.addOption(resourcePathOption);
+ QCommandLineOption resourceOption {
+ u"resource"_qs,
+ QCoreApplication::translate(
+ "main", "Qt resource file that might later contain one of the compiled files"),
+ QCoreApplication::translate("main", "resource file name")
+ };
+ parser.addOption(resourceOption);
QCommandLineOption namespaceOption {
u"namespace"_qs, QCoreApplication::translate("main", "Namespace of the generated C++ code"),
QCoreApplication::translate("main", "namespace")
@@ -132,7 +141,6 @@ int main(int argc, char **argv)
QStringList importPaths = parser.values(importPathOption);
importPaths.append(QLibraryInfo::path(QLibraryInfo::QmlImportsPath));
- importPaths.append(QFileInfo(url).absolutePath());
QStringList qmldirFiles = parser.values(qmldirOption);
QString outputCppFile;
@@ -149,8 +157,8 @@ int main(int argc, char **argv)
outputHFile = parser.value(outputHOption);
}
- if (!parser.isSet(resourcePathOption)) {
- fprintf(stderr, "No resource path for file: %s\n", qPrintable(inputFile));
+ if (!parser.isSet(resourceOption) && !parser.isSet(resourcePathOption)) {
+ fprintf(stderr, "No resource paths for file: %s\n", qPrintable(inputFile));
return EXIT_FAILURE;
}
@@ -164,19 +172,43 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
+ const QStringList resourceFiles = parser.values(resourceOption);
+ QQmlJSResourceFileMapper mapper(resourceFiles);
+
+ // verify that we can map current file to qrc (then use the qrc path later)
+ const QStringList paths = mapper.resourcePaths(QQmlJSResourceFileMapper::localFileFilter(url));
+ QString resolvedResourcePath;
+ if (paths.size() != 1) {
+ if (parser.isSet(resourcePathOption)) {
+ qWarning("--resource-path option is deprecated. Prefer --resource along with "
+ "automatically generated resource file");
+ resolvedResourcePath = parser.value(resourcePathOption);
+ } else if (paths.isEmpty()) {
+ fprintf(stderr, "Failed to find a resource path for file: %s\n", qPrintable(inputFile));
+ return EXIT_FAILURE;
+ } else if (paths.size() > 1) {
+ fprintf(stderr, "Too many (expected 1) resource paths for file: %s\n",
+ qPrintable(inputFile));
+ return EXIT_FAILURE;
+ }
+ } else {
+ resolvedResourcePath = paths.first();
+ }
+
Options options;
options.outputCppFile = parser.value(outputCppOption);
options.outputHFile = parser.value(outputHOption);
- options.resourcePath = parser.value(resourcePathOption);
+ options.resourcePath = resolvedResourcePath;
options.outNamespace = parser.value(namespaceOption);
- QQmlJSImporter importer { importPaths, /* resource file mapper */ nullptr };
+ QQmlJSImporter importer { importPaths, &mapper };
QQmlJSLogger logger;
logger.setFileName(url);
logger.setCode(sourceCode);
setupLogger(logger);
- Qmltc::Visitor visitor(&importer, &logger, implicitImportDirectory, qmldirFiles);
+ Qmltc::Visitor visitor(&importer, &logger,
+ QQmlJSImportVisitor::implicitImportDirectory(url, &mapper), qmldirFiles);
Qmltc::TypeResolver typeResolver { &importer };
typeResolver.init(visitor, document.program);