From bf4a85d60c70158d00e08900db03c82f00c87956 Mon Sep 17 00:00:00 2001 From: Tapani Mattila Date: Mon, 29 Nov 2021 19:34:43 +0200 Subject: CMake generator: Fix support for deeper module folder structure and asset_imports Task-number: QDS-5585 Change-Id: Id7d6f551acc5692a6c7c580d5ffc90ca7528bbc8 Reviewed-by: Thomas Hartmann Reviewed-by: Qt CI Bot --- src/plugins/qmldesigner/generatecmakelists.cpp | 102 ++++++++++++++++----- src/plugins/qmldesigner/generatecmakelists.h | 6 +- .../qmldesigner/generatecmakelistsconstants.h | 2 + .../qmldesigner/qmlprojectmodulecmakelists.tpl | 4 +- src/plugins/qmldesigner/qmlprojectmodules.tpl | 5 +- 5 files changed, 89 insertions(+), 30 deletions(-) diff --git a/src/plugins/qmldesigner/generatecmakelists.cpp b/src/plugins/qmldesigner/generatecmakelists.cpp index 51c199d585..1e49ed3909 100644 --- a/src/plugins/qmldesigner/generatecmakelists.cpp +++ b/src/plugins/qmldesigner/generatecmakelists.cpp @@ -63,13 +63,14 @@ enum ProjectDirectoryError { NoError = 0, MissingContentDir = 1<<1, MissingImportDir = 1<<2, - MissingCppDir = 1<<3, - MissingMainCMake = 1<<4, - MissingMainQml = 1<<5, - MissingAppMainQml = 1<<6, - MissingQmlModules = 1<<7, - MissingMainCpp = 1<<8, - MissingMainCppHeader = 1<<9 + MissingAssetImportDir = 1<<3, + MissingCppDir = 1<<4, + MissingMainCMake = 1<<5, + MissingMainQml = 1<<6, + MissingAppMainQml = 1<<7, + MissingQmlModules = 1<<8, + MissingMainCpp = 1<<9, + MissingMainCppHeader = 1<<10 }; QVector queuedFiles; @@ -131,6 +132,8 @@ int isProjectCorrectlyFormed(const FilePath &rootDir) if (!rootDir.pathAppended(DIRNAME_IMPORT).exists()) errors |= MissingImportDir; + if (!rootDir.pathAppended(DIRNAME_ASSET).exists()) + errors |= MissingAssetImportDir; if (!rootDir.pathAppended(DIRNAME_CPP).exists()) errors |= MissingCppDir; @@ -159,7 +162,7 @@ void removeUnconfirmedQueuedFiles(const Utils::FilePaths confirmedFiles) const QString WARNING_MISSING_STRUCTURE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake", "The project is not properly structured for automatically generating CMake files.\n\nAborting process.\n\nThe following files or directories are missing:\n\n%1"); const QString WARNING_MISSING_STRUCTURE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake", - "The project is not properly structured for automatically generating CMake files.\n\nThe following files will be created:\n\n%1"); + "The project is not properly structured for automatically generating CMake files.\n\nThe following files or directories are missing and may be created:\n\n%1"); const QString WARNING_TITLE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake", "Cannot Generate CMake Files"); const QString WARNING_TITLE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake", @@ -182,6 +185,8 @@ void showProjectDirErrorDialog(int error) if (error & MissingImportDir) fatalList.append(QString(DIRNAME_IMPORT) + "\n"); + if (error & MissingAssetImportDir) + nonFatalList.append(QString(DIRNAME_ASSET) + "\n"); if (error & MissingMainCMake) nonFatalList.append(QString(FILENAME_CMAKELISTS) + "\n"); if (error & MissingQmlModules) @@ -290,16 +295,21 @@ bool generateCmakes(const FilePath &rootDir) { moduleNames.clear(); - FilePath contentDir = rootDir.pathAppended("content"); - FilePath importDir = rootDir.pathAppended("imports"); + FilePath contentDir = rootDir.pathAppended(DIRNAME_CONTENT); + FilePath importDir = rootDir.pathAppended(DIRNAME_IMPORT); + FilePath assetDir = rootDir.pathAppended(DIRNAME_ASSET); generateModuleCmake(contentDir); generateImportCmake(importDir); + generateImportCmake(assetDir); generateMainCmake(rootDir); return true; } +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"; + void generateMainCmake(const FilePath &rootDir) { //TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all. @@ -309,27 +319,47 @@ void generateMainCmake(const FilePath &rootDir) QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH).arg(appName); queueCmakeFile(rootDir, cmakeFileContent); + QString subdirIncludes; + subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_CONTENT)); + subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_IMPORT)); + if (rootDir.pathAppended(DIRNAME_ASSET).exists()) + subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_ASSET)); + QString modulesAsPlugins; for (const QString &moduleName : moduleNames) modulesAsPlugins.append(" " + moduleName + "plugin\n"); - QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH).arg(appName).arg(modulesAsPlugins); + QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH) + .arg(appName) + .arg(subdirIncludes) + .arg(modulesAsPlugins); + GenerateCmake::queueFile(rootDir.pathAppended(FILENAME_MODULES), moduleFileContent); } -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"; - -void generateImportCmake(const FilePath &dir) +void generateImportCmake(const FilePath &dir, const QString &modulePrefix) { + if (!dir.exists()) + return; + QString fileContent; fileContent.append(DO_NOT_EDIT_FILE_COMMENT); - FilePaths subDirs = dir.dirEntries(DIRS_ONLY); for (FilePath &subDir : subDirs) { + if (isDirBlacklisted(subDir)) + continue; + if (getDirectoryTreeQmls(subDir).isEmpty() && getDirectoryTreeResources(subDir).isEmpty()) + continue; fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName())); - generateModuleCmake(subDir); + QString prefix = modulePrefix.isEmpty() ? + modulePrefix % subDir.fileName() : + QString(modulePrefix + '.') + subDir.fileName(); + if (getDirectoryQmls(subDir).isEmpty()) { + generateImportCmake(subDir, prefix); + } else { + generateModuleCmake(subDir, prefix); + } } queueCmakeFile(dir, fileContent); @@ -339,13 +369,12 @@ const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE"; const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n"; const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl"; -void generateModuleCmake(const FilePath &dir) +void generateModuleCmake(const FilePath &dir, const QString &uri) { QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH); - const QStringList qmldirFilesOnly(FILENAME_QMLDIR); QString singletonContent; - FilePaths qmldirFileList = dir.dirEntries(qmldirFilesOnly, FILES_ONLY); + FilePaths qmldirFileList = dir.dirEntries(QStringList(FILENAME_QMLDIR), FILES_ONLY); if (!qmldirFileList.isEmpty()) { QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first()); for (QString &singleton : singletons) { @@ -371,12 +400,14 @@ void generateModuleCmake(const FilePath &dir) moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles)); } - QString moduleName = dir.fileName(); - + QString moduleUri = uri.isEmpty() ? + dir.fileName() : + uri; + QString moduleName = QString(moduleUri).remove('.'); moduleNames.append(moduleName); QString fileContent; - fileContent.append(fileTemplate.arg(singletonContent).arg(moduleName).arg(moduleContent)); + fileContent.append(fileTemplate.arg(singletonContent, moduleName, moduleUri, moduleContent)); queueCmakeFile(dir, fileContent); } @@ -403,6 +434,22 @@ QStringList getSingletonsFromQmldirFile(const FilePath &filePath) return singletons; } +FilePaths getDirectoryQmls(const FilePath &dir) +{ + const QStringList qmlFilesOnly("*.qml"); + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + FilePaths allFiles = dir.dirEntries(qmlFilesOnly, FILES_ONLY); + FilePaths moduleFiles; + for (FilePath &file : allFiles) { + if (!isFileBlacklisted(file.fileName()) && + project->isKnownFile(file)) { + moduleFiles.append(file); + } + } + + return moduleFiles; +} + QStringList getDirectoryTreeQmls(const FilePath &dir) { const QStringList qmlFilesOnly("*.qml"); @@ -419,6 +466,8 @@ QStringList getDirectoryTreeQmls(const FilePath &dir) FilePaths subDirsList = dir.dirEntries(DIRS_ONLY); for (FilePath &subDir : subDirsList) { + if (isDirBlacklisted(subDir)) + continue; QStringList subDirQmlFiles = getDirectoryTreeQmls(subDir); for (QString &qmlFile : subDirQmlFiles) { qmlFileList.append(subDir.fileName().append('/').append(qmlFile)); @@ -444,6 +493,8 @@ QStringList getDirectoryTreeResources(const FilePath &dir) FilePaths subDirsList = dir.dirEntries(DIRS_ONLY); for (FilePath &subDir : subDirsList) { + if (isDirBlacklisted(subDir)) + continue; QStringList subDirResources = getDirectoryTreeResources(subDir); for (QString &resource : subDirResources) { resourceFileList.append(subDir.fileName().append('/').append(resource)); @@ -466,6 +517,11 @@ bool isFileBlacklisted(const QString &fileName) !fileName.compare(FILENAME_CMAKELISTS)); } +bool isDirBlacklisted(const FilePath &dir) +{ + return (!dir.fileName().compare(DIRNAME_DESIGNER)); +} + } namespace GenerateEntryPoints { diff --git a/src/plugins/qmldesigner/generatecmakelists.h b/src/plugins/qmldesigner/generatecmakelists.h index 794610a53f..53c6703ef0 100644 --- a/src/plugins/qmldesigner/generatecmakelists.h +++ b/src/plugins/qmldesigner/generatecmakelists.h @@ -54,13 +54,15 @@ QString readTemplate(const QString &templatePath); namespace GenerateCmakeLists { bool generateCmakes(const Utils::FilePath &rootDir); void generateMainCmake(const Utils::FilePath &rootDir); -void generateImportCmake(const Utils::FilePath &dir); -void generateModuleCmake(const Utils::FilePath &dir); +void generateImportCmake(const Utils::FilePath &dir, const QString &modulePrefix = QString()); +void generateModuleCmake(const Utils::FilePath &dir, const QString &moduleUri = QString()); +Utils::FilePaths getDirectoryQmls(const Utils::FilePath &dir); QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath); QStringList getDirectoryTreeQmls(const Utils::FilePath &dir); QStringList getDirectoryTreeResources(const Utils::FilePath &dir); void queueCmakeFile(const Utils::FilePath &filePath, const QString &content); bool isFileBlacklisted(const QString &fileName); +bool isDirBlacklisted(const Utils::FilePath &dir); } namespace GenerateEntryPoints { bool generateEntryPointFiles(const Utils::FilePath &dir); diff --git a/src/plugins/qmldesigner/generatecmakelistsconstants.h b/src/plugins/qmldesigner/generatecmakelistsconstants.h index 59b11723e4..dce1b8e61b 100644 --- a/src/plugins/qmldesigner/generatecmakelistsconstants.h +++ b/src/plugins/qmldesigner/generatecmakelistsconstants.h @@ -34,7 +34,9 @@ namespace Constants { const char DIRNAME_CONTENT[] = "content"; const char DIRNAME_IMPORT[] = "imports"; +const char DIRNAME_ASSET[] = "asset_imports"; const char DIRNAME_CPP[] = "src"; +const char DIRNAME_DESIGNER[] = "designer"; const char FILENAME_CMAKELISTS[] = "CMakeLists.txt"; const char FILENAME_APPMAINQML[] = "App.qml"; diff --git a/src/plugins/qmldesigner/qmlprojectmodulecmakelists.tpl b/src/plugins/qmldesigner/qmlprojectmodulecmakelists.tpl index 46132d8c1a..e193ebf5ba 100644 --- a/src/plugins/qmldesigner/qmlprojectmodulecmakelists.tpl +++ b/src/plugins/qmldesigner/qmlprojectmodulecmakelists.tpl @@ -5,7 +5,7 @@ qt_add_library(%2 STATIC) qt6_add_qml_module(%2 - URI "%2" + URI "%3" VERSION 1.0 -%3 +%4 ) diff --git a/src/plugins/qmldesigner/qmlprojectmodules.tpl b/src/plugins/qmldesigner/qmlprojectmodules.tpl index 2cae6017cc..a1fdb4071d 100644 --- a/src/plugins/qmldesigner/qmlprojectmodules.tpl +++ b/src/plugins/qmldesigner/qmlprojectmodules.tpl @@ -8,9 +8,8 @@ qt6_add_qml_module(%1 QML_FILES main.qml ) -add_subdirectory(content) -add_subdirectory(imports) +%2 target_link_libraries(%1 PRIVATE -%2 +%3 ) -- cgit v1.2.1