diff options
author | Knud Dollereder <knud.dollereder@qt.io> | 2024-02-12 15:37:43 +0100 |
---|---|---|
committer | Knud Dollereder <knud.dollereder@qt.io> | 2024-02-13 10:15:35 +0000 |
commit | ea03bfea10b7c2e5dba1c6cdd8f6aa19ba7d2c59 (patch) | |
tree | 4057add134c1049e4ffc2e6a3a1b38794903cb5e | |
parent | 211ae491308163cdc1c6ce776c9d706792174610 (diff) |
QmlProjectManager: Cleanup cmake generator
- Consider qmlModules file like any other qml module
- Use ${CMAKE_PROJECT_NAME} when possible
- Break up big functions into smaller ones
- Reorder arguments for tpl files
Change-Id: Ie73cca8596b22adf67eba1019610a00c34976421
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
4 files changed, 167 insertions, 146 deletions
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp index 55bcea6a87..2d78026125 100644 --- a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp +++ b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp @@ -19,19 +19,16 @@ namespace GenerateCmake { const char TEMPLATE_CMAKELISTS_ROOT[] = ":/boilerplatetemplates/gencmakeroot.tpl"; const char TEMPLATE_CMAKELISTS_MODULE[] = ":/boilerplatetemplates/gencmakemodule.tpl"; -const char TEMPLATE_QMLMODULES[] = ":/boilerplatetemplates/qmlprojectmodules.tpl"; const char TEMPLATE_SOURCE_MAIN[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl"; const char TEMPLATE_HEADER_IMPORT_COMPS[] = ":/boilerplatetemplates/gencmakeheadercomponents.tpl"; const char TEMPLATE_HEADER_IMPORT_PLUGINS[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl"; const char TEMPLATE_HEADER_ENVIRONMENT[] = ":/boilerplatetemplates/qmlprojectenvheader.tpl"; -const char DO_NOT_EDIT_FILE_COMMENT[] = -"### This file is automatically generated by Qt Design Studio.\n" -"### Do not change\n\n"; +const char DO_NOT_EDIT_FILE_COMMENT[] + = "### This file is automatically generated by Qt Design Studio.\n" + "### Do not change\n\n"; -const char ADD_SUBDIR[] = "add_subdirectory(%1)\n"; - -const char BIG_RESOURCE_TEMPLATE[] = R"( +const char TEMPLATE_BIG_RESOURCES[] = R"( qt6_add_resources(%1 %2 BIG_RESOURCES PREFIX "%3" @@ -39,6 +36,11 @@ qt6_add_resources(%1 %2 FILES %4 ))"; +const char TEMPLATE_LINK_LIBRARIES[] = R"( +target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE +%3 +))"; + CMakeGenerator::CMakeGenerator(QmlBuildSystem *bs, QObject *parent) : QObject(parent) , m_root(std::make_shared<Node>()) @@ -59,7 +61,9 @@ void CMakeGenerator::initialize(QmlProject *project) m_moduleNames.clear(); m_root = std::make_shared<Node>(); - m_root->name = QString("Root"); + m_root->module = true; + m_root->uri = QString("Main"); + m_root->name = QString("Main"); m_root->dir = project->rootProjectDirectory(); m_projectName = project->displayName(); @@ -102,66 +106,48 @@ void CMakeGenerator::update(const QSet<QString> &added, const QSet<QString> &rem createModuleCMakeFile(module); } -std::vector<Utils::FilePath> CMakeGenerator::qmlFiles(const NodePtr &node) const +std::vector<Utils::FilePath> CMakeGenerator::files(const NodePtr &node, + const FileGetter &getter) const { - std::vector<Utils::FilePath> out = node->files; - for (const NodePtr &child : node->subdirs) { + std::vector<Utils::FilePath> out = getter(node); + for (const CMakeGenerator::NodePtr &child : node->subdirs) { if (child->module) continue; - auto childFiles = qmlFiles(child); + auto childFiles = files(child, getter); out.insert(out.end(), childFiles.begin(), childFiles.end()); } return out; } -std::vector<Utils::FilePath> CMakeGenerator::singletons(const NodePtr &node) const +std::vector<Utils::FilePath> CMakeGenerator::qmlFiles(const NodePtr &node) const { - std::vector<Utils::FilePath> out = node->singletons; - for (const NodePtr &child : node->subdirs) { - if (child->module) - continue; + return files(node, [](const NodePtr &n) { return n->files; }); +} - auto childFiles = singletons(child); - out.insert(out.end(), childFiles.begin(), childFiles.end()); - } - return out; +std::vector<Utils::FilePath> CMakeGenerator::singletons(const NodePtr &node) const +{ + return files(node, [](const NodePtr &n) { return n->singletons; }); } std::vector<Utils::FilePath> CMakeGenerator::resources(const NodePtr &node) const { - std::vector<Utils::FilePath> out = node->resources; - for (const NodePtr &child : node->subdirs) { - if (child->module) - continue; - - auto childFiles = resources(child); - out.insert(out.end(), childFiles.begin(), childFiles.end()); - } - return out; + return files(node, [](const NodePtr &n) { return n->resources; }); } std::vector<Utils::FilePath> CMakeGenerator::sources(const NodePtr &node) const { - std::vector<Utils::FilePath> out = node->sources; - for (const NodePtr &child : node->subdirs) { - if (child->module) - continue; - - auto childFiles = sources(child); - out.insert(out.end(), childFiles.begin(), childFiles.end()); - } - return out; + return files(node, [](const NodePtr &n) { return n->sources; }); } void CMakeGenerator::createCMakeFiles(const NodePtr &node) const { - if (node->name == "Root") { + if (isRootNode(node)) createMainCMakeFile(node); - createQmlModuleFile(node); - } else if (node->module || hasChildModule(node)) { + + if (node->module || hasChildModule(node)) createModuleCMakeFile(node); - } + for (const NodePtr &n : node->subdirs) createCMakeFiles(n); } @@ -183,103 +169,43 @@ void CMakeGenerator::createMainCMakeFile(const NodePtr &node) const writeFile(file, fileContent); } -void CMakeGenerator::createQmlModuleFile(const NodePtr &node) const -{ - const QString appName = m_projectName + "App"; - - QString subdirIncludes; - for (const NodePtr &n : node->subdirs) - subdirIncludes.append(QString(ADD_SUBDIR).arg(n->name)); - - QString modulesAsPlugins; - for (const QString &moduleName : m_moduleNames) - modulesAsPlugins.append(" " + moduleName + "plugin\n"); - - const QString fileTemplate = readTemplate(TEMPLATE_QMLMODULES); - const QString fileContent = fileTemplate.arg(appName, subdirIncludes, modulesAsPlugins); - - const Utils::FilePath file = node->dir.pathAppended("qmlModules"); - writeFile(file, fileContent); -} - void CMakeGenerator::createModuleCMakeFile(const NodePtr &node) const { - QString subDirContent; - for (const NodePtr &n : node->subdirs) { - if (n->module || hasChildModule(n)) - subDirContent.append(QString(ADD_SUBDIR).arg(n->dir.fileName())); - } + Utils::FilePath writeToFile = node->dir.pathAppended("CMakeLists.txt"); - QString content; if (!node->module && hasChildModule(node)) { - content.append(DO_NOT_EDIT_FILE_COMMENT); - content.append(subDirContent); - Utils::FilePath file = node->dir.pathAppended("CMakeLists.txt"); - writeFile(file, content); + QString content(DO_NOT_EDIT_FILE_COMMENT); + content.append(makeSubdirectoriesBlock(node)); + writeFile(writeToFile, content); return; } - auto makeRelative = [](const Utils::FilePath &base, - const Utils::FilePath &converted) -> QString { - return "\"" + Utils::FilePath::calcRelativePath(converted.toString(), base.toString()) + "\""; - }; - - QString uri = node->uri; - if (uri.isEmpty()) - uri = node->dir.baseName(); - - const QString setProperties( - "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n"); - - for (const Utils::FilePath &path : node->singletons) { - content.append(setProperties.arg(path.fileName()).arg("QT_QML_SINGLETON_TYPE").arg("true")); - } - - if (!subDirContent.isEmpty()) - content.append(subDirContent); - - QString qmlFileContent; - for (const Utils::FilePath &path : qmlFiles(node)) { - qmlFileContent.append(QString(" %1\n").arg(makeRelative(node->dir, path))); - } + QString templatePrefix; + templatePrefix.append(makeSubdirectoriesBlock(node)); + templatePrefix.append(makeSingletonBlock(node)); + auto [resources, bigResources] = makeResourcesBlocks(node); QString moduleContent; - if (!qmlFileContent.isEmpty()) - moduleContent.append(QString(" QML_FILES\n%1").arg(qmlFileContent)); + moduleContent.append(makeQmlFilesBlock(node)); + moduleContent.append(resources); - std::vector<QString> bigResources; - QString resourceFiles; - for (const Utils::FilePath &path : resources(node)) { - if (path.fileSize() > 5000000) { - bigResources.push_back(makeRelative(node->dir, path)); - continue; - } - resourceFiles.append(QString(" %1\n").arg(makeRelative(node->dir, path))); - } + QString templatePostfix; + templatePostfix.append(bigResources); - if (!resourceFiles.isEmpty()) - moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles)); + if (isRootNode(node)) { + writeToFile = node->dir.pathAppended("qmlModules"); + QString pluginNames; + for (const QString &moduleName : m_moduleNames) + pluginNames.append(" " + moduleName + "plugin\n"); - QString bigResourceContent; - if (!bigResources.empty()) { - QString resourceContent; - for (const QString &res : bigResources) - resourceContent.append(QString("\n %1").arg(res)); - - const QString prefixPath = QString(uri).replace('.', '/'); - const QString prefix = "/qt/qml/" + prefixPath; - const QString resourceName = node->name + "BigResource"; - - bigResourceContent = QString::fromUtf8(BIG_RESOURCE_TEMPLATE, -1) - .arg(node->name, resourceName, prefix, resourceContent); + templatePostfix += QString::fromUtf8(TEMPLATE_LINK_LIBRARIES, -1).arg(pluginNames); } const QString fileTemplate = readTemplate(TEMPLATE_CMAKELISTS_MODULE); - const QString fileContent = - fileTemplate.arg(content, node->name, uri, moduleContent, bigResourceContent); + const QString fileContent + = fileTemplate.arg(node->name, node->uri, templatePrefix, moduleContent, templatePostfix); - const Utils::FilePath file = node->dir.pathAppended("CMakeLists.txt"); - writeFile(file, fileContent); + writeFile(writeToFile, fileContent); } void CMakeGenerator::createEntryPoints(const NodePtr &node) const @@ -295,6 +221,7 @@ void CMakeGenerator::createMainCppFile(const NodePtr &node) const const Utils::FilePath componentsHeaderPath = srcDir.pathAppended( "import_qml_components_plugins.h"); + const QString componentsHeaderContent = readTemplate(TEMPLATE_HEADER_IMPORT_COMPS); writeFile(componentsHeaderPath, componentsHeaderContent); @@ -314,7 +241,8 @@ void CMakeGenerator::createMainCppFile(const NodePtr &node) const value.prepend(":/"); environment.append(QString(" qputenv(\"%1\", \"%2\");\n").arg(key).arg(value)); } - const QString envHeaderContent = readTemplate(TEMPLATE_HEADER_ENVIRONMENT).arg(environment); + const QString envHeaderContent + = readTemplate(TEMPLATE_HEADER_ENVIRONMENT).arg(environment); writeFile(envHeaderPath, envHeaderContent); } } @@ -337,10 +265,15 @@ void CMakeGenerator::writeFile(const Utils::FilePath &path, const QString &conte fileHandle.close(); } -QString CMakeGenerator::makeEnvironmentVariable(const QString &key) const +QString CMakeGenerator::makeRelative(const NodePtr &node, const Utils::FilePath &path) const { - QString value = {}; + const QString dir = node->dir.toString(); + return "\"" + Utils::FilePath::calcRelativePath(path.toString(), dir) + "\""; +} +QString CMakeGenerator::makeEnvironmentVariable(const QString &key) const +{ + QString value; if (m_buildSystem) { auto envItems = m_buildSystem->environment(); auto confEnv = std::find_if(envItems.begin(), @@ -352,6 +285,78 @@ QString CMakeGenerator::makeEnvironmentVariable(const QString &key) const return value; } +QString CMakeGenerator::makeSingletonBlock(const NodePtr &node) const +{ + const QString setProperties( + "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n"); + + QString str; + for (const Utils::FilePath &path : node->singletons) + str.append(setProperties.arg(path.fileName()).arg("QT_QML_SINGLETON_TYPE").arg("true")); + return str; +} + +QString CMakeGenerator::makeSubdirectoriesBlock(const NodePtr &node) const +{ + QString str; + for (const NodePtr &n : node->subdirs) { + if (n->module || hasChildModule(n)) + str.append(QString("add_subdirectory(%1)\n").arg(n->dir.fileName())); + } + return str; +} + +QString CMakeGenerator::makeQmlFilesBlock(const NodePtr &node) const +{ + QString qmlFileContent; + for (const Utils::FilePath &path : qmlFiles(node)) + qmlFileContent.append(QString(" %1\n").arg(makeRelative(node, path))); + + if (isRootNode(node) && qmlFileContent.isEmpty()) + qmlFileContent.append(QString(" %1\n").arg("\"main.qml\"")); + + QString str; + if (!qmlFileContent.isEmpty()) + str.append(QString(" QML_FILES\n%1").arg(qmlFileContent)); + + return str; +} + +std::tuple<QString, QString> CMakeGenerator::makeResourcesBlocks(const NodePtr &node) const +{ + QString resourcesOut; + QString bigResourcesOut; + + QString resourceFiles; + std::vector<QString> bigResources; + for (const Utils::FilePath &path : resources(node)) { + if (path.fileSize() > 5000000) { + bigResources.push_back(makeRelative(node, path)); + continue; + } + resourceFiles.append(QString(" %1\n").arg(makeRelative(node, path))); + } + + if (!resourceFiles.isEmpty()) + resourcesOut.append(QString(" RESOURCES\n%1").arg(resourceFiles)); + + QString templatePostfix; + if (!bigResources.empty()) { + QString resourceContent; + for (const QString &res : bigResources) + resourceContent.append(QString("\n %1").arg(res)); + + const QString prefixPath = QString(node->uri).replace('.', '/'); + const QString prefix = "/qt/qml/" + prefixPath; + const QString resourceName = node->name + "BigResource"; + + bigResourcesOut = QString::fromUtf8(TEMPLATE_BIG_RESOURCES, -1) + .arg(node->name, resourceName, prefix, resourceContent); + } + + return {resourcesOut, bigResourcesOut}; +} + QString CMakeGenerator::readTemplate(const QString &templatePath) const { QFile templatefile(templatePath); @@ -384,7 +389,6 @@ void CMakeGenerator::readQmlDir(const Utils::FilePath &filePath, NodePtr &node) node->singletons.push_back(tmp); } } - f.close(); } @@ -470,6 +474,11 @@ void CMakeGenerator::removeFile(NodePtr &node, const Utils::FilePath &path) cons } } +bool CMakeGenerator::isRootNode(const NodePtr &node) const +{ + return node->name == "Main"; +} + bool CMakeGenerator::hasChildModule(const NodePtr &node) const { for (const NodePtr &child : node->subdirs) { @@ -484,11 +493,20 @@ bool CMakeGenerator::hasChildModule(const NodePtr &node) const bool CMakeGenerator::isResource(const Utils::FilePath &path) const { static const QStringList suffixes = { - "json", "mesh", "dae", "qad", "hints", "png", "hdr", "ttf", "jpg", - "JPG", "js", "qsb", "frag", "frag.qsb", "vert", "vert.qsb", "svg", "ktx"}; + "json", "mesh", "dae", "qad", "hints", "png", "hdr", "ttf", "jpg", "JPG", + "js", "qsb", "frag", "frag.qsb", "vert", "vert.qsb", "svg", "ktx"}; return suffixes.contains(path.suffix()); } +void CMakeGenerator::printModules(const NodePtr &node) const +{ + if (node->module) + qDebug() << "Module: " << node->name; + + for (const auto &child : node->subdirs) + printModules(child); +} + void CMakeGenerator::printNodeTree(const NodePtr &generatorNode, size_t indent) const { auto addIndent = [](size_t level) -> QString { @@ -516,8 +534,9 @@ void CMakeGenerator::parseNodeTree(NodePtr &generatorNode, if (const auto *subFolderNode = childNode->asFolderNode()) { CMakeGenerator::NodePtr childGeneratorNode = std::make_shared<Node>(); childGeneratorNode->parent = generatorNode; - childGeneratorNode->name = subFolderNode->displayName(); childGeneratorNode->dir = subFolderNode->filePath(); + childGeneratorNode->name = subFolderNode->displayName(); + childGeneratorNode->uri = childGeneratorNode->name; parseNodeTree(childGeneratorNode, subFolderNode); generatorNode->subdirs.push_back(childGeneratorNode); } else if (auto *fileNode = childNode->asFileNode()) { diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h index 54445d3561..f89257ac5d 100644 --- a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h +++ b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h @@ -17,11 +17,6 @@ class QmlBuildSystem; namespace GenerateCmake { -// TODO: -// - Create "module" for src dir -// - Replace AppName in templates with ${CMAKE_PROJECT_NAME} -// - Introduce Blacklist (designer) - class CMakeGenerator : public QObject { Q_OBJECT @@ -53,15 +48,15 @@ private: }; using NodePtr = std::shared_ptr<Node>; + using FileGetter = std::function<std::vector<Utils::FilePath>(const NodePtr &)>; + std::vector<Utils::FilePath> files(const NodePtr &node, const FileGetter &getter) const; std::vector<Utils::FilePath> qmlFiles(const NodePtr &node) const; std::vector<Utils::FilePath> singletons(const NodePtr &node) const; std::vector<Utils::FilePath> resources(const NodePtr &node) const; std::vector<Utils::FilePath> sources(const NodePtr &node) const; void createCMakeFiles(const NodePtr &node) const; - - void createQmlModuleFile(const NodePtr &node) const; void createMainCMakeFile(const NodePtr &node) const; void createModuleCMakeFile(const NodePtr &node) const; @@ -69,7 +64,12 @@ private: void createMainCppFile(const NodePtr &node) const; void writeFile(const Utils::FilePath &path, const QString &content) const; + QString makeRelative(const NodePtr &node, const Utils::FilePath &path) const; QString makeEnvironmentVariable(const QString &key) const; + QString makeSingletonBlock(const NodePtr &node) const; + QString makeSubdirectoriesBlock(const NodePtr &node) const; + QString makeQmlFilesBlock(const NodePtr &node) const; + std::tuple<QString, QString> makeResourcesBlocks(const NodePtr &node) const; QString readTemplate(const QString &templatePath) const; void readQmlDir(const Utils::FilePath &filePath, NodePtr &node) const; @@ -81,9 +81,11 @@ private: void insertFile(NodePtr &node, const Utils::FilePath &path) const; void removeFile(NodePtr &node, const Utils::FilePath &path) const; + bool isRootNode(const NodePtr &node) const; bool hasChildModule(const NodePtr &node) const; bool isResource(const Utils::FilePath &path) const; + void printModules(const NodePtr &generatorNode) const; void printNodeTree(const NodePtr &generatorNode, size_t indent = 0) const; void parseNodeTree(NodePtr &generatorNode, const ProjectExplorer::FolderNode *folderNode); diff --git a/src/plugins/qmlprojectmanager/cmakegen/gencmakemodule.tpl b/src/plugins/qmlprojectmanager/cmakegen/gencmakemodule.tpl index 7c4b38b043..b81d253c90 100644 --- a/src/plugins/qmlprojectmanager/cmakegen/gencmakemodule.tpl +++ b/src/plugins/qmlprojectmanager/cmakegen/gencmakemodule.tpl @@ -1,11 +1,11 @@ ### This file is automatically generated by Qt Design Studio. ### Do not change -%1 +%3 -qt_add_library(%2 STATIC) -qt6_add_qml_module(%2 - URI "%3" +qt_add_library(%1 STATIC) +qt6_add_qml_module(%1 + URI "%2" VERSION 1.0 RESOURCE_PREFIX "/qt/qml" %4 diff --git a/src/plugins/qmlprojectmanager/cmakegen/gencmakeroot.tpl b/src/plugins/qmlprojectmanager/cmakegen/gencmakeroot.tpl index 0b8553d195..a23a311c1a 100644 --- a/src/plugins/qmlprojectmanager/cmakegen/gencmakeroot.tpl +++ b/src/plugins/qmlprojectmanager/cmakegen/gencmakeroot.tpl @@ -19,14 +19,14 @@ if (Qt6_VERSION VERSION_GREATER_EQUAL 6.3) qt_standard_project_setup() endif() -qt_add_executable(%1 %2) +qt_add_executable(${CMAKE_PROJECT_NAME} %2) -qt_add_resources(%1 "configuration" +qt_add_resources(${CMAKE_PROJECT_NAME} "configuration" PREFIX "/" %3 ) -target_link_libraries(%1 PRIVATE +target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Quick @@ -44,7 +44,7 @@ if (LINK_INSIGHT) endif () include(GNUInstallDirs) -install(TARGETS %1 +install(TARGETS ${CMAKE_PROJECT_NAME} BUNDLE DESTINATION . LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} |