forked from qt-creator/qt-creator
QmlProjectExporter: Add writer to compile the project as a library
This writer writes cmake files to compile the project as a library. To enable set the property standaloneApp to false. Note that this writer can be enabled for DS version > 4.8 Change-Id: I24dc2b1a7a0f02648063ce11232c15a5b170f6b7 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -48,6 +48,7 @@ extend_qtc_plugin(QmlProjectManager
|
||||
cmakewriter.cpp cmakewriter.h
|
||||
cmakewriterv0.cpp cmakewriterv0.h
|
||||
cmakewriterv1.cpp cmakewriterv1.h
|
||||
cmakewriterlib.cpp cmakewriterlib.h
|
||||
exporter.cpp exporter.h
|
||||
filegenerator.cpp filegenerator.h
|
||||
filetypes.cpp filetypes.h
|
||||
|
@@ -2,6 +2,7 @@
|
||||
<qresource prefix="/templates">
|
||||
<file alias="cmakeroot_v0">templates/cmakeroot_v0.tpl</file>
|
||||
<file alias="cmakeroot_v1">templates/cmakeroot_v1.tpl</file>
|
||||
<file alias="cmakeroot_lib">templates/cmakeroot_lib.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>
|
||||
|
@@ -11,10 +11,12 @@
|
||||
#include "projectexplorer/projectnodes.h"
|
||||
|
||||
#include "utils/filenamevalidatinglineedit.h"
|
||||
#include "utils/persistentsettings.h"
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QFileInfo>
|
||||
#include <QRegularExpression>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <set>
|
||||
|
||||
@@ -60,7 +62,12 @@ void CMakeGenerator::updateProject(QmlProject *project)
|
||||
if (!isEnabled())
|
||||
return;
|
||||
|
||||
m_writer = CMakeWriter::create(this);
|
||||
if (!isActive())
|
||||
return;
|
||||
|
||||
createWriter();
|
||||
if (!m_writer)
|
||||
return;
|
||||
|
||||
m_root = std::make_shared<Node>();
|
||||
m_root->type = Node::Type::App;
|
||||
@@ -85,6 +92,14 @@ QString CMakeGenerator::projectName() const
|
||||
return m_projectName;
|
||||
}
|
||||
|
||||
Utils::FilePath CMakeGenerator::projectDir() const
|
||||
{
|
||||
if (!m_root)
|
||||
return {};
|
||||
|
||||
return m_root->dir;
|
||||
}
|
||||
|
||||
bool CMakeGenerator::findFile(const Utils::FilePath& file) const
|
||||
{
|
||||
return findFile(m_root, file);
|
||||
@@ -440,6 +455,18 @@ void CMakeGenerator::removeFile(NodePtr &node, const Utils::FilePath &path) cons
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeGenerator::removeAmbiguousFiles(const Utils::FilePath &rootPath) const
|
||||
{
|
||||
const Utils::FilePath rootCMakeFile = rootPath.pathAppended("CMakeLists.txt");
|
||||
rootCMakeFile.removeFile();
|
||||
|
||||
const Utils::FilePath sourceDirPath = rootPath.pathAppended("App");
|
||||
if (sourceDirPath.exists()) {
|
||||
const Utils::FilePath appCMakeFile = sourceDirPath.pathAppended("CMakeLists.txt");
|
||||
appCMakeFile.removeFile();
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeGenerator::printModules(const NodePtr &node) const
|
||||
{
|
||||
if (node->type == Node::Type::Module)
|
||||
@@ -470,11 +497,12 @@ void CMakeGenerator::printNodeTree(const NodePtr &generatorNode, size_t indent)
|
||||
case Node::Type::Module:
|
||||
typeString = "Node::Type::Module";
|
||||
break;
|
||||
case Node::Type::MockModule:
|
||||
typeString = "Node::Type::MockModule";
|
||||
break;
|
||||
case Node::Type::Library:
|
||||
typeString = "Node::Type::Library";
|
||||
break;
|
||||
default:
|
||||
typeString = "Node::Type::Undefined";
|
||||
}
|
||||
|
||||
qDebug() << addIndent(indent) << "GeneratorNode: " << generatorNode->name;
|
||||
@@ -517,7 +545,11 @@ void CMakeGenerator::parseSourceTree()
|
||||
{
|
||||
QTC_ASSERT(m_writer, return);
|
||||
|
||||
const Utils::FilePath srcDir = m_root->dir.pathAppended(m_writer->sourceDirName());
|
||||
QString srcDirName = m_writer->sourceDirName();
|
||||
if (srcDirName.isEmpty())
|
||||
return;
|
||||
|
||||
const Utils::FilePath srcDir = m_root->dir.pathAppended(srcDirName);
|
||||
QDirIterator it(srcDir.path(), {"*.cpp"}, QDir::Files, QDirIterator::Subdirectories);
|
||||
|
||||
NodePtr srcNode = std::make_shared<Node>();
|
||||
@@ -560,5 +592,62 @@ void CMakeGenerator::compareWithFileSystem(const NodePtr &node) const
|
||||
logIssue(ProjectExplorer::Task::Warning, text, file);
|
||||
}
|
||||
|
||||
void CMakeGenerator::createWriter()
|
||||
{
|
||||
auto writer = CMakeWriter::create(this);
|
||||
|
||||
const QmlProject *project = qmlProject();
|
||||
QTC_ASSERT(project, return );
|
||||
|
||||
const Utils::FilePath rootPath = project->projectDirectory();
|
||||
const Utils::FilePath settingsFile = rootPath.pathAppended("CMakeLists.txt.shared");
|
||||
Utils::PersistentSettingsReader reader;
|
||||
reader.load(settingsFile);
|
||||
auto store = reader.restoreValues();
|
||||
|
||||
auto writeSettings = [settingsFile, &store](int identifier) {
|
||||
store["CMake Generator"] = identifier;
|
||||
QString error;
|
||||
Utils::PersistentSettingsWriter settingsWriter(settingsFile, "QtCreatorProject");
|
||||
if (!settingsWriter.save(store, &error)) {
|
||||
const QString text("Failed to write settings file");
|
||||
logIssue(ProjectExplorer::Task::Error, text, settingsFile);
|
||||
}
|
||||
};
|
||||
|
||||
QVariant idVariant = store["CMake Generator"];
|
||||
if (!idVariant.isValid()) {
|
||||
writeSettings(writer->identifier());
|
||||
m_writer = writer;
|
||||
return;
|
||||
}
|
||||
|
||||
int identifier = writer->identifier();
|
||||
int currentId = idVariant.toInt();
|
||||
if (currentId == identifier) {
|
||||
m_writer = writer;
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox msgBox;
|
||||
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
msgBox.setText("The CmakeGenerator Has Changed");
|
||||
msgBox.setInformativeText(
|
||||
"This operation will delete build files that may contain"
|
||||
" user-made changes. Are you sure you want to proceed?");
|
||||
int ret = msgBox.exec();
|
||||
|
||||
if (ret == QMessageBox::Cancel) {
|
||||
m_writer = CMakeWriter::createAndRecover(currentId, this);
|
||||
return;
|
||||
}
|
||||
|
||||
removeAmbiguousFiles( rootPath );
|
||||
|
||||
writeSettings(writer->identifier());
|
||||
m_writer = writer;
|
||||
}
|
||||
|
||||
} // namespace QmlProjectExporter
|
||||
} // namespace QmlProjectManager
|
||||
|
@@ -33,6 +33,8 @@ public:
|
||||
void updateMenuAction() override;
|
||||
|
||||
QString projectName() const;
|
||||
Utils::FilePath projectDir() const;
|
||||
|
||||
bool findFile(const Utils::FilePath &file) const;
|
||||
bool isRootNode(const NodePtr &node) const;
|
||||
bool hasChildModule(const NodePtr &node) const;
|
||||
@@ -57,6 +59,7 @@ private:
|
||||
bool findFile(const NodePtr &node, const Utils::FilePath &file) const;
|
||||
void insertFile(NodePtr &node, const Utils::FilePath &path) const;
|
||||
void removeFile(NodePtr &node, const Utils::FilePath &path) const;
|
||||
void removeAmbiguousFiles(const Utils::FilePath &rootPath) const;
|
||||
|
||||
void printModules(const NodePtr &generatorNode) const;
|
||||
void printNodeTree(const NodePtr &generatorNode, size_t indent = 0) const;
|
||||
@@ -66,6 +69,7 @@ private:
|
||||
|
||||
void compareWithFileSystem(const NodePtr &node) const;
|
||||
|
||||
void createWriter();
|
||||
CMakeWriter::Ptr m_writer = {};
|
||||
|
||||
QString m_projectName = {};
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include "cmakegenerator.h"
|
||||
#include "cmakewriterv0.h"
|
||||
#include "cmakewriterv1.h"
|
||||
#include "cmakewriterlib.h"
|
||||
|
||||
#include "qmlprojectmanager/buildsystem/qmlbuildsystem.h"
|
||||
#include "qmlprojectmanager/qmlproject.h"
|
||||
@@ -42,14 +43,24 @@ CMakeWriter::Ptr CMakeWriter::create(CMakeGenerator *parent)
|
||||
const QmlBuildSystem *buildSystem = parent->buildSystem();
|
||||
QTC_ASSERT(buildSystem, return {});
|
||||
|
||||
auto [major, minor, patch] = versionFromString(buildSystem->versionDesignStudio());
|
||||
auto version = versionFromString(buildSystem->versionDesignStudio());
|
||||
auto normalizedVersion = normalizeVersion(version);
|
||||
|
||||
bool useV1 = false;
|
||||
if (major.has_value())
|
||||
useV1 = minor.has_value() ? *major >= 4 && *minor >= 5 : *major >= 5;
|
||||
|
||||
if (useV1)
|
||||
if (normalizedVersion >= std::make_tuple(4, 5, 0)) {
|
||||
if (!buildSystem->standaloneApp()) {
|
||||
if (normalizedVersion >= std::make_tuple(4, 8, 0)) {
|
||||
return std::make_unique<CMakeWriterLib>(parent);
|
||||
} else {
|
||||
CMakeGenerator::logIssue(
|
||||
ProjectExplorer::Task::Error,
|
||||
Tr::tr(
|
||||
"Compiling the project as a library requires"
|
||||
" Qt Design Studio 4.8 or later."),
|
||||
buildSystem->projectFilePath());
|
||||
}
|
||||
}
|
||||
return std::make_unique<CMakeWriterV1>(parent);
|
||||
}
|
||||
|
||||
CMakeGenerator::logIssue(
|
||||
ProjectExplorer::Task::Warning,
|
||||
@@ -67,6 +78,24 @@ CMakeWriter::Ptr CMakeWriter::create(CMakeGenerator *parent)
|
||||
return std::make_unique<CMakeWriterV0>(parent);
|
||||
}
|
||||
|
||||
CMakeWriter::Ptr CMakeWriter::createAndRecover(int id, CMakeGenerator *parent)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case 1:
|
||||
return std::make_unique<CMakeWriterV0>(parent);
|
||||
case 2:
|
||||
parent->setStandaloneApp(true);
|
||||
return std::make_unique<CMakeWriterV1>(parent);
|
||||
case 3:
|
||||
parent->setStandaloneApp(false);
|
||||
return std::make_unique<CMakeWriterLib>(parent);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
CMakeWriter::Version CMakeWriter::versionFromString(const QString &versionString)
|
||||
{
|
||||
const QStringList versions = versionString.split('.', Qt::SkipEmptyParts);
|
||||
@@ -98,6 +127,12 @@ CMakeWriter::Version CMakeWriter::versionFromIgnoreFile(const Utils::FilePath &p
|
||||
return {};
|
||||
}
|
||||
|
||||
CMakeWriter::NormalizedVersion CMakeWriter::normalizeVersion(const Version &version)
|
||||
{
|
||||
auto [major, minor, patch] = version;
|
||||
return {major.value_or(0), minor.value_or(0), patch.value_or(0)};
|
||||
}
|
||||
|
||||
QString CMakeWriter::readTemplate(const QString &templatePath)
|
||||
{
|
||||
QFile templatefile(templatePath);
|
||||
@@ -149,6 +184,19 @@ QString CMakeWriter::sourceDirName() const
|
||||
void CMakeWriter::transformNode(NodePtr &) const
|
||||
{}
|
||||
|
||||
bool CMakeWriter::hasNewComponents() const
|
||||
{
|
||||
auto rootDir = m_parent->projectDir();
|
||||
auto componentsDir = rootDir.pathAppended("Dependencies/Components");
|
||||
|
||||
if (!componentsDir.exists())
|
||||
return false;
|
||||
|
||||
auto ignoreFile = componentsDir.pathAppended("ignore-in-qds");
|
||||
auto version = normalizeVersion(versionFromIgnoreFile(ignoreFile));
|
||||
return version >= std::make_tuple(4, 8, 0);
|
||||
}
|
||||
|
||||
std::vector<Utils::FilePath> CMakeWriter::files(const NodePtr &node, const FileGetter &getter) const
|
||||
{
|
||||
std::vector<Utils::FilePath> out = getter(node);
|
||||
|
@@ -63,10 +63,14 @@ class CMakeWriter
|
||||
public:
|
||||
using Ptr = std::shared_ptr<CMakeWriter>;
|
||||
using Version = std::tuple<std::optional<int>, std::optional<int>, std::optional<int>>;
|
||||
using NormalizedVersion = std::tuple<int, int, int>;
|
||||
|
||||
static Ptr create(CMakeGenerator *parent);
|
||||
static Ptr createAndRecover(int id, CMakeGenerator *parent);
|
||||
|
||||
static Version versionFromString(const QString &versionString);
|
||||
static Version versionFromIgnoreFile(const Utils::FilePath &path);
|
||||
static NormalizedVersion normalizeVersion(const Version &version);
|
||||
static QString readTemplate(const QString &templatePath);
|
||||
static void writeFile(const Utils::FilePath &path, const QString &content);
|
||||
|
||||
@@ -79,11 +83,14 @@ public:
|
||||
virtual QString sourceDirName() const;
|
||||
virtual void transformNode(NodePtr &) const;
|
||||
|
||||
virtual int identifier() const = 0;
|
||||
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:
|
||||
bool hasNewComponents() const;
|
||||
|
||||
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;
|
||||
|
@@ -0,0 +1,112 @@
|
||||
// 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 "cmakewriterlib.h"
|
||||
#include "cmakegenerator.h"
|
||||
|
||||
#include "qmlprojectmanager/buildsystem/qmlbuildsystem.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
namespace QmlProjectManager {
|
||||
|
||||
namespace QmlProjectExporter {
|
||||
|
||||
CMakeWriterLib::CMakeWriterLib(CMakeGenerator *parent)
|
||||
: CMakeWriterV1(parent)
|
||||
{ }
|
||||
|
||||
QString CMakeWriterLib::mainLibName() const
|
||||
{
|
||||
QTC_ASSERT(parent(), return {});
|
||||
return parent()->projectName() + "Lib";
|
||||
}
|
||||
|
||||
void CMakeWriterLib::transformNode(NodePtr &node) const
|
||||
{
|
||||
CMakeWriterV1::transformNode(node);
|
||||
}
|
||||
|
||||
int CMakeWriterLib::identifier() const
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
void CMakeWriterLib::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);
|
||||
}
|
||||
|
||||
createDependencies(node->dir);
|
||||
|
||||
const Utils::FilePath sharedFile = node->dir.pathAppended("CMakeLists.txt.shared");
|
||||
if (!sharedFile.exists()) {
|
||||
const QString sharedTemplate = readTemplate(":/templates/cmake_shared");
|
||||
writeFile(sharedFile, sharedTemplate);
|
||||
}
|
||||
|
||||
const Utils::FilePath file = node->dir.pathAppended("CMakeLists.txt");
|
||||
if (!file.exists()) {
|
||||
QString fileSection = "";
|
||||
const QString configFile = getEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
|
||||
if (!configFile.isEmpty())
|
||||
fileSection = QString("\t\t%1").arg(configFile);
|
||||
|
||||
const QString fileTemplate = readTemplate(":/templates/cmakeroot_lib");
|
||||
const QString fileContent = fileTemplate.arg(mainLibName(), fileSection);
|
||||
writeFile(file, fileContent);
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeWriterLib::writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const
|
||||
{
|
||||
CMakeWriterV1::writeModuleCMakeFile(node, root);
|
||||
}
|
||||
|
||||
void CMakeWriterLib::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 cmakePath = srcDir.pathAppended("CMakeLists.txt");
|
||||
if (!cmakePath.exists()) {
|
||||
const QString includeAutogen =
|
||||
"\ntarget_include_directories(%1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})";
|
||||
writeFile(cmakePath, includeAutogen.arg(mainLibName()));
|
||||
}
|
||||
|
||||
const Utils::FilePath autogenDir = srcDir.pathAppended("autogen");
|
||||
if (!autogenDir.exists())
|
||||
autogenDir.createDir();
|
||||
|
||||
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 QmlProjectExporter
|
||||
} // namespace QmlProjectManager
|
@@ -0,0 +1,26 @@
|
||||
// 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 "cmakewriterv1.h"
|
||||
|
||||
namespace QmlProjectManager {
|
||||
|
||||
namespace QmlProjectExporter {
|
||||
|
||||
class CMakeWriterLib final : public CMakeWriterV1
|
||||
{
|
||||
public:
|
||||
CMakeWriterLib(CMakeGenerator *parent);
|
||||
|
||||
QString mainLibName() const override;
|
||||
void transformNode(NodePtr &node) const override;
|
||||
|
||||
int identifier() 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 QmlProjectExporter
|
||||
} // namespace QmlProjectManager
|
@@ -46,6 +46,11 @@ void CMakeWriterV0::transformNode(NodePtr &node) const
|
||||
}
|
||||
}
|
||||
|
||||
int CMakeWriterV0::identifier() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CMakeWriterV0::writeRootCMakeFile(const NodePtr &node) const
|
||||
{
|
||||
QTC_ASSERT(parent(), return);
|
||||
|
@@ -16,6 +16,7 @@ public:
|
||||
bool isPlugin(const NodePtr &node) const override;
|
||||
void transformNode(NodePtr &node) const override;
|
||||
|
||||
int identifier() 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;
|
||||
|
@@ -33,6 +33,11 @@ CMakeWriterV1::CMakeWriterV1(CMakeGenerator *parent)
|
||||
: CMakeWriter(parent)
|
||||
{}
|
||||
|
||||
QString CMakeWriterV1::mainLibName() const
|
||||
{
|
||||
return "${CMAKE_PROJECT_NAME}";
|
||||
}
|
||||
|
||||
QString CMakeWriterV1::sourceDirName() const
|
||||
{
|
||||
return "App";
|
||||
@@ -47,6 +52,11 @@ void CMakeWriterV1::transformNode(NodePtr &node) const
|
||||
node->type = Node::Type::Module;
|
||||
}
|
||||
|
||||
int CMakeWriterV1::identifier() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
void CMakeWriterV1::writeRootCMakeFile(const NodePtr &node) const
|
||||
{
|
||||
QTC_ASSERT(parent(), return);
|
||||
@@ -62,72 +72,7 @@ void CMakeWriterV1::writeRootCMakeFile(const NodePtr &node) const
|
||||
writeFile(insightPath, insightTemplate);
|
||||
}
|
||||
|
||||
const Utils::FilePath dependenciesPath = node->dir.pathAppended(DEPENDENCIES_DIR);
|
||||
const Utils::FilePath componentsPath = dependenciesPath.pathAppended(COMPONENTS_DIR);
|
||||
const Utils::FilePath componentsIgnoreFile = componentsPath.pathAppended(COMPONENTS_IGNORE_FILE);
|
||||
|
||||
bool copyComponents = false;
|
||||
// Note: If dependencies directory exists but not the components directory, we assunme
|
||||
// the user has intentionally deleted it because he has the components installed in Qt.
|
||||
if (!dependenciesPath.exists()) {
|
||||
dependenciesPath.createDir();
|
||||
copyComponents = true;
|
||||
} else if (componentsIgnoreFile.exists()) {
|
||||
auto normalizeVersion = [](const auto &version) -> std::tuple<int, int, int> {
|
||||
auto [major, minor, patch] = version;
|
||||
return {major.value_or(0), minor.value_or(0), patch.value_or(0)};
|
||||
};
|
||||
auto *bs = parent()->buildSystem();
|
||||
auto versionDS = normalizeVersion(versionFromString(bs->versionDesignStudio()));
|
||||
auto versionIgnore = normalizeVersion(versionFromIgnoreFile(componentsIgnoreFile));
|
||||
if (versionDS > versionIgnore) {
|
||||
copyComponents = true;
|
||||
if (componentsPath.exists())
|
||||
componentsPath.removeRecursively();
|
||||
}
|
||||
}
|
||||
|
||||
if (copyComponents) {
|
||||
if (!componentsPath.exists())
|
||||
componentsPath.createDir();
|
||||
|
||||
const Utils::FilePath componentsSrc =
|
||||
Core::ICore::resourcePath("qmldesigner/Dependencies/qtquickdesigner-components");
|
||||
|
||||
if (componentsSrc.exists()) {
|
||||
auto cpyResult = componentsSrc.copyRecursively(componentsPath);
|
||||
if (cpyResult) {
|
||||
QString depsTemplate =
|
||||
QString::fromUtf8(TEMPLATE_DEPENDENCIES_CMAKELISTS, -1).arg(COMPONENTS_DIR);
|
||||
writeFile(dependenciesPath.pathAppended("CMakeLists.txt"), depsTemplate);
|
||||
|
||||
const Utils::FilePath qmlComponentsFilePath =
|
||||
cmakeFolderPath.pathAppended("qmlcomponents.cmake");
|
||||
|
||||
if (qmlComponentsFilePath.exists()) {
|
||||
|
||||
const QString warningMsg = Tr::tr(
|
||||
"The project structure has changed.\n"
|
||||
"Please clean the build folder before rebuilding\n");
|
||||
|
||||
CMakeGenerator::logIssue(
|
||||
ProjectExplorer::Task::Warning, warningMsg, componentsPath);
|
||||
|
||||
auto removeResult = qmlComponentsFilePath.removeFile();
|
||||
if (!removeResult) {
|
||||
QString removeMsg = Tr::tr("Failed to remove the qmlcomponents.cmake file.\n");
|
||||
removeMsg.append(removeResult.error());
|
||||
|
||||
CMakeGenerator::logIssue(
|
||||
ProjectExplorer::Task::Warning, removeMsg, qmlComponentsFilePath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CMakeGenerator::logIssue(
|
||||
ProjectExplorer::Task::Error, cpyResult.error(), componentsSrc);
|
||||
}
|
||||
}
|
||||
}
|
||||
createDependencies(node->dir);
|
||||
|
||||
const Utils::FilePath sharedFile = node->dir.pathAppended("CMakeLists.txt.shared");
|
||||
if (!sharedFile.exists()) {
|
||||
@@ -179,12 +124,15 @@ void CMakeWriterV1::writeModuleCMakeFile(const NodePtr &node, const NodePtr &) c
|
||||
pluginNames.append("\n");
|
||||
}
|
||||
|
||||
if (hasNewComponents())
|
||||
pluginNames.append(QString("\n\t") + "QtQuickDesignerComponents");
|
||||
|
||||
QString linkLibrariesTemplate(
|
||||
"target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE\n"
|
||||
"%1)");
|
||||
"target_link_libraries(%1 PRIVATE\n"
|
||||
"%2)");
|
||||
|
||||
userFileContent.append("\n");
|
||||
userFileContent.append(linkLibrariesTemplate.arg(pluginNames));
|
||||
userFileContent.append(linkLibrariesTemplate.arg(mainLibName(), pluginNames));
|
||||
writeFile(userFile, userFileContent);
|
||||
return;
|
||||
}
|
||||
@@ -265,5 +213,78 @@ void CMakeWriterV1::writeSourceFiles(const NodePtr &node, const NodePtr &root) c
|
||||
writeFile(headerPath, headerTemplate.arg(environmentPrefix, environmentPostfix));
|
||||
}
|
||||
|
||||
void CMakeWriterV1::createDependencies(const Utils::FilePath &rootDir) const
|
||||
{
|
||||
const Utils::FilePath dependenciesPath = rootDir.pathAppended(DEPENDENCIES_DIR);
|
||||
const Utils::FilePath componentsPath = dependenciesPath.pathAppended(COMPONENTS_DIR);
|
||||
const Utils::FilePath componentsIgnoreFile = componentsPath.pathAppended(COMPONENTS_IGNORE_FILE);
|
||||
|
||||
bool copyComponents = false;
|
||||
// Note: If dependencies directory exists but not the components directory, we assunme
|
||||
// the user has intentionally deleted it because he has the components installed in Qt.
|
||||
if (!dependenciesPath.exists()) {
|
||||
dependenciesPath.createDir();
|
||||
copyComponents = true;
|
||||
} else if (componentsIgnoreFile.exists()) {
|
||||
auto *bs = parent()->buildSystem();
|
||||
auto versionDS = normalizeVersion(versionFromString(bs->versionDesignStudio()));
|
||||
auto versionIgnore = normalizeVersion(versionFromIgnoreFile(componentsIgnoreFile));
|
||||
if (versionDS > versionIgnore) {
|
||||
copyComponents = true;
|
||||
if (componentsPath.exists())
|
||||
componentsPath.removeRecursively();
|
||||
}
|
||||
}
|
||||
|
||||
if (copyComponents) {
|
||||
if (!componentsPath.exists())
|
||||
componentsPath.createDir();
|
||||
|
||||
Utils::FilePath componentsSrc =
|
||||
Core::ICore::resourcePath("qmldesigner/Dependencies/qtquickdesigner-components");
|
||||
|
||||
const Utils::FilePath unifiedPath =
|
||||
Core::ICore::resourcePath("qmldesigner/Dependencies/qtquickdesigner-components/components");
|
||||
|
||||
if (unifiedPath.exists( ))
|
||||
componentsSrc = unifiedPath;
|
||||
|
||||
if (componentsSrc.exists()) {
|
||||
auto cpyResult = componentsSrc.copyRecursively(componentsPath);
|
||||
if (cpyResult) {
|
||||
QString depsTemplate =
|
||||
QString::fromUtf8(TEMPLATE_DEPENDENCIES_CMAKELISTS, -1).arg(COMPONENTS_DIR);
|
||||
writeFile(dependenciesPath.pathAppended("CMakeLists.txt"), depsTemplate);
|
||||
|
||||
const Utils::FilePath cmakeFolderPath = rootDir.pathAppended("cmake");
|
||||
const Utils::FilePath qmlComponentsFilePath =
|
||||
cmakeFolderPath.pathAppended("qmlcomponents.cmake");
|
||||
|
||||
if (qmlComponentsFilePath.exists()) {
|
||||
|
||||
const QString warningMsg = Tr::tr(
|
||||
"The project structure has changed.\n"
|
||||
"Please clean the build folder before rebuilding\n");
|
||||
|
||||
CMakeGenerator::logIssue(
|
||||
ProjectExplorer::Task::Warning, warningMsg, componentsPath);
|
||||
|
||||
auto removeResult = qmlComponentsFilePath.removeFile();
|
||||
if (!removeResult) {
|
||||
QString removeMsg = Tr::tr("Failed to remove the qmlcomponents.cmake file.\n");
|
||||
removeMsg.append(removeResult.error());
|
||||
|
||||
CMakeGenerator::logIssue(
|
||||
ProjectExplorer::Task::Warning, removeMsg, qmlComponentsFilePath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CMakeGenerator::logIssue(
|
||||
ProjectExplorer::Task::Error, cpyResult.error(), componentsSrc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace QmlProjectExporter
|
||||
} // namespace QmlProjectManager
|
||||
|
@@ -8,17 +8,23 @@ namespace QmlProjectManager {
|
||||
|
||||
namespace QmlProjectExporter {
|
||||
|
||||
class CMakeWriterV1 final : public CMakeWriter
|
||||
class CMakeWriterV1 : public CMakeWriter
|
||||
{
|
||||
public:
|
||||
CMakeWriterV1(CMakeGenerator *parent);
|
||||
|
||||
virtual QString mainLibName() const;
|
||||
|
||||
QString sourceDirName() const override;
|
||||
void transformNode(NodePtr &node) const override;
|
||||
|
||||
int identifier() 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;
|
||||
|
||||
protected:
|
||||
void createDependencies(const Utils::FilePath &rootDir) const;
|
||||
};
|
||||
|
||||
} // namespace QmlProjectExporter
|
||||
|
@@ -36,9 +36,6 @@ void Exporter::updateProjectItem(QmlProjectItem *item, bool updateEnabled)
|
||||
if (updateEnabled) {
|
||||
m_cmakeGen->setEnabled(item->enableCMakeGeneration());
|
||||
m_pythonGen->setEnabled(item->enablePythonGeneration());
|
||||
|
||||
m_cmakeGen->setStandaloneApp(item->standaloneApp());
|
||||
m_pythonGen->setStandaloneApp(item->standaloneApp());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include "../qmlprojectmanagertr.h"
|
||||
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
@@ -68,6 +69,17 @@ bool FileGenerator::isEnabled() const
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
bool FileGenerator::isActive() const
|
||||
{
|
||||
if (!m_buildSystem)
|
||||
return false;
|
||||
|
||||
if (auto *target = m_buildSystem->target())
|
||||
return target->isActive();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FileGenerator::setEnabled(bool enabled)
|
||||
{
|
||||
m_enabled = enabled;
|
||||
@@ -75,12 +87,15 @@ void FileGenerator::setEnabled(bool enabled)
|
||||
|
||||
bool FileGenerator::standaloneApp() const
|
||||
{
|
||||
return m_standaloneApp;
|
||||
if (m_buildSystem)
|
||||
return m_buildSystem->standaloneApp();
|
||||
return false;
|
||||
}
|
||||
|
||||
void FileGenerator::setStandaloneApp(bool value)
|
||||
{
|
||||
m_standaloneApp = value;
|
||||
if (m_buildSystem)
|
||||
m_buildSystem->setStandaloneApp(value);
|
||||
}
|
||||
|
||||
void FileGenerator::updateMenuAction(const Utils::Id &id, std::function<bool(void)> isEnabled)
|
||||
|
@@ -32,6 +32,7 @@ public:
|
||||
const QmlBuildSystem *buildSystem() const;
|
||||
|
||||
bool isEnabled() const;
|
||||
bool isActive() const;
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
bool standaloneApp() const;
|
||||
@@ -42,7 +43,6 @@ protected:
|
||||
|
||||
private:
|
||||
bool m_enabled = false;
|
||||
bool m_standaloneApp = false;
|
||||
QmlBuildSystem *m_buildSystem = nullptr;
|
||||
};
|
||||
|
||||
|
@@ -0,0 +1,28 @@
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
qt_add_library(%1)
|
||||
qt_add_resources(%1 "configuration"
|
||||
PREFIX "/"
|
||||
FILES
|
||||
%2)
|
||||
|
||||
include(qds)
|
||||
|
||||
if (LINK_INSIGHT)
|
||||
include(insight OPTIONAL)
|
||||
endif ()
|
||||
|
Reference in New Issue
Block a user