forked from qt-creator/qt-creator
CMake generator: Fix support for deeper module folder structure and asset_imports
Task-number: QDS-5585 Change-Id: Id7d6f551acc5692a6c7c580d5ffc90ca7528bbc8 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
committed by
Thomas Hartmann
parent
1e537f7ab0
commit
bf4a85d60c
@@ -63,13 +63,14 @@ enum ProjectDirectoryError {
|
|||||||
NoError = 0,
|
NoError = 0,
|
||||||
MissingContentDir = 1<<1,
|
MissingContentDir = 1<<1,
|
||||||
MissingImportDir = 1<<2,
|
MissingImportDir = 1<<2,
|
||||||
MissingCppDir = 1<<3,
|
MissingAssetImportDir = 1<<3,
|
||||||
MissingMainCMake = 1<<4,
|
MissingCppDir = 1<<4,
|
||||||
MissingMainQml = 1<<5,
|
MissingMainCMake = 1<<5,
|
||||||
MissingAppMainQml = 1<<6,
|
MissingMainQml = 1<<6,
|
||||||
MissingQmlModules = 1<<7,
|
MissingAppMainQml = 1<<7,
|
||||||
MissingMainCpp = 1<<8,
|
MissingQmlModules = 1<<8,
|
||||||
MissingMainCppHeader = 1<<9
|
MissingMainCpp = 1<<9,
|
||||||
|
MissingMainCppHeader = 1<<10
|
||||||
};
|
};
|
||||||
|
|
||||||
QVector<GeneratableFile> queuedFiles;
|
QVector<GeneratableFile> queuedFiles;
|
||||||
@@ -131,6 +132,8 @@ int isProjectCorrectlyFormed(const FilePath &rootDir)
|
|||||||
|
|
||||||
if (!rootDir.pathAppended(DIRNAME_IMPORT).exists())
|
if (!rootDir.pathAppended(DIRNAME_IMPORT).exists())
|
||||||
errors |= MissingImportDir;
|
errors |= MissingImportDir;
|
||||||
|
if (!rootDir.pathAppended(DIRNAME_ASSET).exists())
|
||||||
|
errors |= MissingAssetImportDir;
|
||||||
|
|
||||||
if (!rootDir.pathAppended(DIRNAME_CPP).exists())
|
if (!rootDir.pathAppended(DIRNAME_CPP).exists())
|
||||||
errors |= MissingCppDir;
|
errors |= MissingCppDir;
|
||||||
@@ -159,7 +162,7 @@ void removeUnconfirmedQueuedFiles(const Utils::FilePaths confirmedFiles)
|
|||||||
const QString WARNING_MISSING_STRUCTURE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
|
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");
|
"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",
|
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",
|
const QString WARNING_TITLE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
|
||||||
"Cannot Generate CMake Files");
|
"Cannot Generate CMake Files");
|
||||||
const QString WARNING_TITLE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
|
const QString WARNING_TITLE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
|
||||||
@@ -182,6 +185,8 @@ void showProjectDirErrorDialog(int error)
|
|||||||
if (error & MissingImportDir)
|
if (error & MissingImportDir)
|
||||||
fatalList.append(QString(DIRNAME_IMPORT) + "\n");
|
fatalList.append(QString(DIRNAME_IMPORT) + "\n");
|
||||||
|
|
||||||
|
if (error & MissingAssetImportDir)
|
||||||
|
nonFatalList.append(QString(DIRNAME_ASSET) + "\n");
|
||||||
if (error & MissingMainCMake)
|
if (error & MissingMainCMake)
|
||||||
nonFatalList.append(QString(FILENAME_CMAKELISTS) + "\n");
|
nonFatalList.append(QString(FILENAME_CMAKELISTS) + "\n");
|
||||||
if (error & MissingQmlModules)
|
if (error & MissingQmlModules)
|
||||||
@@ -290,16 +295,21 @@ bool generateCmakes(const FilePath &rootDir)
|
|||||||
{
|
{
|
||||||
moduleNames.clear();
|
moduleNames.clear();
|
||||||
|
|
||||||
FilePath contentDir = rootDir.pathAppended("content");
|
FilePath contentDir = rootDir.pathAppended(DIRNAME_CONTENT);
|
||||||
FilePath importDir = rootDir.pathAppended("imports");
|
FilePath importDir = rootDir.pathAppended(DIRNAME_IMPORT);
|
||||||
|
FilePath assetDir = rootDir.pathAppended(DIRNAME_ASSET);
|
||||||
|
|
||||||
generateModuleCmake(contentDir);
|
generateModuleCmake(contentDir);
|
||||||
generateImportCmake(importDir);
|
generateImportCmake(importDir);
|
||||||
|
generateImportCmake(assetDir);
|
||||||
generateMainCmake(rootDir);
|
generateMainCmake(rootDir);
|
||||||
|
|
||||||
return true;
|
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)
|
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.
|
//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);
|
QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH).arg(appName);
|
||||||
queueCmakeFile(rootDir, cmakeFileContent);
|
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;
|
QString modulesAsPlugins;
|
||||||
for (const QString &moduleName : moduleNames)
|
for (const QString &moduleName : moduleNames)
|
||||||
modulesAsPlugins.append(" " + moduleName + "plugin\n");
|
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);
|
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";
|
void generateImportCmake(const FilePath &dir, const QString &modulePrefix)
|
||||||
const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
|
|
||||||
|
|
||||||
void generateImportCmake(const FilePath &dir)
|
|
||||||
{
|
{
|
||||||
|
if (!dir.exists())
|
||||||
|
return;
|
||||||
|
|
||||||
QString fileContent;
|
QString fileContent;
|
||||||
|
|
||||||
fileContent.append(DO_NOT_EDIT_FILE_COMMENT);
|
fileContent.append(DO_NOT_EDIT_FILE_COMMENT);
|
||||||
|
|
||||||
FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
|
FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
|
||||||
for (FilePath &subDir : subDirs) {
|
for (FilePath &subDir : subDirs) {
|
||||||
|
if (isDirBlacklisted(subDir))
|
||||||
|
continue;
|
||||||
|
if (getDirectoryTreeQmls(subDir).isEmpty() && getDirectoryTreeResources(subDir).isEmpty())
|
||||||
|
continue;
|
||||||
fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
|
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);
|
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_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n";
|
||||||
const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl";
|
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);
|
QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH);
|
||||||
const QStringList qmldirFilesOnly(FILENAME_QMLDIR);
|
|
||||||
|
|
||||||
QString singletonContent;
|
QString singletonContent;
|
||||||
FilePaths qmldirFileList = dir.dirEntries(qmldirFilesOnly, FILES_ONLY);
|
FilePaths qmldirFileList = dir.dirEntries(QStringList(FILENAME_QMLDIR), FILES_ONLY);
|
||||||
if (!qmldirFileList.isEmpty()) {
|
if (!qmldirFileList.isEmpty()) {
|
||||||
QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
|
QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
|
||||||
for (QString &singleton : singletons) {
|
for (QString &singleton : singletons) {
|
||||||
@@ -371,12 +400,14 @@ void generateModuleCmake(const FilePath &dir)
|
|||||||
moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles));
|
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);
|
moduleNames.append(moduleName);
|
||||||
|
|
||||||
QString fileContent;
|
QString fileContent;
|
||||||
fileContent.append(fileTemplate.arg(singletonContent).arg(moduleName).arg(moduleContent));
|
fileContent.append(fileTemplate.arg(singletonContent, moduleName, moduleUri, moduleContent));
|
||||||
queueCmakeFile(dir, fileContent);
|
queueCmakeFile(dir, fileContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,6 +434,22 @@ QStringList getSingletonsFromQmldirFile(const FilePath &filePath)
|
|||||||
return singletons;
|
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)
|
QStringList getDirectoryTreeQmls(const FilePath &dir)
|
||||||
{
|
{
|
||||||
const QStringList qmlFilesOnly("*.qml");
|
const QStringList qmlFilesOnly("*.qml");
|
||||||
@@ -419,6 +466,8 @@ QStringList getDirectoryTreeQmls(const FilePath &dir)
|
|||||||
|
|
||||||
FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
|
FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
|
||||||
for (FilePath &subDir : subDirsList) {
|
for (FilePath &subDir : subDirsList) {
|
||||||
|
if (isDirBlacklisted(subDir))
|
||||||
|
continue;
|
||||||
QStringList subDirQmlFiles = getDirectoryTreeQmls(subDir);
|
QStringList subDirQmlFiles = getDirectoryTreeQmls(subDir);
|
||||||
for (QString &qmlFile : subDirQmlFiles) {
|
for (QString &qmlFile : subDirQmlFiles) {
|
||||||
qmlFileList.append(subDir.fileName().append('/').append(qmlFile));
|
qmlFileList.append(subDir.fileName().append('/').append(qmlFile));
|
||||||
@@ -444,6 +493,8 @@ QStringList getDirectoryTreeResources(const FilePath &dir)
|
|||||||
|
|
||||||
FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
|
FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
|
||||||
for (FilePath &subDir : subDirsList) {
|
for (FilePath &subDir : subDirsList) {
|
||||||
|
if (isDirBlacklisted(subDir))
|
||||||
|
continue;
|
||||||
QStringList subDirResources = getDirectoryTreeResources(subDir);
|
QStringList subDirResources = getDirectoryTreeResources(subDir);
|
||||||
for (QString &resource : subDirResources) {
|
for (QString &resource : subDirResources) {
|
||||||
resourceFileList.append(subDir.fileName().append('/').append(resource));
|
resourceFileList.append(subDir.fileName().append('/').append(resource));
|
||||||
@@ -466,6 +517,11 @@ bool isFileBlacklisted(const QString &fileName)
|
|||||||
!fileName.compare(FILENAME_CMAKELISTS));
|
!fileName.compare(FILENAME_CMAKELISTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isDirBlacklisted(const FilePath &dir)
|
||||||
|
{
|
||||||
|
return (!dir.fileName().compare(DIRNAME_DESIGNER));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace GenerateEntryPoints {
|
namespace GenerateEntryPoints {
|
||||||
|
@@ -54,13 +54,15 @@ QString readTemplate(const QString &templatePath);
|
|||||||
namespace GenerateCmakeLists {
|
namespace GenerateCmakeLists {
|
||||||
bool generateCmakes(const Utils::FilePath &rootDir);
|
bool generateCmakes(const Utils::FilePath &rootDir);
|
||||||
void generateMainCmake(const Utils::FilePath &rootDir);
|
void generateMainCmake(const Utils::FilePath &rootDir);
|
||||||
void generateImportCmake(const Utils::FilePath &dir);
|
void generateImportCmake(const Utils::FilePath &dir, const QString &modulePrefix = QString());
|
||||||
void generateModuleCmake(const Utils::FilePath &dir);
|
void generateModuleCmake(const Utils::FilePath &dir, const QString &moduleUri = QString());
|
||||||
|
Utils::FilePaths getDirectoryQmls(const Utils::FilePath &dir);
|
||||||
QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
|
QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
|
||||||
QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
|
QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
|
||||||
QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
|
QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
|
||||||
void queueCmakeFile(const Utils::FilePath &filePath, const QString &content);
|
void queueCmakeFile(const Utils::FilePath &filePath, const QString &content);
|
||||||
bool isFileBlacklisted(const QString &fileName);
|
bool isFileBlacklisted(const QString &fileName);
|
||||||
|
bool isDirBlacklisted(const Utils::FilePath &dir);
|
||||||
}
|
}
|
||||||
namespace GenerateEntryPoints {
|
namespace GenerateEntryPoints {
|
||||||
bool generateEntryPointFiles(const Utils::FilePath &dir);
|
bool generateEntryPointFiles(const Utils::FilePath &dir);
|
||||||
|
@@ -34,7 +34,9 @@ namespace Constants {
|
|||||||
|
|
||||||
const char DIRNAME_CONTENT[] = "content";
|
const char DIRNAME_CONTENT[] = "content";
|
||||||
const char DIRNAME_IMPORT[] = "imports";
|
const char DIRNAME_IMPORT[] = "imports";
|
||||||
|
const char DIRNAME_ASSET[] = "asset_imports";
|
||||||
const char DIRNAME_CPP[] = "src";
|
const char DIRNAME_CPP[] = "src";
|
||||||
|
const char DIRNAME_DESIGNER[] = "designer";
|
||||||
|
|
||||||
const char FILENAME_CMAKELISTS[] = "CMakeLists.txt";
|
const char FILENAME_CMAKELISTS[] = "CMakeLists.txt";
|
||||||
const char FILENAME_APPMAINQML[] = "App.qml";
|
const char FILENAME_APPMAINQML[] = "App.qml";
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
qt_add_library(%2 STATIC)
|
qt_add_library(%2 STATIC)
|
||||||
qt6_add_qml_module(%2
|
qt6_add_qml_module(%2
|
||||||
URI "%2"
|
URI "%3"
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
%3
|
%4
|
||||||
)
|
)
|
||||||
|
@@ -8,9 +8,8 @@ qt6_add_qml_module(%1
|
|||||||
QML_FILES main.qml
|
QML_FILES main.qml
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(content)
|
%2
|
||||||
add_subdirectory(imports)
|
|
||||||
|
|
||||||
target_link_libraries(%1 PRIVATE
|
target_link_libraries(%1 PRIVATE
|
||||||
%2
|
%3
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user