Files
qt-creator/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.cpp
Knud Dollereder e55b5d0a0b QmlProjectManager: Write cmake-generator issues into the issues panel
write qtquickcontrols file if it does not exist
and minor cleanup of the cmake generator.

Change-Id: I9b7523f32e5a9b41904c02a398a6f924623f949a
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
2024-04-16 12:11:34 +00:00

260 lines
7.5 KiB
C++

// 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");
CMakeGenerator::logIssue(ProjectExplorer::Task::Error, text, 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.