forked from qt-creator/qt-creator
QmlProjectManager: New project structure support for CMakeGenerator
- Add writer interface in order to support the current and the new project structure in parallel. Using the new one if qdsVersion is >= 4.5 - Separated templates for the new generator from the old one - Add file name validity check - Generate files in the folder src and cmake if they do not exist yet. Only re-generate files in src/autogen. - Add action to enable or disable the cmake-generator - Add function that checks if a resource file is within the project folder but not part of the project Change-Id: I3d75dbee1043ed28e6126cf0b2c83994cb70ed45 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -50,6 +50,9 @@ extend_qtc_plugin(QmlProjectManager
|
|||||||
generatecmakelists.cpp generatecmakelists.h
|
generatecmakelists.cpp generatecmakelists.h
|
||||||
generatecmakelistsconstants.h
|
generatecmakelistsconstants.h
|
||||||
cmakegenerator.cpp cmakegenerator.h
|
cmakegenerator.cpp cmakegenerator.h
|
||||||
|
cmakewriter.cpp cmakewriter.h
|
||||||
|
cmakewriterv0.cpp cmakewriterv0.h
|
||||||
|
cmakewriterv1.cpp cmakewriterv1.h
|
||||||
boilerplate.qrc
|
boilerplate.qrc
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ QmlBuildSystem::QmlBuildSystem(Target *target)
|
|||||||
connect(target->project(), &Project::projectFileIsDirty, this, [this] {
|
connect(target->project(), &Project::projectFileIsDirty, this, [this] {
|
||||||
refresh(RefreshOptions::Project);
|
refresh(RefreshOptions::Project);
|
||||||
m_cmakeGen->initialize(qmlProject());
|
m_cmakeGen->initialize(qmlProject());
|
||||||
|
m_cmakeGen->updateMenuAction();
|
||||||
updateMcuBuildStep(project()->activeTarget(), qtForMCUs());
|
updateMcuBuildStep(project()->activeTarget(), qtForMCUs());
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -501,6 +502,17 @@ void QmlBuildSystem::setPrimaryLanguage(QString language)
|
|||||||
m_projectItem->setPrimaryLanguage(language);
|
m_projectItem->setPrimaryLanguage(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QmlBuildSystem::enableCMakeGeneration() const
|
||||||
|
{
|
||||||
|
return m_projectItem->enableCMakeGeneration();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlBuildSystem::setEnableCMakeGeneration(bool enable)
|
||||||
|
{
|
||||||
|
if (enable != enableCMakeGeneration())
|
||||||
|
m_projectItem->setEnableCMakeGeneration(enable);
|
||||||
|
}
|
||||||
|
|
||||||
void QmlBuildSystem::refreshFiles(const QSet<QString> & /*added*/, const QSet<QString> &removed)
|
void QmlBuildSystem::refreshFiles(const QSet<QString> & /*added*/, const QSet<QString> &removed)
|
||||||
{
|
{
|
||||||
if (m_blockFilesUpdate) {
|
if (m_blockFilesUpdate) {
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ public:
|
|||||||
QString primaryLanguage() const;
|
QString primaryLanguage() const;
|
||||||
void setPrimaryLanguage(QString language);
|
void setPrimaryLanguage(QString language);
|
||||||
|
|
||||||
|
bool enableCMakeGeneration() const;
|
||||||
|
void setEnableCMakeGeneration(bool enable);
|
||||||
|
|
||||||
bool forceFreeType() const;
|
bool forceFreeType() const;
|
||||||
bool widgetApp() const;
|
bool widgetApp() const;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
|
<qresource prefix="/templates">
|
||||||
|
<file alias="cmakeroot_v0">templates/cmakeroot_v0.tpl</file>
|
||||||
|
<file alias="cmakeroot_v1">templates/cmakeroot_v1.tpl</file>
|
||||||
|
<file alias="main_cpp_v0">templates/main_cpp_v0.tpl</file>
|
||||||
|
<file alias="main_cpp_v1">templates/main_cpp_v1.tpl</file>
|
||||||
|
<file alias="cmakemodule_v1">templates/cmakemodule_v1.tpl</file>
|
||||||
|
<file alias="insight">templates/insight.tpl</file>
|
||||||
|
<file alias="qmlcomponents">templates/qmlcomponents.tpl</file>
|
||||||
|
<file alias="environment_h">templates/environment_h.tpl</file>
|
||||||
|
<file alias="import_qml_components_h">templates/import_qml_components_h.tpl</file>
|
||||||
|
</qresource>
|
||||||
|
|
||||||
<qresource prefix="/boilerplatetemplates">
|
<qresource prefix="/boilerplatetemplates">
|
||||||
<file>gencmakeroot.tpl</file>
|
|
||||||
<file>gencmakemodule.tpl</file>
|
|
||||||
<file>gencmakeheadercomponents.tpl</file>
|
|
||||||
<file>qmlprojectmaincpp.tpl</file>
|
<file>qmlprojectmaincpp.tpl</file>
|
||||||
<file>qmlprojectmaincppheader.tpl</file>
|
<file>qmlprojectmaincppheader.tpl</file>
|
||||||
<file>qmlprojectenvheader.tpl</file>
|
<file>qmlprojectenvheader.tpl</file>
|
||||||
|
|||||||
@@ -2,13 +2,22 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "cmakegenerator.h"
|
#include "cmakegenerator.h"
|
||||||
#include "generatecmakelistsconstants.h"
|
|
||||||
|
#include "qmlprojectmanager/qmlproject.h"
|
||||||
|
#include "qmlprojectmanager/qmlprojectconstants.h"
|
||||||
|
#include "qmlprojectmanager/qmlprojectmanagertr.h"
|
||||||
|
|
||||||
#include "projectexplorer/projectmanager.h"
|
#include "projectexplorer/projectmanager.h"
|
||||||
#include "projectexplorer/projectnodes.h"
|
#include "projectexplorer/projectnodes.h"
|
||||||
#include "qmlprojectmanager/qmlproject.h"
|
|
||||||
|
|
||||||
|
#include "utils/filenamevalidatinglineedit.h"
|
||||||
|
|
||||||
|
#include "coreplugin/actionmanager/actionmanager.h"
|
||||||
|
#include "coreplugin/actionmanager/actioncontainer.h"
|
||||||
|
|
||||||
|
#include <QDirIterator>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
@@ -16,30 +25,63 @@ namespace QmlProjectManager {
|
|||||||
|
|
||||||
namespace GenerateCmake {
|
namespace GenerateCmake {
|
||||||
|
|
||||||
const char TEMPLATE_CMAKELISTS_ROOT[] = ":/boilerplatetemplates/gencmakeroot.tpl";
|
void CMakeGenerator::createMenuAction(QObject *parent)
|
||||||
const char TEMPLATE_CMAKELISTS_MODULE[] = ":/boilerplatetemplates/gencmakemodule.tpl";
|
{
|
||||||
|
Core::ActionContainer *fileMenu = Core::ActionManager::actionContainer(
|
||||||
|
Core::Constants::M_FILE);
|
||||||
|
Core::ActionContainer *exportMenu = Core::ActionManager::createMenu(
|
||||||
|
QmlProjectManager::Constants::EXPORT_MENU);
|
||||||
|
|
||||||
const char TEMPLATE_SOURCE_MAIN[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
|
exportMenu->menu()->setTitle(Tr::tr("Export Project"));
|
||||||
const char TEMPLATE_HEADER_IMPORT_COMPS[] = ":/boilerplatetemplates/gencmakeheadercomponents.tpl";
|
exportMenu->appendGroup(QmlProjectManager::Constants::G_EXPORT_GENERATE);
|
||||||
const char TEMPLATE_HEADER_IMPORT_PLUGINS[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl";
|
fileMenu->addMenu(exportMenu, Core::Constants::G_FILE_EXPORT);
|
||||||
const char TEMPLATE_HEADER_ENVIRONMENT[] = ":/boilerplatetemplates/qmlprojectenvheader.tpl";
|
|
||||||
|
|
||||||
const char DO_NOT_EDIT_FILE_COMMENT[]
|
auto action = new QAction(Tr::tr("Enable Automatic CMake Generation"), parent);
|
||||||
= "### This file is automatically generated by Qt Design Studio.\n"
|
action->setEnabled(false);
|
||||||
"### Do not change\n\n";
|
action->setCheckable(true);
|
||||||
|
|
||||||
const char TEMPLATE_BIG_RESOURCES[] = R"(
|
Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.EnableCMakeGeneration");
|
||||||
qt6_add_resources(%1 %2
|
exportMenu->addAction(cmd, QmlProjectManager::Constants::G_EXPORT_GENERATE);
|
||||||
BIG_RESOURCES
|
|
||||||
PREFIX "%3"
|
|
||||||
VERSION 1.0
|
|
||||||
FILES %4
|
|
||||||
))";
|
|
||||||
|
|
||||||
const char TEMPLATE_LINK_LIBRARIES[] = R"(
|
QObject::connect(
|
||||||
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
|
ProjectExplorer::ProjectManager::instance(),
|
||||||
%3
|
&ProjectExplorer::ProjectManager::startupProjectChanged,
|
||||||
))";
|
[action]() {
|
||||||
|
if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem()) {
|
||||||
|
action->setEnabled(!buildSystem->qtForMCUs());
|
||||||
|
action->setChecked(buildSystem->enableCMakeGeneration());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
QObject::connect(action, &QAction::toggled, [](bool checked) {
|
||||||
|
if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem())
|
||||||
|
buildSystem->setEnableCMakeGeneration(checked);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeGenerator::logIssue(const QString &text)
|
||||||
|
{
|
||||||
|
// TODO: Use Issues panel as soon as it is usable in DS.
|
||||||
|
qDebug() << text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeGenerator::updateMenuAction()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(buildSystem(), return);
|
||||||
|
|
||||||
|
Core::Command *cmd = Core::ActionManager::command("QmlProject.EnableCMakeGeneration");
|
||||||
|
if (!cmd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QAction *action = cmd->action();
|
||||||
|
if (!action)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool enabled = buildSystem()->enableCMakeGeneration();
|
||||||
|
if (enabled != action->isChecked())
|
||||||
|
action->setChecked(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
CMakeGenerator::CMakeGenerator(QmlBuildSystem *bs, QObject *parent)
|
CMakeGenerator::CMakeGenerator(QmlBuildSystem *bs, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
@@ -47,6 +89,44 @@ CMakeGenerator::CMakeGenerator(QmlBuildSystem *bs, QObject *parent)
|
|||||||
, m_buildSystem(bs)
|
, m_buildSystem(bs)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
const QmlProject *CMakeGenerator::qmlProject() const
|
||||||
|
{
|
||||||
|
if (m_buildSystem)
|
||||||
|
return m_buildSystem->qmlProject();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QmlBuildSystem *CMakeGenerator::buildSystem() const
|
||||||
|
{
|
||||||
|
return m_buildSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMakeGenerator::findFile(const Utils::FilePath& file) const
|
||||||
|
{
|
||||||
|
return findFile(m_root, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMakeGenerator::isRootNode(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
return node->name == "Main";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMakeGenerator::hasChildModule(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
for (const NodePtr &child : node->subdirs) {
|
||||||
|
if (child->type == Node::Type::Module)
|
||||||
|
return true;
|
||||||
|
if (hasChildModule(child))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CMakeGenerator::projectName() const
|
||||||
|
{
|
||||||
|
return m_projectName;
|
||||||
|
}
|
||||||
|
|
||||||
void CMakeGenerator::setEnabled(bool enabled)
|
void CMakeGenerator::setEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
m_enabled = enabled;
|
m_enabled = enabled;
|
||||||
@@ -57,11 +137,11 @@ void CMakeGenerator::initialize(QmlProject *project)
|
|||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_srcs.clear();
|
|
||||||
m_moduleNames.clear();
|
m_moduleNames.clear();
|
||||||
|
m_writer = CMakeWriter::create(this);
|
||||||
|
|
||||||
m_root = std::make_shared<Node>();
|
m_root = std::make_shared<Node>();
|
||||||
m_root->module = true;
|
m_root->type = Node::Type::App;
|
||||||
m_root->uri = QString("Main");
|
m_root->uri = QString("Main");
|
||||||
m_root->name = QString("Main");
|
m_root->name = QString("Main");
|
||||||
m_root->dir = project->rootProjectDirectory();
|
m_root->dir = project->rootProjectDirectory();
|
||||||
@@ -72,8 +152,10 @@ void CMakeGenerator::initialize(QmlProject *project)
|
|||||||
parseNodeTree(m_root, rootProjectNode);
|
parseNodeTree(m_root, rootProjectNode);
|
||||||
parseSourceTree();
|
parseSourceTree();
|
||||||
|
|
||||||
|
compareWithFileSystem(m_root);
|
||||||
|
|
||||||
createCMakeFiles(m_root);
|
createCMakeFiles(m_root);
|
||||||
createEntryPoints(m_root);
|
createSourceFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeGenerator::update(const QSet<QString> &added, const QSet<QString> &removed)
|
void CMakeGenerator::update(const QSet<QString> &added, const QSet<QString> &removed)
|
||||||
@@ -81,6 +163,8 @@ void CMakeGenerator::update(const QSet<QString> &added, const QSet<QString> &rem
|
|||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
QTC_ASSERT(m_writer, return);
|
||||||
|
|
||||||
std::set<NodePtr> dirtyModules;
|
std::set<NodePtr> dirtyModules;
|
||||||
for (const QString &add : added) {
|
for (const QString &add : added) {
|
||||||
const Utils::FilePath path = Utils::FilePath::fromString(add);
|
const Utils::FilePath path = Utils::FilePath::fromString(add);
|
||||||
@@ -89,7 +173,8 @@ void CMakeGenerator::update(const QSet<QString> &added, const QSet<QString> &rem
|
|||||||
if (auto module = findModuleFor(node))
|
if (auto module = findModuleFor(node))
|
||||||
dirtyModules.insert(module);
|
dirtyModules.insert(module);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "CmakeGen: Failed to find Folder node " << path;
|
QString text("Failed to find Folder for file: %1");
|
||||||
|
logIssue(text.arg(add));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,282 +188,65 @@ void CMakeGenerator::update(const QSet<QString> &added, const QSet<QString> &rem
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto module : dirtyModules)
|
for (auto module : dirtyModules)
|
||||||
createModuleCMakeFile(module);
|
m_writer->writeModuleCMakeFile(module, m_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Utils::FilePath> CMakeGenerator::files(const NodePtr &node,
|
bool CMakeGenerator::isQml(const Utils::FilePath &path) const
|
||||||
const FileGetter &getter) const
|
|
||||||
{
|
{
|
||||||
std::vector<Utils::FilePath> out = getter(node);
|
const QString suffix = path.suffix();
|
||||||
for (const CMakeGenerator::NodePtr &child : node->subdirs) {
|
return suffix == "qml" || suffix == "ui.qml";
|
||||||
if (child->module)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto childFiles = files(child, getter);
|
|
||||||
out.insert(out.end(), childFiles.begin(), childFiles.end());
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Utils::FilePath> CMakeGenerator::qmlFiles(const NodePtr &node) const
|
bool CMakeGenerator::isResource(const Utils::FilePath &path) const
|
||||||
{
|
{
|
||||||
return files(node, [](const NodePtr &n) { return n->files; });
|
static const QStringList suffixes = {
|
||||||
}
|
"json", "mesh", "dae", "qad", "hints", "png", "hdr", "ttf", "jpg",
|
||||||
|
"jpeg", "js", "qsb", "frag", "frag.qsb", "vert", "vert.qsb", "svg",
|
||||||
std::vector<Utils::FilePath> CMakeGenerator::singletons(const NodePtr &node) const
|
"ktx", "bmp", "gif", "webp", "tiff"};
|
||||||
{
|
return suffixes.contains(path.suffix(), Qt::CaseInsensitive);
|
||||||
return files(node, [](const NodePtr &n) { return n->singletons; });
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Utils::FilePath> CMakeGenerator::resources(const NodePtr &node) const
|
|
||||||
{
|
|
||||||
return files(node, [](const NodePtr &n) { return n->resources; });
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Utils::FilePath> CMakeGenerator::sources(const NodePtr &node) const
|
|
||||||
{
|
|
||||||
return files(node, [](const NodePtr &n) { return n->sources; });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeGenerator::createCMakeFiles(const NodePtr &node) const
|
void CMakeGenerator::createCMakeFiles(const NodePtr &node) const
|
||||||
{
|
{
|
||||||
if (isRootNode(node))
|
QTC_ASSERT(m_writer, return);
|
||||||
createMainCMakeFile(node);
|
|
||||||
|
|
||||||
if (node->module || hasChildModule(node))
|
if (isRootNode(node))
|
||||||
createModuleCMakeFile(node);
|
m_writer->writeRootCMakeFile(node);
|
||||||
|
|
||||||
|
if (node->type == Node::Type::Module || (hasChildModule(node)))
|
||||||
|
m_writer->writeModuleCMakeFile(node, m_root);
|
||||||
|
|
||||||
for (const NodePtr &n : node->subdirs)
|
for (const NodePtr &n : node->subdirs)
|
||||||
createCMakeFiles(n);
|
createCMakeFiles(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeGenerator::createMainCMakeFile(const NodePtr &node) const
|
void CMakeGenerator::createSourceFiles() const
|
||||||
{
|
{
|
||||||
const QString appName = m_projectName + "App";
|
QTC_ASSERT(m_writer, return);
|
||||||
|
|
||||||
const QString qtcontrolsConfFile = makeEnvironmentVariable(Constants::ENV_VARIABLE_CONTROLCONF);
|
NodePtr sourceNode = {};
|
||||||
|
for (const NodePtr &child : m_root->subdirs) {
|
||||||
QString fileSection = "";
|
if (child->name == m_writer->sourceDirName())
|
||||||
if (!qtcontrolsConfFile.isEmpty())
|
sourceNode = child;
|
||||||
fileSection = QString(" FILES\n %1").arg(qtcontrolsConfFile);
|
|
||||||
|
|
||||||
const QString fileTemplate = readTemplate(TEMPLATE_CMAKELISTS_ROOT);
|
|
||||||
const QString fileContent = fileTemplate.arg(appName, m_srcs.join(" "), fileSection);
|
|
||||||
|
|
||||||
const Utils::FilePath file = node->dir.pathAppended("CMakeLists.txt");
|
|
||||||
writeFile(file, fileContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMakeGenerator::createModuleCMakeFile(const NodePtr &node) const
|
|
||||||
{
|
|
||||||
Utils::FilePath writeToFile = node->dir.pathAppended("CMakeLists.txt");
|
|
||||||
|
|
||||||
if (!node->module && hasChildModule(node)) {
|
|
||||||
QString content(DO_NOT_EDIT_FILE_COMMENT);
|
|
||||||
content.append(makeSubdirectoriesBlock(node));
|
|
||||||
writeFile(writeToFile, content);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString templatePrefix;
|
if (sourceNode)
|
||||||
templatePrefix.append(makeSubdirectoriesBlock(node));
|
m_writer->writeSourceFiles(sourceNode, m_root);
|
||||||
templatePrefix.append(makeSingletonBlock(node));
|
|
||||||
|
|
||||||
auto [resources, bigResources] = makeResourcesBlocks(node);
|
|
||||||
QString moduleContent;
|
|
||||||
moduleContent.append(makeQmlFilesBlock(node));
|
|
||||||
moduleContent.append(resources);
|
|
||||||
|
|
||||||
QString templatePostfix;
|
|
||||||
templatePostfix.append(bigResources);
|
|
||||||
|
|
||||||
if (isRootNode(node)) {
|
|
||||||
writeToFile = node->dir.pathAppended("qmlModules");
|
|
||||||
QString pluginNames;
|
|
||||||
for (const QString &moduleName : m_moduleNames)
|
|
||||||
pluginNames.append(" " + moduleName + "plugin\n");
|
|
||||||
|
|
||||||
templatePostfix += QString::fromUtf8(TEMPLATE_LINK_LIBRARIES, -1).arg(pluginNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString fileTemplate = readTemplate(TEMPLATE_CMAKELISTS_MODULE);
|
|
||||||
const QString fileContent
|
|
||||||
= fileTemplate.arg(node->name, node->uri, templatePrefix, moduleContent, templatePostfix);
|
|
||||||
|
|
||||||
writeFile(writeToFile, fileContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMakeGenerator::createEntryPoints(const NodePtr &node) const
|
|
||||||
{
|
|
||||||
createMainCppFile(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMakeGenerator::createMainCppFile(const NodePtr &node) const
|
|
||||||
{
|
|
||||||
const Utils::FilePath srcDir = node->dir.pathAppended(Constants::DIRNAME_CPP);
|
|
||||||
if (!srcDir.exists()) {
|
|
||||||
srcDir.createDir();
|
|
||||||
|
|
||||||
const Utils::FilePath componentsHeaderPath = srcDir.pathAppended(
|
|
||||||
"import_qml_components_plugins.h");
|
|
||||||
|
|
||||||
const QString componentsHeaderContent = readTemplate(TEMPLATE_HEADER_IMPORT_COMPS);
|
|
||||||
writeFile(componentsHeaderPath, componentsHeaderContent);
|
|
||||||
|
|
||||||
const Utils::FilePath cppFilePath = srcDir.pathAppended("main.cpp");
|
|
||||||
const QString cppContent = readTemplate(TEMPLATE_SOURCE_MAIN);
|
|
||||||
writeFile(cppFilePath, cppContent);
|
|
||||||
|
|
||||||
const Utils::FilePath envHeaderPath = srcDir.pathAppended("app_environment.h");
|
|
||||||
if (m_buildSystem) {
|
|
||||||
QString environment;
|
|
||||||
const QString qtcontrolsConfFile = makeEnvironmentVariable(
|
|
||||||
Constants::ENV_VARIABLE_CONTROLCONF);
|
|
||||||
for (Utils::EnvironmentItem &envItem : m_buildSystem->environment()) {
|
|
||||||
QString key = envItem.name;
|
|
||||||
QString value = envItem.value;
|
|
||||||
if (value == qtcontrolsConfFile)
|
|
||||||
value.prepend(":/");
|
|
||||||
environment.append(QString(" qputenv(\"%1\", \"%2\");\n").arg(key).arg(value));
|
|
||||||
}
|
|
||||||
const QString envHeaderContent
|
|
||||||
= readTemplate(TEMPLATE_HEADER_ENVIRONMENT).arg(environment);
|
|
||||||
writeFile(envHeaderPath, envHeaderContent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString moduleContent;
|
|
||||||
for (const QString &module : m_moduleNames)
|
|
||||||
moduleContent.append(QString("Q_IMPORT_QML_PLUGIN(%1)\n").arg(module + "Plugin"));
|
|
||||||
|
|
||||||
const QString headerContent = readTemplate(TEMPLATE_HEADER_IMPORT_PLUGINS).arg(moduleContent);
|
|
||||||
const Utils::FilePath headerFilePath = srcDir.pathAppended("import_qml_plugins.h");
|
|
||||||
writeFile(headerFilePath, headerContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMakeGenerator::writeFile(const Utils::FilePath &path, const QString &content) const
|
|
||||||
{
|
|
||||||
QFile fileHandle(path.toString());
|
|
||||||
fileHandle.open(QIODevice::WriteOnly);
|
|
||||||
QTextStream stream(&fileHandle);
|
|
||||||
stream << content;
|
|
||||||
fileHandle.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString CMakeGenerator::makeRelative(const NodePtr &node, const Utils::FilePath &path) const
|
|
||||||
{
|
|
||||||
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(),
|
|
||||||
envItems.end(),
|
|
||||||
[key](Utils::EnvironmentItem &item) { return item.name == key; });
|
|
||||||
if (confEnv != envItems.end())
|
|
||||||
value = confEnv->value;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
templatefile.open(QIODevice::ReadOnly);
|
|
||||||
QTextStream stream(&templatefile);
|
|
||||||
QString content = stream.readAll();
|
|
||||||
templatefile.close();
|
|
||||||
return content;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeGenerator::readQmlDir(const Utils::FilePath &filePath, NodePtr &node) const
|
void CMakeGenerator::readQmlDir(const Utils::FilePath &filePath, NodePtr &node) const
|
||||||
{
|
{
|
||||||
node->module = true;
|
node->type = Node::Type::Module;
|
||||||
|
|
||||||
QFile f(filePath.toString());
|
QFile f(filePath.toString());
|
||||||
f.open(QIODevice::ReadOnly);
|
f.open(QIODevice::ReadOnly);
|
||||||
QTextStream stream(&f);
|
QTextStream stream(&f);
|
||||||
|
|
||||||
Utils::FilePath dir = filePath.parentDir();
|
Utils::FilePath dir = filePath.parentDir();
|
||||||
|
static const QRegularExpression whitespaceRegex("\\s+");
|
||||||
while (!stream.atEnd()) {
|
while (!stream.atEnd()) {
|
||||||
const QString line = stream.readLine();
|
const QString line = stream.readLine();
|
||||||
const QStringList tokenizedLine = line.split(QRegularExpression("\\s+"));
|
const QStringList tokenizedLine = line.split(whitespaceRegex);
|
||||||
const QString maybeFileName = tokenizedLine.last();
|
const QString maybeFileName = tokenizedLine.last();
|
||||||
if (tokenizedLine.first().compare("module", Qt::CaseInsensitive) == 0) {
|
if (tokenizedLine.first().compare("module", Qt::CaseInsensitive) == 0) {
|
||||||
node->uri = tokenizedLine.last();
|
node->uri = tokenizedLine.last();
|
||||||
@@ -392,11 +260,11 @@ void CMakeGenerator::readQmlDir(const Utils::FilePath &filePath, NodePtr &node)
|
|||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
CMakeGenerator::NodePtr CMakeGenerator::findModuleFor(const NodePtr &node) const
|
NodePtr CMakeGenerator::findModuleFor(const NodePtr &node) const
|
||||||
{
|
{
|
||||||
NodePtr current = node;
|
NodePtr current = node;
|
||||||
while (current->parent) {
|
while (current->parent) {
|
||||||
if (current->module)
|
if (current->type == Node::Type::Module)
|
||||||
return current;
|
return current;
|
||||||
|
|
||||||
current = current->parent;
|
current = current->parent;
|
||||||
@@ -404,7 +272,7 @@ CMakeGenerator::NodePtr CMakeGenerator::findModuleFor(const NodePtr &node) const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMakeGenerator::NodePtr CMakeGenerator::findNode(NodePtr &node, const Utils::FilePath &path) const
|
NodePtr CMakeGenerator::findNode(NodePtr &node, const Utils::FilePath &path) const
|
||||||
{
|
{
|
||||||
const Utils::FilePath parentDir = path.parentDir();
|
const Utils::FilePath parentDir = path.parentDir();
|
||||||
for (NodePtr &child : node->subdirs) {
|
for (NodePtr &child : node->subdirs) {
|
||||||
@@ -416,8 +284,7 @@ CMakeGenerator::NodePtr CMakeGenerator::findNode(NodePtr &node, const Utils::Fil
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMakeGenerator::NodePtr CMakeGenerator::findOrCreateNode(NodePtr &node,
|
NodePtr CMakeGenerator::findOrCreateNode(NodePtr &node, const Utils::FilePath &path) const
|
||||||
const Utils::FilePath &path) const
|
|
||||||
{
|
{
|
||||||
if (auto found = findNode(node, path))
|
if (auto found = findNode(node, path))
|
||||||
return found;
|
return found;
|
||||||
@@ -442,14 +309,46 @@ CMakeGenerator::NodePtr CMakeGenerator::findOrCreateNode(NodePtr &node,
|
|||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool findFileWithGetter(const Utils::FilePath &file, const NodePtr &node, const FileGetter &getter)
|
||||||
|
{
|
||||||
|
for (const auto &f : getter(node)) {
|
||||||
|
if (f == file)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (const auto &subdir : node->subdirs) {
|
||||||
|
if (findFileWithGetter(file, subdir, getter))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMakeGenerator::findFile(const NodePtr &node, const Utils::FilePath &file) const
|
||||||
|
{
|
||||||
|
if (isResource(file)) {
|
||||||
|
return findFileWithGetter(file, node, [](const NodePtr &n) { return n->resources; });
|
||||||
|
} else if (isQml(file)) {
|
||||||
|
if (findFileWithGetter(file, node, [](const NodePtr &n) { return n->files; }))
|
||||||
|
return true;
|
||||||
|
else if (findFileWithGetter(file, node, [](const NodePtr &n) { return n->singletons; }))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void CMakeGenerator::insertFile(NodePtr &node, const Utils::FilePath &path) const
|
void CMakeGenerator::insertFile(NodePtr &node, const Utils::FilePath &path) const
|
||||||
{
|
{
|
||||||
|
QString error;
|
||||||
|
if (!Utils::FileNameValidatingLineEdit::validateFileName(path.fileName(), false, &error)) {
|
||||||
|
QString text(path.path() + error);
|
||||||
|
logIssue(error);
|
||||||
|
}
|
||||||
|
|
||||||
if (path.fileName() == "qmldir") {
|
if (path.fileName() == "qmldir") {
|
||||||
readQmlDir(path, node);
|
readQmlDir(path, node);
|
||||||
} else if (path.suffix() == "qml" || path.suffix() == "ui.qml") {
|
|
||||||
node->files.push_back(path);
|
|
||||||
} else if (path.suffix() == "cpp") {
|
} else if (path.suffix() == "cpp") {
|
||||||
node->sources.push_back(path);
|
node->sources.push_back(path);
|
||||||
|
} else if (isQml(path)) {
|
||||||
|
node->files.push_back(path);
|
||||||
} else if (isResource(path)) {
|
} else if (isResource(path)) {
|
||||||
node->resources.push_back(path);
|
node->resources.push_back(path);
|
||||||
}
|
}
|
||||||
@@ -458,12 +357,12 @@ void CMakeGenerator::insertFile(NodePtr &node, const Utils::FilePath &path) cons
|
|||||||
void CMakeGenerator::removeFile(NodePtr &node, const Utils::FilePath &path) const
|
void CMakeGenerator::removeFile(NodePtr &node, const Utils::FilePath &path) const
|
||||||
{
|
{
|
||||||
if (path.fileName() == "qmldir") {
|
if (path.fileName() == "qmldir") {
|
||||||
node->module = false;
|
node->type = Node::Type::Folder;
|
||||||
node->singletons.clear();
|
node->singletons.clear();
|
||||||
node->uri = "";
|
node->uri = "";
|
||||||
node->name = path.parentDir().fileName();
|
node->name = path.parentDir().fileName();
|
||||||
|
|
||||||
} else if (path.suffix() == "qml") {
|
} else if (isQml(path)) {
|
||||||
auto iter = std::find(node->files.begin(), node->files.end(), path);
|
auto iter = std::find(node->files.begin(), node->files.end(), path);
|
||||||
if (iter != node->files.end())
|
if (iter != node->files.end())
|
||||||
node->files.erase(iter);
|
node->files.erase(iter);
|
||||||
@@ -474,33 +373,9 @@ 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) {
|
|
||||||
if (child->module)
|
|
||||||
return true;
|
|
||||||
if (hasChildModule(child))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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"};
|
|
||||||
return suffixes.contains(path.suffix());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMakeGenerator::printModules(const NodePtr &node) const
|
void CMakeGenerator::printModules(const NodePtr &node) const
|
||||||
{
|
{
|
||||||
if (node->module)
|
if (node->type == Node::Type::Module)
|
||||||
qDebug() << "Module: " << node->name;
|
qDebug() << "Module: " << node->name;
|
||||||
|
|
||||||
for (const auto &child : node->subdirs)
|
for (const auto &child : node->subdirs)
|
||||||
@@ -516,7 +391,27 @@ void CMakeGenerator::printNodeTree(const NodePtr &generatorNode, size_t indent)
|
|||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QString typeString;
|
||||||
|
switch (generatorNode->type)
|
||||||
|
{
|
||||||
|
case Node::Type::App:
|
||||||
|
typeString = "Node::Type::App";
|
||||||
|
break;
|
||||||
|
case Node::Type::Folder:
|
||||||
|
typeString = "Node::Type::Folder";
|
||||||
|
break;
|
||||||
|
case Node::Type::Module:
|
||||||
|
typeString = "Node::Type::Module";
|
||||||
|
break;
|
||||||
|
case Node::Type::Library:
|
||||||
|
typeString = "Node::Type::Library";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
typeString = "Node::Type::Undefined";
|
||||||
|
}
|
||||||
|
|
||||||
qDebug() << addIndent(indent) << "GeneratorNode: " << generatorNode->name;
|
qDebug() << addIndent(indent) << "GeneratorNode: " << generatorNode->name;
|
||||||
|
qDebug() << addIndent(indent) << "type: " << typeString;
|
||||||
qDebug() << addIndent(indent) << "directory: " << generatorNode->dir;
|
qDebug() << addIndent(indent) << "directory: " << generatorNode->dir;
|
||||||
qDebug() << addIndent(indent) << "files: " << generatorNode->files;
|
qDebug() << addIndent(indent) << "files: " << generatorNode->files;
|
||||||
qDebug() << addIndent(indent) << "singletons: " << generatorNode->singletons;
|
qDebug() << addIndent(indent) << "singletons: " << generatorNode->singletons;
|
||||||
@@ -532,7 +427,7 @@ void CMakeGenerator::parseNodeTree(NodePtr &generatorNode,
|
|||||||
{
|
{
|
||||||
for (const auto *childNode : folderNode->nodes()) {
|
for (const auto *childNode : folderNode->nodes()) {
|
||||||
if (const auto *subFolderNode = childNode->asFolderNode()) {
|
if (const auto *subFolderNode = childNode->asFolderNode()) {
|
||||||
CMakeGenerator::NodePtr childGeneratorNode = std::make_shared<Node>();
|
NodePtr childGeneratorNode = std::make_shared<Node>();
|
||||||
childGeneratorNode->parent = generatorNode;
|
childGeneratorNode->parent = generatorNode;
|
||||||
childGeneratorNode->dir = subFolderNode->filePath();
|
childGeneratorNode->dir = subFolderNode->filePath();
|
||||||
childGeneratorNode->name = subFolderNode->displayName();
|
childGeneratorNode->name = subFolderNode->displayName();
|
||||||
@@ -544,25 +439,55 @@ void CMakeGenerator::parseNodeTree(NodePtr &generatorNode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (generatorNode->name == "content")
|
if (m_writer)
|
||||||
generatorNode->module = true;
|
m_writer->transformNode(generatorNode);
|
||||||
|
|
||||||
if (generatorNode->module)
|
if (generatorNode->type == Node::Type::Module)
|
||||||
m_moduleNames.push_back(generatorNode->name);
|
m_moduleNames.push_back(generatorNode->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeGenerator::parseSourceTree()
|
void CMakeGenerator::parseSourceTree()
|
||||||
{
|
{
|
||||||
m_srcs.clear();
|
QTC_ASSERT(m_writer, return);
|
||||||
const QString srcDir = m_root->dir.pathAppended(Constants::DIRNAME_CPP).path();
|
|
||||||
QDirIterator it(srcDir, QStringList({"*.cpp"}), QDir::Files, QDirIterator::Subdirectories);
|
const Utils::FilePath srcDir = m_root->dir.pathAppended(m_writer->sourceDirName());
|
||||||
|
QDirIterator it(srcDir.path(), {"*.cpp"}, QDir::Files, QDirIterator::Subdirectories);
|
||||||
|
|
||||||
|
NodePtr srcNode = std::make_shared<Node>();
|
||||||
|
srcNode->parent = m_root;
|
||||||
|
srcNode->type = Node::Type::App;
|
||||||
|
srcNode->dir = srcDir;
|
||||||
|
srcNode->uri = srcDir.baseName();
|
||||||
|
srcNode->name = srcNode->uri;
|
||||||
|
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
QString relative = Utils::FilePath::calcRelativePath(it.next(), m_root->dir.path());
|
auto next = it.next();
|
||||||
m_srcs.push_back(relative);
|
srcNode->sources.push_back(Utils::FilePath::fromString(next));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_srcs.empty())
|
if (srcNode->sources.empty())
|
||||||
m_srcs.push_back("src/main.cpp");
|
srcNode->sources.push_back(srcDir.pathAppended("main.cpp"));
|
||||||
|
|
||||||
|
if (m_writer)
|
||||||
|
m_writer->transformNode(srcNode);
|
||||||
|
|
||||||
|
m_root->subdirs.push_back(srcNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeGenerator::compareWithFileSystem(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
std::vector<Utils::FilePath> files;
|
||||||
|
QDirIterator iter(node->dir.path(), QDir::Files, QDirIterator::Subdirectories);
|
||||||
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
auto next = Utils::FilePath::fromString(iter.next());
|
||||||
|
if (isResource(next) && !findFile(next))
|
||||||
|
files.push_back(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString text("File %1 is not part of the project");
|
||||||
|
for (const auto& file : files)
|
||||||
|
logIssue(text.arg(file.path()));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace GenerateCmake
|
} // namespace GenerateCmake
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "cmakewriter.h"
|
||||||
|
|
||||||
#include "utils/filepath.h"
|
#include "utils/filepath.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
@@ -22,80 +24,55 @@ class CMakeGenerator : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static void createMenuAction(QObject *parent);
|
||||||
|
static void logIssue(const QString &text);
|
||||||
|
|
||||||
CMakeGenerator(QmlBuildSystem *bs, QObject *parent = nullptr);
|
CMakeGenerator(QmlBuildSystem *bs, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QString projectName() const;
|
||||||
|
|
||||||
|
const QmlProject *qmlProject() const;
|
||||||
|
const QmlBuildSystem *buildSystem() const;
|
||||||
|
|
||||||
|
bool findFile(const Utils::FilePath &file) const;
|
||||||
|
bool isRootNode(const NodePtr &node) const;
|
||||||
|
bool hasChildModule(const NodePtr &node) const;
|
||||||
|
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
void initialize(QmlProject *project);
|
void initialize(QmlProject *project);
|
||||||
|
|
||||||
void update(const QSet<QString> &added, const QSet<QString> &removed);
|
void update(const QSet<QString> &added, const QSet<QString> &removed);
|
||||||
|
void updateMenuAction();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Node
|
bool isQml(const Utils::FilePath &path) const;
|
||||||
{
|
bool isResource(const Utils::FilePath &path) const;
|
||||||
std::shared_ptr<Node> parent = nullptr;
|
|
||||||
bool module = false;
|
|
||||||
|
|
||||||
QString uri;
|
|
||||||
QString name;
|
|
||||||
Utils::FilePath dir;
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Node>> subdirs;
|
|
||||||
std::vector<Utils::FilePath> files;
|
|
||||||
std::vector<Utils::FilePath> singletons;
|
|
||||||
std::vector<Utils::FilePath> resources;
|
|
||||||
std::vector<Utils::FilePath> sources;
|
|
||||||
};
|
|
||||||
|
|
||||||
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 createCMakeFiles(const NodePtr &node) const;
|
||||||
void createMainCMakeFile(const NodePtr &node) const;
|
void createSourceFiles() const;
|
||||||
void createModuleCMakeFile(const NodePtr &node) const;
|
|
||||||
|
|
||||||
void createEntryPoints(const NodePtr &node) const;
|
|
||||||
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;
|
void readQmlDir(const Utils::FilePath &filePath, NodePtr &node) const;
|
||||||
|
|
||||||
NodePtr findModuleFor(const NodePtr &node) const;
|
NodePtr findModuleFor(const NodePtr &node) const;
|
||||||
NodePtr findNode(NodePtr &node, const Utils::FilePath &path) const;
|
NodePtr findNode(NodePtr &node, const Utils::FilePath &path) const;
|
||||||
NodePtr findOrCreateNode(NodePtr &node, const Utils::FilePath &path) const;
|
NodePtr findOrCreateNode(NodePtr &node, const Utils::FilePath &path) const;
|
||||||
|
|
||||||
|
bool findFile(const NodePtr &node, const Utils::FilePath &file) const;
|
||||||
void insertFile(NodePtr &node, const Utils::FilePath &path) const;
|
void insertFile(NodePtr &node, const Utils::FilePath &path) const;
|
||||||
void removeFile(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 printModules(const NodePtr &generatorNode) const;
|
||||||
void printNodeTree(const NodePtr &generatorNode, size_t indent = 0) const;
|
void printNodeTree(const NodePtr &generatorNode, size_t indent = 0) const;
|
||||||
|
|
||||||
void parseNodeTree(NodePtr &generatorNode, const ProjectExplorer::FolderNode *folderNode);
|
void parseNodeTree(NodePtr &generatorNode, const ProjectExplorer::FolderNode *folderNode);
|
||||||
void parseSourceTree();
|
void parseSourceTree();
|
||||||
|
|
||||||
|
void compareWithFileSystem(const NodePtr &node) const;
|
||||||
|
|
||||||
bool m_enabled = false;
|
bool m_enabled = false;
|
||||||
|
CMakeWriter::Ptr m_writer = {};
|
||||||
|
|
||||||
QString m_projectName = {};
|
QString m_projectName = {};
|
||||||
NodePtr m_root = {};
|
NodePtr m_root = {};
|
||||||
QStringList m_srcs = {};
|
QStringList m_moduleNames = {};
|
||||||
std::vector<QString> m_moduleNames = {};
|
|
||||||
QmlBuildSystem *m_buildSystem = nullptr;
|
QmlBuildSystem *m_buildSystem = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
259
src/plugins/qmlprojectmanager/cmakegen/cmakewriter.cpp
Normal file
259
src/plugins/qmlprojectmanager/cmakegen/cmakewriter.cpp
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
#include "cmakewriter.h"
|
||||||
|
#include "cmakegenerator.h"
|
||||||
|
#include "cmakewriterv0.h"
|
||||||
|
#include "cmakewriterv1.h"
|
||||||
|
#include "generatecmakelistsconstants.h"
|
||||||
|
|
||||||
|
#include "qmlprojectmanager/qmlproject.h"
|
||||||
|
#include "qmlprojectmanager/buildsystem/qmlbuildsystem.h"
|
||||||
|
|
||||||
|
#include "utils/namevalueitem.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
namespace QmlProjectManager {
|
||||||
|
|
||||||
|
namespace GenerateCmake {
|
||||||
|
|
||||||
|
const char TEMPLATE_BIG_RESOURCES[] = R"(
|
||||||
|
qt6_add_resources(%1 %2
|
||||||
|
BIG_RESOURCES
|
||||||
|
PREFIX "%3"
|
||||||
|
VERSION 1.0
|
||||||
|
FILES %4
|
||||||
|
))";
|
||||||
|
|
||||||
|
CMakeWriter::Ptr CMakeWriter::create(CMakeGenerator *parent)
|
||||||
|
{
|
||||||
|
const QmlProject *project = parent->qmlProject();
|
||||||
|
QTC_ASSERT(project, return {});
|
||||||
|
|
||||||
|
const QmlBuildSystem *buildSystem = parent->buildSystem();
|
||||||
|
QTC_ASSERT(buildSystem, return {});
|
||||||
|
|
||||||
|
const QString versionString = buildSystem->versionDesignStudio();
|
||||||
|
bool ok = false;
|
||||||
|
if (float version = versionString.toFloat(&ok); ok && version > 4.4)
|
||||||
|
return std::make_unique<CMakeWriterV1>(parent);
|
||||||
|
|
||||||
|
return std::make_unique<CMakeWriterV0>(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
CMakeWriter::CMakeWriter(CMakeGenerator *parent)
|
||||||
|
: m_parent(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
const CMakeGenerator *CMakeWriter::parent() const
|
||||||
|
{
|
||||||
|
return m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMakeWriter::isPlugin(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
if (node->type == Node::Type::Module)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CMakeWriter::sourceDirName() const
|
||||||
|
{
|
||||||
|
return Constants::DIRNAME_CPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeWriter::transformNode(NodePtr &) const
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::vector<Utils::FilePath> CMakeWriter::files(const NodePtr &node, const FileGetter &getter) const
|
||||||
|
{
|
||||||
|
std::vector<Utils::FilePath> out = getter(node);
|
||||||
|
for (const NodePtr &child : node->subdirs) {
|
||||||
|
if (child->type == Node::Type::Module)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto childFiles = files(child, getter);
|
||||||
|
out.insert(out.end(), childFiles.begin(), childFiles.end());
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Utils::FilePath> CMakeWriter::qmlFiles(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
return files(node, [](const NodePtr &n) { return n->files; });
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Utils::FilePath> CMakeWriter::singletons(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
return files(node, [](const NodePtr &n) { return n->singletons; });
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Utils::FilePath> CMakeWriter::resources(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
return files(node, [](const NodePtr &n) { return n->resources; });
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Utils::FilePath> CMakeWriter::sources(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
return files(node, [](const NodePtr &n) { return n->sources; });
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<QString> CMakeWriter::plugins(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return {});
|
||||||
|
std::vector<QString> out;
|
||||||
|
collectPlugins(node, out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CMakeWriter::getEnvironmentVariable(const QString &key) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return {});
|
||||||
|
|
||||||
|
QString value;
|
||||||
|
if (m_parent->buildSystem()) {
|
||||||
|
auto envItems = m_parent->buildSystem()->environment();
|
||||||
|
auto confEnv = std::find_if(
|
||||||
|
envItems.begin(), envItems.end(), [key](const Utils::EnvironmentItem &item) {
|
||||||
|
return item.name == key;
|
||||||
|
});
|
||||||
|
if (confEnv != envItems.end())
|
||||||
|
value = confEnv->value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CMakeWriter::makeRelative(const NodePtr &node, const Utils::FilePath &path) const
|
||||||
|
{
|
||||||
|
const QString dir = node->dir.toString();
|
||||||
|
return "\"" + Utils::FilePath::calcRelativePath(path.toString(), dir) + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CMakeWriter::makeQmlFilesBlock(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return {});
|
||||||
|
|
||||||
|
QString qmlFileContent;
|
||||||
|
for (const Utils::FilePath &path : qmlFiles(node))
|
||||||
|
qmlFileContent.append(QString("\t\t%1\n").arg(makeRelative(node, path)));
|
||||||
|
|
||||||
|
QString str;
|
||||||
|
if (!qmlFileContent.isEmpty())
|
||||||
|
str.append(QString("\tQML_FILES\n%1").arg(qmlFileContent));
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CMakeWriter::makeSingletonBlock(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
QString str;
|
||||||
|
const QString setProperties("set_source_files_properties(%1\n\tPROPERTIES\n\t\t%2 %3\n)\n\n");
|
||||||
|
for (const Utils::FilePath &path : node->singletons)
|
||||||
|
str.append(setProperties.arg(path.fileName()).arg("QT_QML_SINGLETON_TYPE").arg("true"));
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CMakeWriter::makeSubdirectoriesBlock(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return {});
|
||||||
|
|
||||||
|
QString str;
|
||||||
|
for (const NodePtr &n : node->subdirs) {
|
||||||
|
if (n->type == Node::Type::Module || n->type == Node::Type::Library
|
||||||
|
|| n->type == Node::Type::App || parent()->hasChildModule(n))
|
||||||
|
str.append(QString("add_subdirectory(%1)\n").arg(n->dir.fileName()));
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CMakeWriter::makeSetEnvironmentFn() const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return {});
|
||||||
|
QTC_ASSERT(parent()->buildSystem(), return {});
|
||||||
|
|
||||||
|
const QmlBuildSystem *buildSystem = parent()->buildSystem();
|
||||||
|
const QString configFile = getEnvironmentVariable(Constants::ENV_VARIABLE_CONTROLCONF);
|
||||||
|
|
||||||
|
QString out("inline void set_qt_environment() {\n");
|
||||||
|
for (Utils::EnvironmentItem &envItem : buildSystem->environment()) {
|
||||||
|
QString key = envItem.name;
|
||||||
|
QString value = envItem.value;
|
||||||
|
if (value == configFile)
|
||||||
|
value.prepend(":/");
|
||||||
|
out.append(QString("\tqputenv(\"%1\", \"%2\");\n").arg(key).arg(value));
|
||||||
|
}
|
||||||
|
out.append("}");
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<QString, QString> CMakeWriter::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("\t\t%1\n").arg(makeRelative(node, path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resourceFiles.isEmpty())
|
||||||
|
resourcesOut.append(QString("\tRESOURCES\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 CMakeWriter::readTemplate(const QString &templatePath) const
|
||||||
|
{
|
||||||
|
QFile templatefile(templatePath);
|
||||||
|
templatefile.open(QIODevice::ReadOnly);
|
||||||
|
QTextStream stream(&templatefile);
|
||||||
|
QString content = stream.readAll();
|
||||||
|
templatefile.close();
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeWriter::writeFile(const Utils::FilePath &path, const QString &content) const
|
||||||
|
{
|
||||||
|
QFile fileHandle(path.toString());
|
||||||
|
if (fileHandle.open(QIODevice::WriteOnly)) {
|
||||||
|
QTextStream stream(&fileHandle);
|
||||||
|
stream << content;
|
||||||
|
} else {
|
||||||
|
QString text("Failed to write file: %1");
|
||||||
|
CMakeGenerator::logIssue(text.arg(path.path()));
|
||||||
|
}
|
||||||
|
fileHandle.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeWriter::collectPlugins(const NodePtr &node, std::vector<QString> &out) const
|
||||||
|
{
|
||||||
|
if (isPlugin(node))
|
||||||
|
out.push_back(node->name);
|
||||||
|
for (const auto &child : node->subdirs)
|
||||||
|
collectPlugins(child, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace GenerateCmake.
|
||||||
|
|
||||||
|
} // End namespace QmlProjectManager.
|
||||||
98
src/plugins/qmlprojectmanager/cmakegen/cmakewriter.h
Normal file
98
src/plugins/qmlprojectmanager/cmakegen/cmakewriter.h
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "utils/filepath.h"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace QmlProjectManager {
|
||||||
|
|
||||||
|
class QmlProject;
|
||||||
|
class QmlBuildSystem;
|
||||||
|
|
||||||
|
namespace GenerateCmake {
|
||||||
|
|
||||||
|
struct Node
|
||||||
|
{
|
||||||
|
enum class Type {
|
||||||
|
App,
|
||||||
|
Module,
|
||||||
|
Library,
|
||||||
|
Folder,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<Node> parent = nullptr;
|
||||||
|
Type type = Type::Folder;
|
||||||
|
|
||||||
|
QString uri;
|
||||||
|
QString name;
|
||||||
|
Utils::FilePath dir;
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<Node>> subdirs;
|
||||||
|
std::vector<Utils::FilePath> files;
|
||||||
|
std::vector<Utils::FilePath> singletons;
|
||||||
|
std::vector<Utils::FilePath> resources;
|
||||||
|
std::vector<Utils::FilePath> sources;
|
||||||
|
};
|
||||||
|
|
||||||
|
using NodePtr = std::shared_ptr<Node>;
|
||||||
|
using FileGetter = std::function<std::vector<Utils::FilePath>(const NodePtr &)>;
|
||||||
|
|
||||||
|
class CMakeGenerator;
|
||||||
|
|
||||||
|
const char DO_NOT_EDIT_FILE[] =
|
||||||
|
"### This file is automatically generated by Qt Design Studio.\n"
|
||||||
|
"### Do not change\n\n";
|
||||||
|
|
||||||
|
const char TEMPLATE_LINK_LIBRARIES[] =
|
||||||
|
"target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE\n"
|
||||||
|
"%3"
|
||||||
|
")";
|
||||||
|
|
||||||
|
class CMakeWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Ptr = std::shared_ptr<CMakeWriter>;
|
||||||
|
|
||||||
|
static Ptr create(CMakeGenerator *parent);
|
||||||
|
|
||||||
|
CMakeWriter(CMakeGenerator *parent);
|
||||||
|
const CMakeGenerator *parent() const;
|
||||||
|
|
||||||
|
virtual bool isPlugin(const NodePtr &node) const;
|
||||||
|
virtual QString sourceDirName() const;
|
||||||
|
virtual void transformNode(NodePtr &) const;
|
||||||
|
|
||||||
|
virtual void writeRootCMakeFile(const NodePtr &node) const = 0;
|
||||||
|
virtual void writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const = 0;
|
||||||
|
virtual void writeSourceFiles(const NodePtr &node, const NodePtr &root) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
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;
|
||||||
|
std::vector<QString> plugins(const NodePtr &node) const;
|
||||||
|
|
||||||
|
QString getEnvironmentVariable(const QString &key) const;
|
||||||
|
|
||||||
|
QString makeRelative(const NodePtr &node, const Utils::FilePath &path) const;
|
||||||
|
QString makeQmlFilesBlock(const NodePtr &node) const;
|
||||||
|
QString makeSingletonBlock(const NodePtr &node) const;
|
||||||
|
QString makeSubdirectoriesBlock(const NodePtr &node) const;
|
||||||
|
QString makeSetEnvironmentFn() const;
|
||||||
|
std::tuple<QString, QString> makeResourcesBlocks(const NodePtr &node) const;
|
||||||
|
|
||||||
|
QString readTemplate(const QString &templatePath) const;
|
||||||
|
void writeFile(const Utils::FilePath &path, const QString &content) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void collectPlugins(const NodePtr &node, std::vector<QString> &out) const;
|
||||||
|
const CMakeGenerator *m_parent = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace GenerateCmake.
|
||||||
|
|
||||||
|
} // End namespace QmlProjectManager.
|
||||||
178
src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.cpp
Normal file
178
src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.cpp
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
#include "cmakewriterv0.h"
|
||||||
|
#include "cmakegenerator.h"
|
||||||
|
#include "generatecmakelistsconstants.h"
|
||||||
|
|
||||||
|
namespace QmlProjectManager {
|
||||||
|
|
||||||
|
namespace GenerateCmake {
|
||||||
|
|
||||||
|
const char TEMPLATE_ADD_QML_MODULE[] = R"(
|
||||||
|
qt6_add_qml_module(%1
|
||||||
|
URI "%2"
|
||||||
|
VERSION 1.0
|
||||||
|
RESOURCE_PREFIX "/qt/qml"
|
||||||
|
%3))";
|
||||||
|
|
||||||
|
CMakeWriterV0::CMakeWriterV0(CMakeGenerator *parent)
|
||||||
|
: CMakeWriter(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool CMakeWriterV0::isPlugin(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
if (CMakeWriter::isPlugin(node))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (node->type == Node::Type::App)
|
||||||
|
return !node->files.empty() || !node->singletons.empty() || !node->resources.empty();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeWriterV0::transformNode(NodePtr &node) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return);
|
||||||
|
|
||||||
|
if (node->name == "src") {
|
||||||
|
node->type = Node::Type::Folder;
|
||||||
|
} else if (node->name == "content") {
|
||||||
|
node->type = Node::Type::Module;
|
||||||
|
} else if (node->type == Node::Type::App) {
|
||||||
|
Utils::FilePath path = node->dir.pathAppended("main.qml");
|
||||||
|
if (!path.exists()) {
|
||||||
|
QString text("Expected File %1 not found.");
|
||||||
|
CMakeGenerator::logIssue(text.arg(path.path()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!parent()->findFile(path))
|
||||||
|
node->files.push_back(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeWriterV0::writeRootCMakeFile(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return);
|
||||||
|
|
||||||
|
const Utils::FilePath insightPath = node->dir.pathAppended("insight");
|
||||||
|
if (!insightPath.exists()) {
|
||||||
|
const QString insightTemplate = readTemplate(":/templates/insight");
|
||||||
|
writeFile(insightPath, insightTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Utils::FilePath componentPath = node->dir.pathAppended("qmlcomponents");
|
||||||
|
if (!componentPath.exists()) {
|
||||||
|
const QString compTemplate = readTemplate(":/templates/qmlcomponents");
|
||||||
|
writeFile(componentPath, compTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString appName = parent()->projectName() + "App";
|
||||||
|
const QString qtcontrolsConfFile = getEnvironmentVariable(Constants::ENV_VARIABLE_CONTROLCONF);
|
||||||
|
|
||||||
|
QString fileSection = "";
|
||||||
|
if (!qtcontrolsConfFile.isEmpty())
|
||||||
|
fileSection = QString("\tFILES\n\t\t%1").arg(qtcontrolsConfFile);
|
||||||
|
|
||||||
|
QStringList srcs;
|
||||||
|
for (const Utils::FilePath &path : sources(node))
|
||||||
|
srcs.push_back(makeRelative(node, path));
|
||||||
|
|
||||||
|
const QString fileTemplate = readTemplate(":/templates/cmakeroot_v0");
|
||||||
|
const QString fileContent = fileTemplate.arg(appName, srcs.join(" "), fileSection);
|
||||||
|
|
||||||
|
const Utils::FilePath cmakeFile = node->dir.pathAppended("CMakeLists.txt");
|
||||||
|
writeFile(cmakeFile, fileContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeWriterV0::writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return);
|
||||||
|
|
||||||
|
Utils::FilePath writeToFile = node->dir.pathAppended("CMakeLists.txt");
|
||||||
|
|
||||||
|
QString content(DO_NOT_EDIT_FILE);
|
||||||
|
if (node->type == Node::Type::Folder && parent()->hasChildModule(node)) {
|
||||||
|
content.append(makeSubdirectoriesBlock(node));
|
||||||
|
writeFile(writeToFile, content);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
content.append(makeSubdirectoriesBlock(node));
|
||||||
|
content.append("\n");
|
||||||
|
content.append(makeSingletonBlock(node));
|
||||||
|
|
||||||
|
QString qmlModulesContent;
|
||||||
|
qmlModulesContent.append(makeQmlFilesBlock(node));
|
||||||
|
|
||||||
|
auto [resources, bigResources] = makeResourcesBlocks(node);
|
||||||
|
qmlModulesContent.append(resources);
|
||||||
|
|
||||||
|
if (!qmlModulesContent.isEmpty()) {
|
||||||
|
const QString addLibraryTemplate("qt_add_library(%1 STATIC)");
|
||||||
|
const QString addModuleTemplate(TEMPLATE_ADD_QML_MODULE);
|
||||||
|
|
||||||
|
content.append(addLibraryTemplate.arg(node->name));
|
||||||
|
content.append(addModuleTemplate.arg(node->name, node->uri, qmlModulesContent));
|
||||||
|
content.append("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
content.append(bigResources);
|
||||||
|
|
||||||
|
if (node->type == Node::Type::App) {
|
||||||
|
writeToFile = node->dir.pathAppended("qmlModules");
|
||||||
|
QString pluginNames;
|
||||||
|
for (const QString &moduleName : plugins(root))
|
||||||
|
pluginNames.append("\t" + moduleName + "plugin\n");
|
||||||
|
|
||||||
|
if (!pluginNames.isEmpty())
|
||||||
|
content += QString::fromUtf8(TEMPLATE_LINK_LIBRARIES, -1).arg(pluginNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFile(writeToFile, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeWriterV0::writeSourceFiles(const NodePtr &node, const NodePtr &root) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return);
|
||||||
|
|
||||||
|
const Utils::FilePath srcDir = node->dir;
|
||||||
|
if (!srcDir.exists()) {
|
||||||
|
srcDir.createDir();
|
||||||
|
|
||||||
|
const Utils::FilePath componentsHeaderPath = srcDir.pathAppended(
|
||||||
|
"import_qml_components_plugins.h");
|
||||||
|
const QString componentsHeaderContent = readTemplate(
|
||||||
|
":/templates/import_qml_components_h");
|
||||||
|
writeFile(componentsHeaderPath, componentsHeaderContent);
|
||||||
|
|
||||||
|
const Utils::FilePath cppFilePath = srcDir.pathAppended("main.cpp");
|
||||||
|
const QString cppContent = readTemplate(":/templates/main_cpp_v0");
|
||||||
|
writeFile(cppFilePath, cppContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString fileHeader(
|
||||||
|
"/*\n"
|
||||||
|
" * This file is automatically generated by Qt Design Studio.\n"
|
||||||
|
" * Do not change\n"
|
||||||
|
"*/\n\n");
|
||||||
|
|
||||||
|
const Utils::FilePath envHeaderPath = srcDir.pathAppended("app_environment.h");
|
||||||
|
QString envHeaderContent(fileHeader);
|
||||||
|
envHeaderContent.append("#include <QGuiApplication>\n\n");
|
||||||
|
envHeaderContent.append(makeSetEnvironmentFn());
|
||||||
|
writeFile(envHeaderPath, envHeaderContent);
|
||||||
|
|
||||||
|
QString importPluginsContent;
|
||||||
|
for (const QString &module : plugins(root))
|
||||||
|
importPluginsContent.append(QString("Q_IMPORT_QML_PLUGIN(%1)\n").arg(module + "Plugin"));
|
||||||
|
|
||||||
|
QString importPluginsHeader(fileHeader);
|
||||||
|
importPluginsHeader.append("#include <QtQml/qqmlextensionplugin.h>\n\n");
|
||||||
|
importPluginsHeader.append(importPluginsContent);
|
||||||
|
|
||||||
|
const Utils::FilePath headerFilePath = srcDir.pathAppended("import_qml_plugins.h");
|
||||||
|
writeFile(headerFilePath, importPluginsHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace GenerateCmake
|
||||||
|
} // namespace QmlProjectManager
|
||||||
25
src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.h
Normal file
25
src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cmakewriter.h"
|
||||||
|
|
||||||
|
namespace QmlProjectManager {
|
||||||
|
|
||||||
|
namespace GenerateCmake {
|
||||||
|
|
||||||
|
class CMakeWriterV0 final : public CMakeWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMakeWriterV0(CMakeGenerator *parent);
|
||||||
|
|
||||||
|
bool isPlugin(const NodePtr &node) const override;
|
||||||
|
void transformNode(NodePtr &node) const override;
|
||||||
|
|
||||||
|
void writeRootCMakeFile(const NodePtr &node) const override;
|
||||||
|
void writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const override;
|
||||||
|
void writeSourceFiles(const NodePtr &node, const NodePtr &root) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace GenerateCmake
|
||||||
|
} // namespace QmlProjectManager
|
||||||
179
src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.cpp
Normal file
179
src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.cpp
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
#include "cmakewriterv1.h"
|
||||||
|
#include "cmakegenerator.h"
|
||||||
|
#include "generatecmakelistsconstants.h"
|
||||||
|
|
||||||
|
#include "qmlprojectmanager/buildsystem/qmlbuildsystem.h"
|
||||||
|
|
||||||
|
namespace QmlProjectManager {
|
||||||
|
|
||||||
|
namespace GenerateCmake {
|
||||||
|
|
||||||
|
const char TEMPLATE_SRC_CMAKELISTS[] = R"(
|
||||||
|
target_sources(${CMAKE_PROJECT_NAME} PUBLIC
|
||||||
|
%2)
|
||||||
|
|
||||||
|
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
|
||||||
|
Qt${QT_VERSION_MAJOR}::Core
|
||||||
|
Qt${QT_VERSION_MAJOR}::Gui
|
||||||
|
Qt${QT_VERSION_MAJOR}::Quick
|
||||||
|
Qt${QT_VERSION_MAJOR}::Qml))";
|
||||||
|
|
||||||
|
CMakeWriterV1::CMakeWriterV1(CMakeGenerator *parent)
|
||||||
|
: CMakeWriter(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QString CMakeWriterV1::sourceDirName() const
|
||||||
|
{
|
||||||
|
return "App";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeWriterV1::transformNode(NodePtr &node) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return);
|
||||||
|
|
||||||
|
QString contentDir = parent()->projectName() + "Content";
|
||||||
|
if (node->name == contentDir)
|
||||||
|
node->type = Node::Type::Module;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeWriterV1::writeRootCMakeFile(const NodePtr &node) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return);
|
||||||
|
|
||||||
|
const Utils::FilePath cmakeFolderPath = node->dir.pathAppended("cmake");
|
||||||
|
if (!cmakeFolderPath.exists())
|
||||||
|
cmakeFolderPath.createDir();
|
||||||
|
|
||||||
|
const Utils::FilePath insightPath = cmakeFolderPath.pathAppended("insight.cmake");
|
||||||
|
if (!insightPath.exists()) {
|
||||||
|
const QString insightTemplate = readTemplate(":/templates/insight");
|
||||||
|
writeFile(insightPath, insightTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Utils::FilePath componentPath = cmakeFolderPath.pathAppended("qmlcomponents.cmake");
|
||||||
|
if (!componentPath.exists()) {
|
||||||
|
const QString compTemplate = readTemplate(":/templates/qmlcomponents");
|
||||||
|
writeFile(componentPath, compTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Utils::FilePath file = node->dir.pathAppended("CMakeLists.txt");
|
||||||
|
const QString appName = parent()->projectName() + "App";
|
||||||
|
|
||||||
|
QString fileSection = "";
|
||||||
|
const QString configFile = getEnvironmentVariable(Constants::ENV_VARIABLE_CONTROLCONF);
|
||||||
|
if (!configFile.isEmpty())
|
||||||
|
fileSection = QString("\t\t%1").arg(configFile);
|
||||||
|
|
||||||
|
const QString fileTemplate = readTemplate(":/templates/cmakeroot_v1");
|
||||||
|
const QString fileContent = fileTemplate.arg(appName, fileSection);
|
||||||
|
writeFile(file, fileContent);
|
||||||
|
|
||||||
|
const Utils::FilePath userFile = node->dir.pathAppended("qds.cmake");
|
||||||
|
QString userFileContent(DO_NOT_EDIT_FILE);
|
||||||
|
userFileContent.append(makeSubdirectoriesBlock(node));
|
||||||
|
userFileContent.append("\n");
|
||||||
|
|
||||||
|
QString pluginNames;
|
||||||
|
std::vector<QString> plugs = plugins(node);
|
||||||
|
for (size_t i = 0; i < plugs.size(); ++i) {
|
||||||
|
pluginNames.append("\t" + plugs[i] + "plugin");
|
||||||
|
if (i != plugs.size() - 1)
|
||||||
|
pluginNames.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString linkLibrariesTemplate(
|
||||||
|
"target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE\n"
|
||||||
|
"%1)");
|
||||||
|
|
||||||
|
userFileContent.append(linkLibrariesTemplate.arg(pluginNames));
|
||||||
|
|
||||||
|
writeFile(userFile, userFileContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeWriterV1::writeModuleCMakeFile(const NodePtr &node, const NodePtr &) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return);
|
||||||
|
|
||||||
|
if (node->type == Node::Type::App)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Utils::FilePath writeToFile = node->dir.pathAppended("CMakeLists.txt");
|
||||||
|
if (node->type == Node::Type::Folder && parent()->hasChildModule(node)) {
|
||||||
|
QString content(DO_NOT_EDIT_FILE);
|
||||||
|
content.append(makeSubdirectoriesBlock(node));
|
||||||
|
writeFile(writeToFile, content);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString prefix;
|
||||||
|
prefix.append(makeSubdirectoriesBlock(node));
|
||||||
|
prefix.append(makeSingletonBlock(node));
|
||||||
|
|
||||||
|
auto [resources, bigResources] = makeResourcesBlocks(node);
|
||||||
|
QString moduleContent;
|
||||||
|
moduleContent.append(makeQmlFilesBlock(node));
|
||||||
|
moduleContent.append(resources);
|
||||||
|
|
||||||
|
QString postfix;
|
||||||
|
postfix.append(bigResources);
|
||||||
|
|
||||||
|
const QString fileTemplate = readTemplate(":/templates/cmakemodule_v1");
|
||||||
|
const QString fileContent = fileTemplate
|
||||||
|
.arg(node->name, node->uri, prefix, moduleContent, postfix);
|
||||||
|
writeFile(writeToFile, fileContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeWriterV1::writeSourceFiles(const NodePtr &node, const NodePtr &root) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(parent(), return);
|
||||||
|
QTC_ASSERT(parent()->buildSystem(), return);
|
||||||
|
|
||||||
|
const QmlBuildSystem *buildSystem = parent()->buildSystem();
|
||||||
|
|
||||||
|
const Utils::FilePath srcDir = node->dir;
|
||||||
|
if (!srcDir.exists())
|
||||||
|
srcDir.createDir();
|
||||||
|
|
||||||
|
const Utils::FilePath autogenDir = srcDir.pathAppended("autogen");
|
||||||
|
if (!autogenDir.exists())
|
||||||
|
autogenDir.createDir();
|
||||||
|
|
||||||
|
const Utils::FilePath mainCppPath = srcDir.pathAppended("main.cpp");
|
||||||
|
if (!mainCppPath.exists()) {
|
||||||
|
const QString cppContent = readTemplate(":/templates/main_cpp_v1");
|
||||||
|
writeFile(mainCppPath, cppContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Utils::FilePath cmakePath = srcDir.pathAppended("CMakeLists.txt");
|
||||||
|
if (!cmakePath.exists()) {
|
||||||
|
std::vector<Utils::FilePath> sourcePaths = sources(node);
|
||||||
|
if (sourcePaths.empty())
|
||||||
|
sourcePaths.push_back(mainCppPath);
|
||||||
|
|
||||||
|
QString srcs = {};
|
||||||
|
for (const Utils::FilePath &src : sourcePaths)
|
||||||
|
srcs.append("\t" + makeRelative(node, src) + "\n");
|
||||||
|
|
||||||
|
QString fileTemplate = QString::fromUtf8(TEMPLATE_SRC_CMAKELISTS, -1).arg(srcs);
|
||||||
|
writeFile(cmakePath, fileTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Utils::FilePath headerPath = autogenDir.pathAppended("environment.h");
|
||||||
|
|
||||||
|
QString environmentPrefix;
|
||||||
|
for (const QString &module : plugins(root))
|
||||||
|
environmentPrefix.append(QString("Q_IMPORT_QML_PLUGIN(%1)\n").arg(module + "Plugin"));
|
||||||
|
|
||||||
|
const QString mainFile("const char mainQmlFile[] = \"qrc:/qt/qml/%1\";");
|
||||||
|
environmentPrefix.append("\n");
|
||||||
|
environmentPrefix.append(mainFile.arg(buildSystem->mainFile()));
|
||||||
|
|
||||||
|
const QString environmentPostfix = makeSetEnvironmentFn();
|
||||||
|
const QString headerTemplate = readTemplate(":/templates/environment_h");
|
||||||
|
writeFile(headerPath, headerTemplate.arg(environmentPrefix, environmentPostfix));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace GenerateCmake
|
||||||
|
} // namespace QmlProjectManager
|
||||||
25
src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.h
Normal file
25
src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cmakewriter.h"
|
||||||
|
|
||||||
|
namespace QmlProjectManager {
|
||||||
|
|
||||||
|
namespace GenerateCmake {
|
||||||
|
|
||||||
|
class CMakeWriterV1 final : public CMakeWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMakeWriterV1(CMakeGenerator *parent);
|
||||||
|
|
||||||
|
QString sourceDirName() const override;
|
||||||
|
void transformNode(NodePtr &node) const override;
|
||||||
|
|
||||||
|
void writeRootCMakeFile(const NodePtr &node) const override;
|
||||||
|
void writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const override;
|
||||||
|
void writeSourceFiles(const NodePtr &node, const NodePtr &root) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace GenerateCmake
|
||||||
|
} // namespace QmlProjectManager
|
||||||
@@ -8,7 +8,6 @@ qt6_add_qml_module(%1
|
|||||||
URI "%2"
|
URI "%2"
|
||||||
VERSION 1.0
|
VERSION 1.0
|
||||||
RESOURCE_PREFIX "/qt/qml"
|
RESOURCE_PREFIX "/qt/qml"
|
||||||
%4
|
%4)
|
||||||
)
|
|
||||||
|
|
||||||
%5
|
%5
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.21.1)
|
||||||
|
|
||||||
|
option(LINK_INSIGHT "Link Qt Insight Tracker library" ON)
|
||||||
|
option(BUILD_QDS_COMPONENTS "Build design studio components" ON)
|
||||||
|
|
||||||
|
project(%1 LANGUAGES CXX)
|
||||||
|
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml)
|
||||||
|
set(QML_IMPORT_PATH ${QT_QML_OUTPUT_DIRECTORY}
|
||||||
|
CACHE STRING "Import paths for Qt Creator's code model"
|
||||||
|
FORCE
|
||||||
|
)
|
||||||
|
|
||||||
|
find_package(Qt6 6.2 REQUIRED COMPONENTS Core Gui Qml Quick)
|
||||||
|
|
||||||
|
if (Qt6_VERSION VERSION_GREATER_EQUAL 6.3)
|
||||||
|
qt_standard_project_setup()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
qt_add_executable(${CMAKE_PROJECT_NAME})
|
||||||
|
qt_add_resources(${CMAKE_PROJECT_NAME} "configuration"
|
||||||
|
PREFIX "/"
|
||||||
|
FILES
|
||||||
|
%2)
|
||||||
|
|
||||||
|
include(qds)
|
||||||
|
|
||||||
|
if (BUILD_QDS_COMPONENTS)
|
||||||
|
include(qmlcomponents OPTIONAL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (LINK_INSIGHT)
|
||||||
|
include(insight OPTIONAL)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
install(TARGETS ${CMAKE_PROJECT_NAME}
|
||||||
|
BUNDLE DESTINATION .
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* This file is automatically generated by Qt Design Studio.
|
||||||
|
* Do not change.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include "qqmlextensionplugin.h"
|
||||||
|
|
||||||
|
%1
|
||||||
|
|
||||||
|
#ifdef BUILD_QDS_COMPONENTS
|
||||||
|
|
||||||
|
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_ComponentsPlugin)
|
||||||
|
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EffectsPlugin)
|
||||||
|
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_ApplicationPlugin)
|
||||||
|
Q_IMPORT_QML_PLUGIN(FlowViewPlugin)
|
||||||
|
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_LogicHelperPlugin)
|
||||||
|
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_MultiTextPlugin)
|
||||||
|
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSimulatorPlugin)
|
||||||
|
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSystemPlugin)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%2
|
||||||
@@ -17,3 +17,4 @@ Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSimulatorPlugin)
|
|||||||
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSystemPlugin)
|
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSystemPlugin)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
19
src/plugins/qmlprojectmanager/cmakegen/templates/insight.tpl
Normal file
19
src/plugins/qmlprojectmanager/cmakegen/templates/insight.tpl
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
### This file is automatically generated by Qt Design Studio.
|
||||||
|
### Do not change
|
||||||
|
|
||||||
|
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/qtinsight.conf)
|
||||||
|
if (QT_VERSION GREATER_EQUAL 6.5.0)
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS InsightTracker)
|
||||||
|
|
||||||
|
qt_add_resources(${CMAKE_PROJECT_NAME} "configuration"
|
||||||
|
PREFIX "/"
|
||||||
|
FILES
|
||||||
|
qtinsight.conf
|
||||||
|
)
|
||||||
|
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
|
||||||
|
Qt6::InsightTracker
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(WARNING "You need Qt 6.5.0 or newer to build the application.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
|
||||||
|
#include "app_environment.h"
|
||||||
|
#include "import_qml_plugins.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
set_qt_environment();
|
||||||
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
|
QQmlApplicationEngine engine;
|
||||||
|
const QUrl url(u"qrc:/qt/qml/Main/main.qml"_qs);
|
||||||
|
QObject::connect(
|
||||||
|
&engine, &QQmlApplicationEngine::objectCreated, &app,
|
||||||
|
[url](QObject *obj, const QUrl &objUrl) {
|
||||||
|
if (!obj && url == objUrl)
|
||||||
|
QCoreApplication::exit(-1);
|
||||||
|
},
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
|
engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml");
|
||||||
|
engine.addImportPath(":/");
|
||||||
|
|
||||||
|
engine.load(url);
|
||||||
|
|
||||||
|
if (engine.rootObjects().isEmpty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
|
||||||
|
#include "autogen/environment.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
set_qt_environment();
|
||||||
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
|
QQmlApplicationEngine engine;
|
||||||
|
const QUrl url(mainQmlFile);
|
||||||
|
QObject::connect(
|
||||||
|
&engine, &QQmlApplicationEngine::objectCreated, &app,
|
||||||
|
[url](QObject *obj, const QUrl &objUrl) {
|
||||||
|
if (!obj && url == objUrl)
|
||||||
|
QCoreApplication::exit(-1);
|
||||||
|
}, Qt::QueuedConnection);
|
||||||
|
|
||||||
|
engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml");
|
||||||
|
engine.addImportPath(":/");
|
||||||
|
engine.load(url);
|
||||||
|
|
||||||
|
if (engine.rootObjects().isEmpty())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
### This file is automatically generated by Qt Design Studio.
|
||||||
|
### Do not change
|
||||||
|
|
||||||
|
message("Building designer components.")
|
||||||
|
|
||||||
|
set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml")
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(
|
||||||
|
ds
|
||||||
|
GIT_TAG qds-4.5
|
||||||
|
GIT_REPOSITORY https://code.qt.io/qt-labs/qtquickdesigner-components.git
|
||||||
|
)
|
||||||
|
|
||||||
|
FetchContent_GetProperties(ds)
|
||||||
|
FetchContent_Populate(ds)
|
||||||
|
|
||||||
|
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
|
||||||
|
QuickStudioComponentsplugin
|
||||||
|
QuickStudioEffectsplugin
|
||||||
|
QuickStudioApplicationplugin
|
||||||
|
FlowViewplugin
|
||||||
|
QuickStudioLogicHelperplugin
|
||||||
|
QuickStudioMultiTextplugin
|
||||||
|
QuickStudioEventSimulatorplugin
|
||||||
|
QuickStudioEventSystemplugin
|
||||||
|
QuickStudioUtilsplugin
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(${ds_SOURCE_DIR} ${ds_BINARY_DIR})
|
||||||
|
|
||||||
|
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
|
||||||
|
BULD_QDS_COMPONENTS=true
|
||||||
|
)
|
||||||
@@ -54,6 +54,10 @@ QtcPlugin {
|
|||||||
"cmakegeneratordialog.cpp", "cmakegeneratordialog.h",
|
"cmakegeneratordialog.cpp", "cmakegeneratordialog.h",
|
||||||
"cmakeprojectconverter.cpp", "cmakeprojectconverter.h",
|
"cmakeprojectconverter.cpp", "cmakeprojectconverter.h",
|
||||||
"cmakeprojectconverterdialog.cpp", "cmakeprojectconverterdialog.h",
|
"cmakeprojectconverterdialog.cpp", "cmakeprojectconverterdialog.h",
|
||||||
|
"cmakegenerator.cpp", "cmakegenerator.h",
|
||||||
|
"cmakewriter.cpp", "cmakewriter.h",
|
||||||
|
"cmakewriterv0.cpp", "cmakewriterv0.h",
|
||||||
|
"cmakewriterv1.cpp", "cmakewriterv1.h"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -386,6 +386,8 @@ void QmlProjectPlugin::initialize()
|
|||||||
mainUifileAction->setEnabled(buildSystem->mainUiFilePath()
|
mainUifileAction->setEnabled(buildSystem->mainUiFilePath()
|
||||||
!= fileNode->filePath());
|
!= fileNode->filePath());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
GenerateCmake::CMakeGenerator::createMenuAction(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
GenerateCmake::generateMenuEntry(this);
|
GenerateCmake::generateMenuEntry(this);
|
||||||
|
|||||||
Reference in New Issue
Block a user