diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-11-07 16:47:26 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-11-08 14:51:35 +0100 |
commit | 9d89702ab26958dbd075de11041af0b230b1230b (patch) | |
tree | 778c65d55a51af6f856df5922fab23a4e59f3f6c /tools | |
parent | ee8589dd9a681a469511308345e4ef0b304aaaab (diff) |
Move qmltyperegistrar into src
We want it to be available early in the build process.
qmltyperegistrar will be required to build qml, quick, and various
imports.
Change-Id: I15b827cd4b322a2bcea2780eeedb8dbe132aa59a
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/qmltyperegistrar/qmltyperegistrar.cpp | 410 | ||||
-rw-r--r-- | tools/qmltyperegistrar/qmltyperegistrar.pro | 26 | ||||
-rw-r--r-- | tools/qmltyperegistrar/qmltypes.prf | 86 | ||||
-rw-r--r-- | tools/qmltyperegistrar/qmltypesclassdescription.cpp | 161 | ||||
-rw-r--r-- | tools/qmltyperegistrar/qmltypesclassdescription.h | 58 | ||||
-rw-r--r-- | tools/qmltyperegistrar/qmltypescreator.cpp | 357 | ||||
-rw-r--r-- | tools/qmltyperegistrar/qmltypescreator.h | 68 | ||||
-rw-r--r-- | tools/shared/shared.pri | 10 | ||||
-rw-r--r-- | tools/tools.pro | 2 |
9 files changed, 8 insertions, 1170 deletions
diff --git a/tools/qmltyperegistrar/qmltyperegistrar.cpp b/tools/qmltyperegistrar/qmltyperegistrar.cpp deleted file mode 100644 index 8813907697..0000000000 --- a/tools/qmltyperegistrar/qmltyperegistrar.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmltypescreator.h" - -#include <QCoreApplication> -#include <QCommandLineParser> -#include <QtDebug> -#include <QJsonDocument> -#include <QJsonArray> -#include <QJsonValue> -#include <QJsonObject> -#include <QFile> -#include <QScopedPointer> -#include <QSaveFile> -#include <QQueue> - -#include <cstdlib> - -struct ScopedPointerFileCloser -{ - static inline void cleanup(FILE *handle) { if (handle) fclose(handle); } -}; - -static bool acceptClassForQmlTypeRegistration(const QJsonObject &classDef) -{ - const QJsonArray classInfos = classDef[QLatin1String("classInfos")].toArray(); - for (const QJsonValue &info: classInfos) { - if (info[QLatin1String("name")].toString() == QLatin1String("QML.Element")) - return true; - } - return false; -} - -static QVector<QJsonObject> foreignRelatedTypes(const QVector<QJsonObject> &types, - const QVector<QJsonObject> &foreignTypes) -{ - const QLatin1String classInfosKey("classInfos"); - const QLatin1String nameKey("name"); - const QLatin1String qualifiedClassNameKey("qualifiedClassName"); - const QLatin1String qmlNamePrefix("QML."); - const QLatin1String qmlForeignName("QML.Foreign"); - const QLatin1String qmlAttachedName("QML.Attached"); - const QLatin1String valueKey("value"); - const QLatin1String superClassesKey("superClasses"); - const QLatin1String accessKey("access"); - const QLatin1String publicAccess("public"); - - QSet<QString> processedRelatedNames; - QQueue<QJsonObject> typeQueue; - typeQueue.append(types.toList()); - QVector<QJsonObject> relatedTypes; - - // First mark all classes registered from this module as already processed. - for (const QJsonObject &type : types) { - processedRelatedNames.insert(type.value(qualifiedClassNameKey).toString()); - const auto classInfos = type.value(classInfosKey).toArray(); - for (const QJsonValue &classInfo : classInfos) { - const QJsonObject obj = classInfo.toObject(); - if (obj.value(nameKey).toString() == qmlForeignName) { - processedRelatedNames.insert(obj.value(valueKey).toString()); - break; - } - } - } - - // Then mark all classes registered from other modules as already processed. - // We don't want to generate them again for this module. - for (const QJsonObject &foreignType : foreignTypes) { - const auto classInfos = foreignType.value(classInfosKey).toArray(); - bool seenQmlPrefix = false; - for (const QJsonValue &classInfo : classInfos) { - const QJsonObject obj = classInfo.toObject(); - const QString name = obj.value(nameKey).toString(); - if (!seenQmlPrefix && name.startsWith(qmlNamePrefix)) { - processedRelatedNames.insert(foreignType.value(qualifiedClassNameKey).toString()); - seenQmlPrefix = true; - } - if (name == qmlForeignName) { - processedRelatedNames.insert(obj.value(valueKey).toString()); - break; - } - } - } - - auto addType = [&](const QString &typeName) { - if (processedRelatedNames.contains(typeName)) - return; - processedRelatedNames.insert(typeName); - if (const QJsonObject *other = QmlTypesClassDescription::findType(foreignTypes, typeName)) { - relatedTypes.append(*other); - typeQueue.enqueue(*other); - } - }; - - // Then recursively iterate the super types and attached types, marking the - // ones we are interested in as related. - while (!typeQueue.isEmpty()) { - const QJsonObject classDef = typeQueue.dequeue(); - - const auto classInfos = classDef.value(classInfosKey).toArray(); - for (const QJsonValue &classInfo : classInfos) { - const QJsonObject obj = classInfo.toObject(); - if (obj.value(nameKey).toString() == qmlAttachedName) { - addType(obj.value(valueKey).toString()); - } else if (obj.value(nameKey).toString() == qmlForeignName) { - const QString foreignClassName = obj.value(valueKey).toString(); - if (const QJsonObject *other = QmlTypesClassDescription::findType( - foreignTypes, foreignClassName)) { - const auto otherSupers = other->value(superClassesKey).toArray(); - if (!otherSupers.isEmpty()) { - const QJsonObject otherSuperObject = otherSupers.first().toObject(); - if (otherSuperObject.value(accessKey).toString() == publicAccess) - addType(otherSuperObject.value(nameKey).toString()); - } - - const auto otherClassInfos = other->value(classInfosKey).toArray(); - for (const QJsonValue &otherClassInfo : otherClassInfos) { - const QJsonObject obj = otherClassInfo.toObject(); - if (obj.value(nameKey).toString() == qmlAttachedName) { - addType(obj.value(valueKey).toString()); - break; - } - // No, you cannot chain QML_FOREIGN declarations. Sorry. - } - break; - } - } - } - - const auto supers = classDef.value(superClassesKey).toArray(); - if (!supers.isEmpty()) { - const QJsonObject superObject = supers.first().toObject(); - if (superObject.value(accessKey).toString() == publicAccess) - addType(superObject.value(nameKey).toString()); - } - } - - return relatedTypes; -} - -int main(int argc, char **argv) -{ - // Produce reliably the same output for the same input by disabling QHash's random seeding. - qSetGlobalQHashSeed(0); - - QCoreApplication app(argc, argv); - QCoreApplication::setApplicationName(QStringLiteral("qmltyperegistrar")); - QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); - - QCommandLineParser parser; - parser.addHelpOption(); - parser.addVersionOption(); - - QCommandLineOption outputOption(QStringLiteral("o")); - outputOption.setDescription(QStringLiteral("Write output to specified file.")); - outputOption.setValueName(QStringLiteral("file")); - outputOption.setFlags(QCommandLineOption::ShortOptionStyle); - parser.addOption(outputOption); - - QCommandLineOption privateIncludesOption( - QStringLiteral("private-includes"), - QStringLiteral("Include headers ending in \"_p.h\" using \"#include <private/foo_p.h>\"" - "rather than \"#include <foo_p.h>\".")); - parser.addOption(privateIncludesOption); - - QCommandLineOption importNameOption(QStringLiteral("import-name")); - importNameOption.setDescription(QStringLiteral("Name of the module to use with QML type registrations.")); - importNameOption.setValueName(QStringLiteral("QML module name")); - parser.addOption(importNameOption); - - QCommandLineOption majorVersionOption(QStringLiteral("major-version")); - majorVersionOption.setDescription(QStringLiteral("Major version to use for type registrations.")); - majorVersionOption.setValueName(QStringLiteral("major version")); - parser.addOption(majorVersionOption); - - QCommandLineOption minorVersionOption(QStringLiteral("minor-version")); - minorVersionOption.setDescription(QStringLiteral("Minor version to use for module registration.")); - minorVersionOption.setValueName(QStringLiteral("minor version")); - parser.addOption(minorVersionOption); - - QCommandLineOption pluginTypesOption(QStringLiteral("generate-plugintypes")); - pluginTypesOption.setDescription(QStringLiteral("Generate plugins.qmltypes into specified directory.")); - pluginTypesOption.setValueName(QStringLiteral("qmltypes target Directory")); - parser.addOption(pluginTypesOption); - - QCommandLineOption foreignTypesOption(QStringLiteral("foreign-types")); - foreignTypesOption.setDescription(QStringLiteral("Consider foreign types when generating plugins.qmltypes.")); - foreignTypesOption.setValueName(QStringLiteral("Comma separated list of other modules to consult for types.")); - parser.addOption(foreignTypesOption); - - QCommandLineOption dependenciesOption(QStringLiteral("dependencies")); - dependenciesOption.setDescription(QStringLiteral("Dependencies to be stated in plugins.qmltypes")); - dependenciesOption.setValueName(QStringLiteral("name of JSON file with dependencies")); - parser.addOption(dependenciesOption); - - parser.addPositionalArgument(QStringLiteral("[MOC generated json file]"), - QStringLiteral("MOC generated json output")); - - parser.process(app); - - FILE *output = stdout; - QScopedPointer<FILE, ScopedPointerFileCloser> outputFile; - - if (parser.isSet(outputOption)) { - QString outputName = parser.value(outputOption); -#if defined(_MSC_VER) - if (_wfopen_s(&output, reinterpret_cast<const wchar_t *>(outputName.utf16()), L"w") != 0) { -#else - output = fopen(QFile::encodeName(outputName).constData(), "w"); // create output file - if (!output) { -#endif - fprintf(stderr, "Error: Cannot open %s for writing\n", qPrintable(outputName)); - return EXIT_FAILURE; - } - outputFile.reset(output); - } - - fprintf(output, - "/****************************************************************************\n" - "** Generated QML type registration code\n**\n"); - fprintf(output, - "** WARNING! All changes made in this file will be lost!\n" - "*****************************************************************************/\n\n"); - fprintf(output, - "#include <QtQml/qqmlengine.h>\n"); - - QStringList includes; - QVector<QJsonObject> types; - QVector<QJsonObject> foreignTypes; - - const QString module = parser.value(importNameOption); - const QStringList files = parser.positionalArguments(); - for (const QString &source: files) { - QJsonDocument metaObjects; - { - QFile f(source); - if (!f.open(QIODevice::ReadOnly)) { - fprintf(stderr, "Error opening %s for reading\n", qPrintable(source)); - return EXIT_FAILURE; - } - QJsonParseError error = {0, QJsonParseError::NoError}; - metaObjects = QJsonDocument::fromJson(f.readAll(), &error); - if (error.error != QJsonParseError::NoError) { - fprintf(stderr, "Error parsing %s\n", qPrintable(source)); - return EXIT_FAILURE; - } - } - - auto processMetaObject = [&](const QJsonObject &metaObject) { - const QJsonArray classes = metaObject[QLatin1String("classes")].toArray(); - for (const auto &cls : classes) { - QJsonObject classDef = cls.toObject(); - if (acceptClassForQmlTypeRegistration(classDef)) { - const QString include = metaObject[QLatin1String("inputFile")].toString(); - const bool declaredInHeader = include.endsWith(QLatin1String(".h")); - if (declaredInHeader) { - includes.append(include); - classDef.insert(QLatin1String("registerable"), true); - } else { - fprintf(stderr, "Cannot generate QML type registration for class %s " - "because it is not declared in a header.", - qPrintable(classDef.value(QLatin1String("qualifiedClassName")) - .toString())); - } - types.append(classDef); - } else { - foreignTypes.append(classDef); - } - } - }; - - if (metaObjects.isArray()) { - const QJsonArray metaObjectsArray = metaObjects.array(); - for (const auto &metaObject : metaObjectsArray) { - if (!metaObject.isObject()) { - fprintf(stderr, "Error parsing %s: JSON is not an object\n", - qPrintable(source)); - return EXIT_FAILURE; - } - - processMetaObject(metaObject.toObject()); - } - } else if (metaObjects.isObject()) { - processMetaObject(metaObjects.object()); - } else { - fprintf(stderr, "Error parsing %s: JSON is not an object or an array\n", - qPrintable(source)); - return EXIT_FAILURE; - } - } - - const QLatin1String qualifiedClassNameKey("qualifiedClassName"); - auto sortTypes = [&](QVector<QJsonObject> &types) { - std::sort(types.begin(), types.end(), [&](const QJsonObject &a, const QJsonObject &b) { - return a.value(qualifiedClassNameKey).toString() < - b.value(qualifiedClassNameKey).toString(); - }); - }; - - sortTypes(types); - - fprintf(output, "\n#include <QtQml/qqmlmoduleregistration.h>"); - const bool privateIncludes = parser.isSet(privateIncludesOption); - for (const QString &include : qAsConst(includes)) { - if (privateIncludes && include.endsWith(QLatin1String("_p.h"))) - fprintf(output, "\n#include <private/%s>", qPrintable(include)); - else - fprintf(output, "\n#include <%s>", qPrintable(include)); - } - - fprintf(output, "\n\n"); - - QString moduleAsSymbol = module; - moduleAsSymbol.replace(QLatin1Char('.'), QLatin1Char('_')); - - const QString functionName = QStringLiteral("qml_register_types_") + moduleAsSymbol; - - fprintf(output, "void %s()\n{", qPrintable(functionName)); - const auto majorVersion = parser.value(majorVersionOption); - - for (const QJsonObject &classDef : qAsConst(types)) { - if (!classDef.value(QLatin1String("registerable")).toBool()) - continue; - - const QString className = classDef[QLatin1String("qualifiedClassName")].toString(); - fprintf(output, "\n qmlRegisterTypesAndRevisions<%s>(\"%s\", %s);", qPrintable(className), - qPrintable(module), qPrintable(majorVersion)); - } - - fprintf(output, "\n qmlRegisterModule(\"%s\", %s, %s);", - qPrintable(module), qPrintable(majorVersion), - qPrintable(parser.value(minorVersionOption))); - fprintf(output, "\n}\n"); - fprintf(output, "\nstatic const QQmlModuleRegistration registration(\"%s\", %s, %s);\n", - qPrintable(module), qPrintable(majorVersion), qPrintable(functionName)); - - if (!parser.isSet(pluginTypesOption)) - return EXIT_SUCCESS; - - if (parser.isSet(foreignTypesOption)) { - const QStringList foreignTypesFiles = parser.value(foreignTypesOption) - .split(QLatin1Char(',')); - for (const QString &types : foreignTypesFiles) { - QFile typesFile(types); - if (!typesFile.open(QIODevice::ReadOnly)) { - fprintf(stderr, "Cannot open foreign types file %s\n", qPrintable(types)); - continue; - } - - QJsonParseError error = {0, QJsonParseError::NoError}; - QJsonDocument foreignMetaObjects = QJsonDocument::fromJson(typesFile.readAll(), &error); - if (error.error != QJsonParseError::NoError) { - fprintf(stderr, "Error parsing %s\n", qPrintable(types)); - continue; - } - - const QJsonArray foreignObjectsArray = foreignMetaObjects.array(); - for (const auto &metaObject : foreignObjectsArray) { - if (!metaObject.isObject()) { - fprintf(stderr, "Error parsing %s: JSON is not an object\n", - qPrintable(types)); - continue; - } - - const QJsonArray classes = metaObject[QLatin1String("classes")].toArray(); - for (const auto &cls : classes) - foreignTypes.append(cls.toObject()); - } - } - } - - sortTypes(foreignTypes); - types += foreignRelatedTypes(types, foreignTypes); - sortTypes(types); - - QmlTypesCreator creator; - creator.setOwnTypes(std::move(types)); - creator.setForeignTypes(std::move(foreignTypes)); - creator.setModule(module); - creator.setMajorVersion(parser.value(majorVersionOption).toInt()); - - creator.generate(parser.value(pluginTypesOption), parser.value(dependenciesOption)); - return EXIT_SUCCESS; -} diff --git a/tools/qmltyperegistrar/qmltyperegistrar.pro b/tools/qmltyperegistrar/qmltyperegistrar.pro deleted file mode 100644 index 802526d964..0000000000 --- a/tools/qmltyperegistrar/qmltyperegistrar.pro +++ /dev/null @@ -1,26 +0,0 @@ -option(host_build) - -QT = core-private -DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII - -QMAKE_TARGET_DESCRIPTION = QML Types Registrar - -INCLUDEPATH += ../shared - -SOURCES += \ - qmltyperegistrar.cpp \ - ../shared/qmlstreamwriter.cpp \ - qmltypesclassdescription.cpp \ - qmltypescreator.cpp - -HEADERS += \ - ../shared/qmlstreamwriter.h \ - qmltypesclassdescription.h \ - qmltypescreator.h - -build_integration.files = qmltypes.prf -build_integration.path = $$[QT_HOST_DATA]/mkspecs/features -prefix_build: INSTALLS += build_integration -else: COPIES += build_integration - -load(qt_tool) diff --git a/tools/qmltyperegistrar/qmltypes.prf b/tools/qmltyperegistrar/qmltypes.prf deleted file mode 100644 index d8e826c671..0000000000 --- a/tools/qmltyperegistrar/qmltypes.prf +++ /dev/null @@ -1,86 +0,0 @@ -CONFIG += metatypes - -qtPrepareTool(QML_TYPEREGISTRAR, qmltyperegistrar) - -isEmpty(QML_IMPORT_VERSION): \ - QML_IMPORT_VERSION = $$IMPORT_VERSION - -# from moc.prf -isEmpty(QML_IMPORT_MAJOR_VERSION):!isEmpty(QML_IMPORT_VERSION): \ - QML_IMPORT_MAJOR_VERSION = $$section(QML_IMPORT_VERSION, ., 0, 0) - -isEmpty(QML_IMPORT_MINOR_VERSION):!isEmpty(QML_IMPORT_VERSION): \ - QML_IMPORT_MINOR_VERSION = $$section(QML_IMPORT_VERSION, ., 1, 1) - -isEmpty(QML_IMPORT_NAME):!isEmpty(TARGETPATH) { - QML_IMPORT_NAME = $$replace(TARGETPATH, "/", ".") - QML_IMPORT_NAME = $$replace(QML_IMPORT_NAME, .$${QML_IMPORT_MAJOR_VERSION}$, '') -} - -isEmpty(QML_IMPORT_NAME) { - error("Need TARGET_PATH or QML_IMPORT_NAME in order to generate qml types."); -} - -isEmpty(QML_IMPORT_MAJOR_VERSION) { - error("Need IMPORT_VERSION, QML_IMPORT_VERSION, or QML_IMPORT_MAJOR_VERSION in order to generate qml types."); -} - -isEmpty(QML_IMPORT_MINOR_VERSION) { - QML_IMPORT_MINOR_VERSION = 0 -} - -isEmpty(QMLTYPES_FILENAME) { - plugin: QMLTYPES_FILENAME = $$OUT_PWD/plugins.qmltypes - else: QMLTYPES_FILENAME = $$OUT_PWD/$${TEMPLATE}.qmltypes -} - -qt_module_deps = $$replace(QT, -private$, '') -qt_module_deps += $$replace(QT_PRIVATE, -private$, '') -qt_module_deps = $$replace(qt_module_deps, _private$, '') -all_qt_module_deps = $$resolve_depends(qt_module_deps, "QT.", ".depends" ".run_depends") -foreign_types = -for(dep, all_qt_module_deps): \ - foreign_types += $$[QT_INSTALL_LIBS]/metatypes/$$lower($$eval(QT.$${dep}.module))_metatypes.json - -QML_TYPEREGISTRAR_FLAGS = \ - --generate-plugintypes=$$QMLTYPES_FILENAME \ - --import-name=$$QML_IMPORT_NAME \ - --major-version=$$QML_IMPORT_MAJOR_VERSION \ - --minor-version=$$QML_IMPORT_MINOR_VERSION \ - --foreign-types=$$join(foreign_types, ',') - -DEPENDENCIESFILE = $$_PRO_FILE_PWD_/dependencies.json -exists($$DEPENDENCIESFILE): QML_TYPEREGISTRAR_FLAGS += --dependencies=$$DEPENDENCIESFILE - -!isEmpty(MODULE_PRIVATE_INCLUDES): QML_TYPEREGISTRAR_FLAGS += --private-includes - -METATYPES_JSON = $$lower($$basename(TARGET))_metatypes.json - -TYPEREGISTRATIONS = $$lower($$basename(TARGET))_qmltyperegistrations$${first(QMAKE_EXT_CPP)} - -qmltyperegistrar_compiler.CONFIG += combine -qmltyperegistrar_compiler.commands = \ - $$QML_TYPEREGISTRAR $$QML_TYPEREGISTRAR_FLAGS -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} -qmltyperegistrar_compiler.input = METATYPES_JSON -qmltyperegistrar_compiler.output = $$TYPEREGISTRATIONS -qmltyperegistrar_compiler.variable_out = SOURCES -qmltyperegistrar_compiler.name = Automatic QML type registration -qmltyperegistrar_compiler.dependency_type = TYPE_C - -qmltyperegistrar_qmltypes.input = METATYPES_JSON -qmltyperegistrar_qmltypes.depends = $$TYPEREGISTRATIONS -qmltyperegistrar_qmltypes.output = $$QMLTYPES_FILENAME -qmltyperegistrar_qmltypes.CONFIG = no_link -qmltyperegistrar_qmltypes.commands = $$escape_expand(\\n) # force creation of rule - -install_qmltypes { - isEmpty(QMLTYPES_INSTALL_DIR): \ - QMLTYPES_INSTALL_DIR = $$[QT_INSTALL_QML]/$$TARGETPATH - do_install.files = $$QMLTYPES_FILENAME - do_install.path = $$QMLTYPES_INSTALL_DIR - do_install.CONFIG += no_link - prefix_build: INSTALLS += do_install - else: COPIES += do_install -} - -QMAKE_EXTRA_COMPILERS += qmltyperegistrar_compiler qmltyperegistrar_qmltypes diff --git a/tools/qmltyperegistrar/qmltypesclassdescription.cpp b/tools/qmltyperegistrar/qmltypesclassdescription.cpp deleted file mode 100644 index 8189bcd52e..0000000000 --- a/tools/qmltyperegistrar/qmltypesclassdescription.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmltypesclassdescription.h" - -#include <QtCore/qjsonarray.h> - -static void collectExtraVersions(const QJsonObject *component, const QString &key, - QList<int> &extraVersions) -{ - const QJsonArray &items = component->value(key).toArray(); - for (const QJsonValue &item : items) { - const QJsonObject obj = item.toObject(); - const auto revision = obj.find(QLatin1String("revision")); - if (revision != obj.end()) { - const int extraVersion = revision.value().toInt(); - if (!extraVersions.contains(extraVersion)) - extraVersions.append(extraVersion); - } - } -} - -const QJsonObject *QmlTypesClassDescription::findType(const QVector<QJsonObject> &types, - const QString &name) -{ - static const QLatin1String qualifiedClassNameKey("qualifiedClassName"); - auto it = std::lower_bound(types.begin(), types.end(), name, - [&](const QJsonObject &type, const QString &typeName) { - return type.value(qualifiedClassNameKey).toString() < typeName; - }); - - return (it != types.end() && it->value(qualifiedClassNameKey) == name) ? &(*it) : nullptr; -} - -void QmlTypesClassDescription::collect(const QJsonObject *classDef, - const QVector<QJsonObject> &types, - const QVector<QJsonObject> &foreign, - bool topLevel) -{ - const auto classInfos = classDef->value(QLatin1String("classInfos")).toArray(); - for (const QJsonValue &classInfo : classInfos) { - const QJsonObject obj = classInfo.toObject(); - const QString name = obj[QLatin1String("name")].toString(); - const QString value = obj[QLatin1String("value")].toString(); - - if (name == QLatin1String("DefaultProperty")) { - if (defaultProp.isEmpty()) - defaultProp = value; - } else if (name == QLatin1String("QML.AddedInMinorVersion")) { - if (topLevel) { - addedInRevision = value.toInt(); - revisions.append(value.toInt()); - } else if (!elementName.isEmpty()) { - revisions.append(value.toInt()); - } - } - - if (!topLevel) - continue; - - // These only apply to the original class - if (name == QLatin1String("QML.Element")) { - if (value == QLatin1String("auto")) - elementName = classDef->value(QLatin1String("className")).toString(); - else if (value != QLatin1String("anonymous")) - elementName = value; - } else if (name == QLatin1String("QML.RemovedInMinorVersion")) { - removedInRevision = value.toInt(); - } else if (name == QLatin1String("QML.Creatable")) { - isCreatable = (value != QLatin1String("false")); - } else if (name == QLatin1String("QML.Attached")) { - attachedType = value; - if (const QJsonObject *other = findType(types, attachedType)) - collect(other, types, foreign, false); - else if (const QJsonObject *other = findType(foreign, attachedType)) - collect(other, types, foreign, false); - } else if (name == QLatin1String("QML.Singleton")) { - if (value == QLatin1String("true")) - isSingleton = true; - } else if (name == QLatin1String("QML.Foreign")) { - if (const QJsonObject *other = findType(foreign, value)) { - classDef = other; - if (defaultProp.isEmpty()) { - // Foreign type can have a default property - const auto classInfos = classDef->value(QLatin1String("classInfos")).toArray(); - for (const QJsonValue &classInfo : classInfos) { - QJsonObject obj = classInfo.toObject(); - if (obj[QLatin1String("name")].toString() == QLatin1String("DefaultProperty")) { - defaultProp = obj[QLatin1String("value")].toString(); - break; - } - } - } - } - } else if (name == QLatin1String("QML.Root")) { - isRootClass = true; - isBuiltin = true; - } else if (name == QLatin1String("QML.Builtin")) { - isBuiltin = true; - } - } - - if (!elementName.isEmpty()) { - collectExtraVersions(classDef, QString::fromLatin1("properties"), revisions); - collectExtraVersions(classDef, QString::fromLatin1("slots"), revisions); - collectExtraVersions(classDef, QString::fromLatin1("methods"), revisions); - collectExtraVersions(classDef, QString::fromLatin1("signals"), revisions); - } - - const auto supers = classDef->value(QLatin1String("superClasses")).toArray(); - if (!supers.isEmpty()) { - const QJsonObject superObject = supers.first().toObject(); - if (superObject[QLatin1String("access")].toString() == QLatin1String("public")) { - const QString superName = superObject[QLatin1String("name")].toString(); - if (topLevel && superClass.isEmpty()) - superClass = superName; - - if (const QJsonObject *other = findType(types, superName)) - collect(other, types, foreign, false); - else if (const QJsonObject *other = findType(foreign, superName)) - collect(other, types, foreign, false); - } - } - - if (addedInRevision == -1) { - revisions.append(0); - addedInRevision = 0; - } - - std::sort(revisions.begin(), revisions.end(), - [](int a, int b) { return QByteArray::number(a) < QByteArray::number(b); }); - const auto end = std::unique(revisions.begin(), revisions.end()); - revisions.erase(end, revisions.end()); - - resolvedClass = classDef; -} diff --git a/tools/qmltyperegistrar/qmltypesclassdescription.h b/tools/qmltyperegistrar/qmltypesclassdescription.h deleted file mode 100644 index 8f3a6ea124..0000000000 --- a/tools/qmltyperegistrar/qmltypesclassdescription.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLTYPESCLASSDESCRIPTION_H -#define QMLTYPESCLASSDESCRIPTION_H - -#include <QtCore/qstring.h> -#include <QtCore/qjsonobject.h> -#include <QtCore/qvector.h> -#include <QtCore/qset.h> - -struct QmlTypesClassDescription -{ - const QJsonObject *resolvedClass = nullptr; - QString elementName; - QString defaultProp; - QString superClass; - QString attachedType; - QList<int> revisions; - int addedInRevision = -1; - int removedInRevision = -1; - bool isCreatable = true; - bool isSingleton = false; - bool isRootClass = false; - bool isBuiltin = false; - - void collect(const QJsonObject *classDef, const QVector<QJsonObject> &types, - const QVector<QJsonObject> &foreign, bool topLevel); - - static const QJsonObject *findType(const QVector<QJsonObject> &types, const QString &name); -}; - -#endif // QMLTYPESCLASSDESCRIPTION_H diff --git a/tools/qmltyperegistrar/qmltypescreator.cpp b/tools/qmltyperegistrar/qmltypescreator.cpp deleted file mode 100644 index 7bac6a87d8..0000000000 --- a/tools/qmltyperegistrar/qmltypescreator.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmltypescreator.h" -#include "qmlstreamwriter.h" -#include "qmltypesclassdescription.h" - -#include <QtCore/qset.h> -#include <QtCore/qjsonarray.h> -#include <QtCore/qsavefile.h> -#include <QtCore/qfile.h> -#include <QtCore/qjsondocument.h> - -static QString enquote(const QString &string) -{ - QString s = string; - return QString::fromLatin1("\"%1\"").arg(s.replace(QLatin1Char('\\'), QLatin1String("\\\\")) - .replace(QLatin1Char('"'),QLatin1String("\\\""))); -} - -void QmlTypesCreator::writeClassProperties(const QmlTypesClassDescription &collector) -{ - m_qml.writeScriptBinding( - QLatin1String("name"), - enquote(collector.resolvedClass->value( - QLatin1String("qualifiedClassName")).toString())); - - if (!collector.defaultProp.isEmpty()) - m_qml.writeScriptBinding(QLatin1String("defaultProperty"), enquote(collector.defaultProp)); - - if (!collector.superClass.isEmpty()) - m_qml.writeScriptBinding(QLatin1String("prototype"), enquote(collector.superClass)); - - if (collector.elementName.isEmpty()) - return; - - QStringList exports; - QStringList metaObjects; - - for (auto it = collector.revisions.begin(), end = collector.revisions.end(); it != end; ++it) { - const int revision = *it; - if (revision < collector.addedInRevision) - continue; - if (collector.removedInRevision > collector.addedInRevision - && revision >= collector.removedInRevision) { - break; - } - - if (collector.isBuiltin) { - exports.append(enquote(QString::fromLatin1("QML/%1 1.0").arg(collector.elementName))); - metaObjects.append(QLatin1String("0")); - } - - exports.append(enquote(QString::fromLatin1("%1/%2 %3.%4") - .arg(m_module).arg(collector.elementName) - .arg(m_majorVersion).arg(revision))); - metaObjects.append(QString::number(revision)); - } - - m_qml.writeArrayBinding(QLatin1String("exports"), exports); - - if (!collector.isCreatable || collector.isSingleton) - m_qml.writeScriptBinding(QLatin1String("isCreatable"), QLatin1String("false")); - - if (collector.isSingleton) - m_qml.writeScriptBinding(QLatin1String("isSingleton"), QLatin1String("true")); - - m_qml.writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), metaObjects); - - if (!collector.attachedType.isEmpty()) - m_qml.writeScriptBinding(QLatin1String("attachedType"), enquote(collector.attachedType)); -} - -void QmlTypesCreator::writeType(const QJsonObject &property, const QString &key, bool isReadonly, - bool parsePointer) -{ - auto it = property.find(key); - if (it == property.end()) - return; - - QString type = (*it).toString(); - if (type.isEmpty() || type == QLatin1String("void")) - return; - - const QLatin1String typeKey("type"); - - bool isList = false; - bool isPointer = false; - - if (type == QLatin1String("QString")) { - type = QLatin1String("string"); - } else if (type == QLatin1String("qreal")) { - type = QLatin1String("double"); - } else if (type == QLatin1String("qint32")) { - type = QLatin1String("int"); - } else if (type == QLatin1String("quint32")) { - type = QLatin1String("uint"); - } else if (type == QLatin1String("qint64")) { - type = QLatin1String("qlonglong"); - } else if (type == QLatin1String("quint64")) { - type = QLatin1String("qulonglong"); - } else { - - const QLatin1String listProperty("QQmlListProperty<"); - if (type.startsWith(listProperty)) { - isList = true; - const int listPropertySize = listProperty.size(); - type = type.mid(listPropertySize, type.size() - listPropertySize - 1); - } - - if (parsePointer && type.endsWith(QLatin1Char('*'))) { - isPointer = true; - type = type.left(type.size() - 1); - } - } - - m_qml.writeScriptBinding(typeKey, enquote(type)); - const QLatin1String trueString("true"); - if (isList) - m_qml.writeScriptBinding(QLatin1String("isList"), trueString); - if (isReadonly) - m_qml.writeScriptBinding(QLatin1String("isReadonly"), trueString); - if (isPointer) - m_qml.writeScriptBinding(QLatin1String("isPointer"), trueString); -} - -void QmlTypesCreator::writeProperties(const QJsonArray &properties, QSet<QString> ¬ifySignals) -{ - for (const QJsonValue &property : properties) { - const QJsonObject obj = property.toObject(); - const QString name = obj[QLatin1String("name")].toString(); - m_qml.writeStartObject(QLatin1String("Property")); - m_qml.writeScriptBinding(QLatin1String("name"), enquote(name)); - const auto it = obj.find(QLatin1String("revision")); - if (it != obj.end()) - m_qml.writeScriptBinding(QLatin1String("revision"), QString::number(it.value().toInt())); - writeType(obj, QLatin1String("type"), !obj.contains(QLatin1String("write")), true); - m_qml.writeEndObject(); - - const QString notify = obj[QLatin1String("notify")].toString(); - if (notify == name + QLatin1String("Changed")) - notifySignals.insert(notify); - } -} - -void QmlTypesCreator::writeMethods(const QJsonArray &methods, const QString &type, - const QSet<QString> ¬ifySignals) -{ - for (const QJsonValue &method : methods) { - const QJsonObject obj = method.toObject(); - if (obj[QLatin1String("access")].toString() != QLatin1String("public")) - continue; - const QString name = obj[QLatin1String("name")].toString(); - const QJsonArray arguments = method[QLatin1String("arguments")].toArray(); - const auto revision = obj.find(QLatin1String("revision")); - if (notifySignals.contains(name) && arguments.isEmpty() && revision == obj.end()) - continue; - m_qml.writeStartObject(type); - m_qml.writeScriptBinding(QLatin1String("name"), enquote(name)); - if (revision != obj.end()) - m_qml.writeScriptBinding(QLatin1String("revision"), QString::number(revision.value().toInt())); - writeType(obj, QLatin1String("returnType"), false, false); - for (const QJsonValue &argument : arguments) { - const QJsonObject obj = argument.toObject(); - m_qml.writeStartObject(QLatin1String("Parameter")); - const QString name = obj[QLatin1String("name")].toString(); - if (!name.isEmpty()) - m_qml.writeScriptBinding(QLatin1String("name"), enquote(name)); - writeType(obj, QLatin1String("type"), false, true); - m_qml.writeEndObject(); - } - m_qml.writeEndObject(); - } -} - -void QmlTypesCreator::writeEnums(const QJsonArray &enums) -{ - for (const auto &item : enums) { - const QJsonObject obj = item.toObject(); - const QJsonArray values = obj.value(QLatin1String("values")).toArray(); - QStringList valueList; - - for (const QJsonValue &value : values) - valueList.append(enquote(value.toString())); - - m_qml.writeStartObject(QLatin1String("Enum")); - m_qml.writeScriptBinding(QLatin1String("name"), - enquote(obj.value(QLatin1String("name")).toString())); - m_qml.writeArrayBinding(QLatin1String("values"), valueList); - m_qml.writeEndObject(); - } -} - -void QmlTypesCreator::writeComponents() -{ - const QLatin1String nameKey("name"); - const QLatin1String signalsKey("signals"); - const QLatin1String enumsKey("enums"); - const QLatin1String propertiesKey("properties"); - const QLatin1String slotsKey("slots"); - const QLatin1String methodsKey("methods"); - const QLatin1String accessKey("access"); - const QLatin1String typeKey("type"); - const QLatin1String argumentsKey("arguments"); - - const QLatin1String destroyedName("destroyed"); - const QLatin1String deleteLaterName("deleteLater"); - const QLatin1String toStringName("toString"); - const QLatin1String destroyName("destroy"); - const QLatin1String delayName("delay"); - - const QLatin1String signalElement("Signal"); - const QLatin1String componentElement("Component"); - const QLatin1String methodElement("Method"); - - const QLatin1String publicAccess("public"); - const QLatin1String intType("int"); - - for (const QJsonObject &component : m_ownTypes) { - m_qml.writeStartObject(componentElement); - - QmlTypesClassDescription collector; - collector.collect(&component, m_ownTypes, m_foreignTypes, true); - - writeClassProperties(collector); - - const QJsonObject *classDef = collector.resolvedClass; - writeEnums(classDef->value(enumsKey).toArray()); - - QSet<QString> notifySignals; - writeProperties(classDef->value(propertiesKey).toArray(), notifySignals); - - if (collector.isRootClass) { - - // Hide destroyed() signals - QJsonArray componentSignals = classDef->value(signalsKey).toArray(); - for (auto it = componentSignals.begin(); it != componentSignals.end();) { - if (it->toObject().value(nameKey).toString() == destroyedName) - it = componentSignals.erase(it); - else - ++it; - } - writeMethods(componentSignals, signalElement, notifySignals); - - // Hide deleteLater() methods - QJsonArray componentMethods = classDef->value(methodsKey).toArray() - + classDef->value(slotsKey).toArray(); - for (auto it = componentMethods.begin(); it != componentMethods.end();) { - if (it->toObject().value(nameKey).toString() == deleteLaterName) - it = componentMethods.erase(it); - else - ++it; - } - - // Add toString() - QJsonObject toStringMethod; - toStringMethod.insert(nameKey, toStringName); - toStringMethod.insert(accessKey, publicAccess); - componentMethods.append(toStringMethod); - - // Add destroy() - QJsonObject destroyMethod; - destroyMethod.insert(nameKey, destroyName); - destroyMethod.insert(accessKey, publicAccess); - componentMethods.append(destroyMethod); - - // Add destroy(int) - QJsonObject destroyMethodWithArgument; - destroyMethodWithArgument.insert(nameKey, destroyName); - destroyMethodWithArgument.insert(accessKey, publicAccess); - QJsonObject delayArgument; - delayArgument.insert(nameKey, delayName); - delayArgument.insert(typeKey, intType); - QJsonArray destroyArguments; - destroyArguments.append(delayArgument); - destroyMethodWithArgument.insert(argumentsKey, destroyArguments); - componentMethods.append(destroyMethodWithArgument); - - writeMethods(componentMethods, methodElement); - } else { - writeMethods(classDef->value(signalsKey).toArray(), signalElement, notifySignals); - writeMethods(classDef->value(slotsKey).toArray(), methodElement); - writeMethods(classDef->value(methodsKey).toArray(), methodElement); - } - m_qml.writeEndObject(); - } -} - -void QmlTypesCreator::generate(const QString &outFileName, const QString &dependenciesFileName) -{ - m_qml.writeStartDocument(); - m_qml.writeLibraryImport(QLatin1String("QtQuick.tooling"), 1, 2); - m_qml.write(QString::fromLatin1( - "\n// This file describes the plugin-supplied types contained in the library." - "\n// It is used for QML tooling purposes only." - "\n//" - "\n// This file was auto-generated by qmltyperegistrar.\n\n")); - m_qml.writeStartObject(QLatin1String("Module")); - - QStringList dependencies; - if (!dependenciesFileName.isEmpty()) { - QFile file(dependenciesFileName); - if (!file.open(QIODevice::ReadOnly)) { - fprintf(stderr, "Failed to open %s\n", qPrintable(dependenciesFileName)); - } else { - QJsonParseError error { -1, QJsonParseError::NoError }; - QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error); - if (error.error != QJsonParseError::NoError) { - fprintf(stderr, "Failed to parse %s\n", qPrintable(dependenciesFileName)); - } else { - const QJsonArray array = doc.array(); - for (const QJsonValue &value : array) - dependencies.append(enquote(value.toString())); - } - } - } else { - // Default dependency is QtQuick 2.0 - dependencies.append(enquote(QLatin1String("QtQuick 2.0"))); - } - - m_qml.writeArrayBinding(QLatin1String("dependencies"), dependencies); - - writeComponents(); - - m_qml.writeEndObject(); - - QSaveFile file(outFileName); - file.open(QIODevice::WriteOnly); - file.write(m_output); - file.commit(); -} - diff --git a/tools/qmltyperegistrar/qmltypescreator.h b/tools/qmltyperegistrar/qmltypescreator.h deleted file mode 100644 index 9207a64b7e..0000000000 --- a/tools/qmltyperegistrar/qmltypescreator.h +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLTYPESCREATOR_H -#define QMLTYPESCREATOR_H - -#include "qmlstreamwriter.h" -#include "qmltypesclassdescription.h" - -#include <QtCore/qstring.h> -#include <QtCore/qset.h> - -class QmlTypesCreator -{ -public: - QmlTypesCreator() : m_qml(&m_output) {} - - void generate(const QString &outFileName, const QString &dependenciesFileName); - - void setOwnTypes(QVector<QJsonObject> ownTypes) { m_ownTypes = std::move(ownTypes); } - void setForeignTypes(QVector<QJsonObject> foreignTypes) { m_foreignTypes = std::move(foreignTypes); } - void setModule(QString module) { m_module = std::move(module); } - void setMajorVersion(int majorVersion) { m_majorVersion = majorVersion; } - -private: - void writeClassProperties(const QmlTypesClassDescription &collector); - void writeType(const QJsonObject &property, const QString &key, bool isReadonly, - bool parsePointer); - void writeProperties(const QJsonArray &properties, QSet<QString> ¬ifySignals); - void writeMethods(const QJsonArray &methods, const QString &type, - const QSet<QString> ¬ifySignals = QSet<QString>()); - void writeEnums(const QJsonArray &enums); - void writeComponents(); - - QByteArray m_output; - QmlStreamWriter m_qml; - QVector<QJsonObject> m_ownTypes; - QVector<QJsonObject> m_foreignTypes; - QString m_module; - int m_majorVersion = 0; -}; - -#endif // QMLTYPESCREATOR_H diff --git a/tools/shared/shared.pri b/tools/shared/shared.pri index c094b51d5f..1438c3b3da 100644 --- a/tools/shared/shared.pri +++ b/tools/shared/shared.pri @@ -1,3 +1,9 @@ INCLUDEPATH += $$PWD -SOURCES += $$PWD/resourcefilemapper.cpp -HEADERS += $$PWD/resourcefilemapper.h + +SOURCES += \ + $$PWD/resourcefilemapper.cpp \ + $$PWD/qmlstreamwriter.cpp + +HEADERS += \ + $$PWD/resourcefilemapper.h \ + $$PWD/qmlstreamwriter.h diff --git a/tools/tools.pro b/tools/tools.pro index 69b79e8816..25ed760903 100644 --- a/tools/tools.pro +++ b/tools/tools.pro @@ -10,8 +10,6 @@ qtConfig(qml-devtools) { qtConfig(commandlineparser):qtConfig(xmlstreamwriter): SUBDIRS += qmlcachegen } -qtConfig(commandlineparser): SUBDIRS += qmltyperegistrar - qtConfig(thread):!android|android_app:!wasm:!rtems { SUBDIRS += \ qml |