diff options
author | Liang Qi <liang.qi@qt.io> | 2017-03-14 10:49:51 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2017-03-14 10:49:51 +0100 |
commit | 12e82111ab86669969430ab10118236d8d846d33 (patch) | |
tree | fb2345160fbe9d46cb61212f4a5eac81389464ba /tools | |
parent | 30635ee2424dbd08bb5c2170be0c2dc5f9d23b2c (diff) | |
parent | 77e0dc0485953427320ed0b442ba24eef4f9d73b (diff) |
Merge remote-tracking branch 'origin/5.9' into dev
Change-Id: I0ec164ce6e8099e6e4d6b40a3c7340737473ef4b
Diffstat (limited to 'tools')
-rw-r--r-- | tools/qmlcachegen/qmlcache.prf | 52 | ||||
-rw-r--r-- | tools/qmlcachegen/qmlcachegen.cpp | 89 | ||||
-rw-r--r-- | tools/qmlcachegen/qmlcachegen.pro | 18 |
3 files changed, 123 insertions, 36 deletions
diff --git a/tools/qmlcachegen/qmlcache.prf b/tools/qmlcachegen/qmlcache.prf index fed9f0d2f3..31c18a231b 100644 --- a/tools/qmlcachegen/qmlcache.prf +++ b/tools/qmlcachegen/qmlcache.prf @@ -1,12 +1,52 @@ -qtPrepareTool(QML_CACHEGEN, qmlcachegen) +static { + message("QML cache generation ahead of time is not supported in static builds") + return() +} + +qtPrepareTool(QML_CACHEGEN, qmlcachegen, _ARCH_CHECK) + +isEmpty(TARGETPATH): error("Must set TARGETPATH (QML import name) for ahead-of-time QML cache generation") !isEmpty(QT_TARGET_ARCH):QML_CACHEGEN_ARCH=$$QT_TARGET_ARCH else:QML_CACHEGEN_ARCH=$$QT_ARCH -qmlcachegen.input = QML_FILES -qmlcachegen.output = ${QMAKE_FILE_IN}c -qmlcachegen.commands = $$QML_CACHEGEN --target-architecture=$$QML_CACHEGEN_ARCH ${QMAKE_FILE_IN} +QML_CACHEGEN_ARGS=--target-architecture=$$QML_CACHEGEN_ARCH + +!system($$QML_CACHEGEN_ARCH_CHECK $$QML_CACHEGEN_ARGS --check-if-supported) { + message("QML cache generation requested but target architecture $$QML_CACHEGEN_ARCH is not supported.") + return() +} + +load(qt_build_paths) + +prefix_build: QMLCACHE_DESTDIR = $$MODULE_BASE_OUTDIR/qml/$$TARGETPATH +else: QMLCACHE_DESTDIR = $$[QT_INSTALL_QML]/$$TARGETPATH + +CACHEGEN_FILES= +qmlcacheinst.files = +for(qmlf, QML_FILES) { + contains(qmlf,.*\\.js$)|contains(qmlf,.*\\.qml$) { + CACHEGEN_FILES += $$absolute_path($$qmlf, $$_PRO_FILE_PWD_) + qmlcacheinst.files += $$QMLCACHE_DESTDIR/$$relative_path($$qmlf, $$_PRO_FILE_PWD_)c + } +} + +defineReplace(qmlCacheOutputFileName) { + return($$relative_path($$QMLCACHE_DESTDIR/$$relative_path($$1, $$_PRO_FILE_PWD_)c, $$OUT_PWD)) +} + +qmlcacheinst.base = $$QMLCACHE_DESTDIR +qmlcacheinst.path = $$[QT_INSTALL_QML]/$$TARGETPATH +qmlcacheinst.CONFIG = no_check_exist + +qmlcachegen.input = CACHEGEN_FILES +qmlcachegen.output = ${QMAKE_FUNC_FILE_IN_qmlCacheOutputFileName} +qmlcachegen.CONFIG = no_link target_predeps +qmlcachegen.commands = $$QML_CACHEGEN $$QML_CACHEGEN_ARGS -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} qmlcachegen.name = Generate QML Cache ${QMAKE_FILE_IN} -qmlcachegen.variable_out = AUX_QML_FILES +qmlcachegen.variable_out = GENERATED_FILES -QMAKE_EXTRA_COMPILERS += qmlcachegen +!debug_and_release|!build_all|CONFIG(release, debug|release) { + QMAKE_EXTRA_COMPILERS += qmlcachegen + INSTALLS += qmlcacheinst +} diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp index 977c5b6ff1..9a68e2ac97 100644 --- a/tools/qmlcachegen/qmlcachegen.cpp +++ b/tools/qmlcachegen/qmlcachegen.cpp @@ -80,7 +80,40 @@ QString diagnosticErrorMessage(const QString &fileName, const QQmlJS::Diagnostic return message; } -static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *iselFactory, Error *error) +// Ensure that ListElement objects keep all property assignments in their string form +static void annotateListElements(QmlIR::Document *document) +{ + QStringList listElementNames; + + foreach (const QV4::CompiledData::Import *import, document->imports) { + const QString uri = document->stringAt(import->uriIndex); + if (uri != QStringLiteral("QtQml.Models") && uri != QStringLiteral("QtQuick")) + continue; + + QString listElementName = QStringLiteral("ListElement"); + const QString qualifier = document->stringAt(import->qualifierIndex); + if (!qualifier.isEmpty()) { + listElementName.prepend(QLatin1Char('.')); + listElementName.prepend(qualifier); + } + listElementNames.append(listElementName); + } + + if (listElementNames.isEmpty()) + return; + + foreach (QmlIR::Object *object, document->objects) { + if (!listElementNames.contains(document->stringAt(object->inheritedTypeNameIndex))) + continue; + for (QmlIR::Binding *binding = object->firstBinding(); binding; binding = binding->next) { + if (binding->type != QV4::CompiledData::Binding::Type_Script) + continue; + binding->stringIndex = document->registerString(object->bindingAsString(document, binding->value.compiledScriptIndex)); + } + } +} + +static bool compileQmlFile(const QString &inputFileName, const QString &outputFileName, QV4::EvalISelFactory *iselFactory, Error *error) { QmlIR::Document irDocument(/*debugMode*/false); @@ -96,7 +129,6 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i error->message = QLatin1String("Error reading from ") + inputFileName + QLatin1Char(':') + f.errorString(); return false; } - irDocument.jsModule.sourceTimeStamp = QFileInfo(f).lastModified().toMSecsSinceEpoch(); } { @@ -112,8 +144,10 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i } } + annotateListElements(&irDocument); + { - QmlIR::JSCodeGen v4CodeGen(inputFileName, irDocument.code, &irDocument.jsModule, &irDocument.jsParserEngine, irDocument.program, /*import cache*/0, &irDocument.jsGenerator.stringTable); + QmlIR::JSCodeGen v4CodeGen(/*empty input file name*/QString(), irDocument.code, &irDocument.jsModule, &irDocument.jsParserEngine, irDocument.program, /*import cache*/0, &irDocument.jsGenerator.stringTable); for (QmlIR::Object *object: qAsConst(irDocument.objects)) { if (object->functionsAndExpressions->count == 0) continue; @@ -153,7 +187,7 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i unit->flags |= QV4::CompiledData::Unit::PendingTypeCompilation; irDocument.javaScriptCompilationUnit->data = unit; - if (!irDocument.javaScriptCompilationUnit->saveToDisk(inputFileName, &error->message)) + if (!irDocument.javaScriptCompilationUnit->saveToDisk(outputFileName, &error->message)) return false; free(unit); @@ -161,7 +195,7 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i return true; } -static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *iselFactory, Error *error) +static bool compileJSFile(const QString &inputFileName, const QString &outputFileName, QV4::EvalISelFactory *iselFactory, Error *error) { QmlIR::Document irDocument(/*debugMode*/false); @@ -177,7 +211,6 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is error->message = QLatin1String("Error reading from ") + inputFileName + QLatin1Char(':') + f.errorString(); return false; } - irDocument.jsModule.sourceTimeStamp = QFileInfo(f).lastModified().toMSecsSinceEpoch(); } QQmlJS::Engine *engine = &irDocument.jsParserEngine; @@ -217,7 +250,7 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is { QmlIR::JSCodeGen v4CodeGen(inputFileName, irDocument.code, &irDocument.jsModule, &irDocument.jsParserEngine, irDocument.program, /*import cache*/0, &irDocument.jsGenerator.stringTable); - v4CodeGen.generateFromProgram(inputFileName, sourceCode, program, &irDocument.jsModule, QQmlJS::Codegen::GlobalCode); + v4CodeGen.generateFromProgram(/*empty input file name*/QString(), sourceCode, program, &irDocument.jsModule, QQmlJS::Codegen::GlobalCode); QList<QQmlJS::DiagnosticMessage> jsErrors = v4CodeGen.errors(); if (!jsErrors.isEmpty()) { for (const QQmlJS::DiagnosticMessage &e: qAsConst(jsErrors)) { @@ -233,7 +266,8 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is // ### translation binding simplification - QScopedPointer<QV4::EvalInstructionSelection> isel(iselFactory->create(/*engine*/nullptr, /*executable allocator*/nullptr, &irDocument.jsModule, &irDocument.jsGenerator)); + QV4::ExecutableAllocator allocator; + QScopedPointer<QV4::EvalInstructionSelection> isel(iselFactory->create(/*engine*/nullptr, &allocator, &irDocument.jsModule, &irDocument.jsGenerator)); // Disable lookups in non-standalone (aka QML) mode isel->setUseFastLookups(false); irDocument.javaScriptCompilationUnit = isel->compile(/*generate unit*/false); @@ -243,7 +277,7 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is unit->flags |= QV4::CompiledData::Unit::StaticData; irDocument.javaScriptCompilationUnit->data = unit; - if (!irDocument.javaScriptCompilationUnit->saveToDisk(inputFileName, &error->message)) { + if (!irDocument.javaScriptCompilationUnit->saveToDisk(outputFileName, &error->message)) { engine->setDirectives(oldDirs); return false; } @@ -270,37 +304,60 @@ int main(int argc, char **argv) QCommandLineOption targetArchitectureOption(QStringLiteral("target-architecture"), QCoreApplication::translate("main", "Target architecture"), QCoreApplication::translate("main", "architecture")); parser.addOption(targetArchitectureOption); + QCommandLineOption outputFileOption(QStringLiteral("o"), QCoreApplication::translate("main", "Output file name"), QCoreApplication::translate("main", "file name")); + parser.addOption(outputFileOption); + + QCommandLineOption checkIfSupportedOption(QStringLiteral("check-if-supported"), QCoreApplication::translate("main", "Check if cache generate is supported on the specified target architecture")); + parser.addOption(checkIfSupportedOption); + parser.addPositionalArgument(QStringLiteral("[qml file]"), QStringLiteral("QML source file to generate cache for.")); parser.process(app); - const QStringList sources = parser.positionalArguments(); - if (sources.isEmpty()){ + if (!parser.isSet(targetArchitectureOption)) { + fprintf(stderr, "Target architecture not specified. Please specify with --target-architecture=<arch>\n"); parser.showHelp(); - } else if (sources.count() > 1) { - fprintf(stderr, "%s\n", qPrintable(QStringLiteral("Too many input files specified: '") + sources.join(QStringLiteral("' '")) + QLatin1Char('\''))); return EXIT_FAILURE; } - const QString inputFile = sources.first(); QScopedPointer<QV4::EvalISelFactory> isel; const QString targetArchitecture = parser.value(targetArchitectureOption); isel.reset(QV4::JIT::createISelForArchitecture(targetArchitecture)); + if (parser.isSet(checkIfSupportedOption)) { + if (isel.isNull()) + return EXIT_FAILURE; + else + return EXIT_SUCCESS; + } + + const QStringList sources = parser.positionalArguments(); + if (sources.isEmpty()){ + parser.showHelp(); + } else if (sources.count() > 1) { + fprintf(stderr, "%s\n", qPrintable(QStringLiteral("Too many input files specified: '") + sources.join(QStringLiteral("' '")) + QLatin1Char('\''))); + return EXIT_FAILURE; + } + const QString inputFile = sources.first(); + if (!isel) isel.reset(new QV4::Moth::ISelFactory); Error error; + QString outputFileName = inputFile + QLatin1Char('c'); + if (parser.isSet(outputFileOption)) + outputFileName = parser.value(outputFileOption); + if (inputFile.endsWith(QLatin1String(".qml"))) { - if (!compileQmlFile(inputFile, isel.data(), &error)) { + if (!compileQmlFile(inputFile, outputFileName, isel.data(), &error)) { error.augment(QLatin1String("Error compiling qml file: ")).print(); return EXIT_FAILURE; } } else if (inputFile.endsWith(QLatin1String(".js"))) { - if (!compileJSFile(inputFile, isel.data(), &error)) { + if (!compileJSFile(inputFile, outputFileName, isel.data(), &error)) { error.augment(QLatin1String("Error compiling qml file: ")).print(); return EXIT_FAILURE; } diff --git a/tools/qmlcachegen/qmlcachegen.pro b/tools/qmlcachegen/qmlcachegen.pro index 81783d0396..25afc2860d 100644 --- a/tools/qmlcachegen/qmlcachegen.pro +++ b/tools/qmlcachegen/qmlcachegen.pro @@ -6,19 +6,9 @@ DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII SOURCES = qmlcachegen.cpp TARGET = qmlcachegen -BUILD_INTEGRATION = qmlcache.prf -!force_independent { - qmake_integration.input = BUILD_INTEGRATION - qmake_integration.output = $$[QT_HOST_DATA]/mkspecs/features/${QMAKE_FILE_BASE}.prf - qmake_integration.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} - qmake_integration.name = COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} - qmake_integration.CONFIG = no_clean no_link - !contains(TEMPLATE, vc.*): qmake_integration.variable_out = GENERATED_FILES - QMAKE_EXTRA_COMPILERS += qmake_integration -} - -qmake_integration_installs.files = $$BUILD_INTEGRATION -qmake_integration_installs.path = $$[QT_HOST_DATA]/mkspecs/features -INSTALLS += qmake_integration_installs +build_integration.files = qmlcache.prf +build_integration.path = $$[QT_HOST_DATA]/mkspecs/features +prefix_build: INSTALLS += build_integration +else: COPIES += build_integration load(qt_tool) |