CMakePM: Add "CMake Install" deployment step

This commit adds a "CMake Install" deployment step, which is using
"cmake --install" command.

"cmake --install" command has been added in CMake 3.15, this is why the
minimum CMake version has been updated to 3.15.

Note that CMakeBuildSystem::makeInstallCommand is still using cmake --
build --target install due to a CMake bug regarding "Ninja Multi-Config"
generator, which doesn't intall all binaries via "cmake --install".

Fixes: QTCREATORBUG-25880
Change-Id: I504674c380055d8ef136d344a78b80c17ecf9765
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Cristian Adam
2022-12-09 18:44:42 +01:00
parent 2eb2aa13ae
commit a0afd51f3f
12 changed files with 270 additions and 46 deletions

View File

@@ -5,6 +5,7 @@ add_qtc_plugin(CMakeProjectManager
SOURCES
builddirparameters.cpp builddirparameters.h
cmake_global.h
cmakeabstractprocessstep.cpp cmakeabstractprocessstep.h
cmakeautocompleter.cpp cmakeautocompleter.h
cmakebuildconfiguration.cpp cmakebuildconfiguration.h
cmakebuildsystem.cpp cmakebuildsystem.h
@@ -17,6 +18,7 @@ add_qtc_plugin(CMakeProjectManager
cmakeformatteroptionspage.cpp cmakeformatteroptionspage.h
cmakeformattersettings.cpp cmakeformattersettings.h
cmakeindenter.cpp cmakeindenter.h
cmakeinstallstep.cpp cmakeinstallstep.h
cmakekitinformation.cpp cmakekitinformation.h
cmakelocatorfilter.cpp cmakelocatorfilter.h
cmakeparser.cpp cmakeparser.h

View File

@@ -0,0 +1,66 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "cmakeabstractprocessstep.h"
#include "cmakekitinformation.h"
#include "cmakeprojectmanagertr.h"
#include "cmaketool.h"
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/project.h>
#include <projectexplorer/target.h>
using namespace Core;
using namespace ProjectExplorer;
using namespace Utils;
namespace CMakeProjectManager::Internal {
// CMakeAbstractProcessStep
CMakeAbstractProcessStep::CMakeAbstractProcessStep(BuildStepList *bsl, Utils::Id id)
: AbstractProcessStep(bsl, id)
{}
bool CMakeAbstractProcessStep::init()
{
if (!AbstractProcessStep::init())
return false;
BuildConfiguration *bc = buildConfiguration();
QTC_ASSERT(bc, return false);
if (!bc->isEnabled()) {
emit addTask(
BuildSystemTask(Task::Error, Tr::tr("The build configuration is currently disabled.")));
emitFaultyConfigurationMessage();
return false;
}
CMakeTool *tool = CMakeKitAspect::cmakeTool(kit());
if (!tool || !tool->isValid()) {
emit addTask(BuildSystemTask(Task::Error,
Tr::tr("A CMake tool must be set up for building. "
"Configure a CMake tool in the kit options.")));
emitFaultyConfigurationMessage();
return false;
}
// Warn if doing out-of-source builds with a CMakeCache.txt is the source directory
const Utils::FilePath projectDirectory = bc->target()->project()->projectDirectory();
if (bc->buildDirectory() != projectDirectory) {
if (projectDirectory.pathAppended("CMakeCache.txt").exists()) {
emit addTask(BuildSystemTask(
Task::Warning,
Tr::tr("There is a CMakeCache.txt file in \"%1\", which suggest an "
"in-source build was done before. You are now building in \"%2\", "
"and the CMakeCache.txt file might confuse CMake.")
.arg(projectDirectory.toUserOutput(), bc->buildDirectory().toUserOutput())));
}
}
return true;
}
} // namespace CMakeProjectManager::Internal

View File

@@ -0,0 +1,21 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#pragma once
#include <projectexplorer/abstractprocessstep.h>
namespace CMakeProjectManager::Internal {
class CMakeAbstractProcessStep : public ProjectExplorer::AbstractProcessStep
{
Q_OBJECT
public:
CMakeAbstractProcessStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
protected:
bool init() override;
};
} // namespace CMakeProjectManager::Internal

View File

@@ -156,7 +156,7 @@ Qt::ItemFlags CMakeTargetItem::flags(int) const
// CMakeBuildStep
CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, Utils::Id id) :
AbstractProcessStep(bsl, id)
CMakeAbstractProcessStep(bsl, id)
{
m_cmakeArguments = addAspect<StringAspect>();
m_cmakeArguments->setSettingsKey(CMAKE_ARGUMENTS_KEY);
@@ -212,7 +212,7 @@ CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, Utils::Id id) :
QVariantMap CMakeBuildStep::toMap() const
{
QVariantMap map(AbstractProcessStep::toMap());
QVariantMap map(CMakeAbstractProcessStep::toMap());
map.insert(BUILD_TARGETS_KEY, m_buildTargets);
map.insert(QLatin1String(CLEAR_SYSTEM_ENVIRONMENT_KEY), m_clearSystemEnvironment);
map.insert(QLatin1String(USER_ENVIRONMENT_CHANGES_KEY), EnvironmentItem::toStringList(m_userEnvironmentChanges));
@@ -239,28 +239,9 @@ bool CMakeBuildStep::fromMap(const QVariantMap &map)
bool CMakeBuildStep::init()
{
if (!AbstractProcessStep::init())
if (!CMakeAbstractProcessStep::init())
return false;
BuildConfiguration *bc = buildConfiguration();
QTC_ASSERT(bc, return false);
if (!bc->isEnabled()) {
emit addTask(BuildSystemTask(Task::Error,
Tr::tr("The build configuration is currently disabled.")));
emitFaultyConfigurationMessage();
return false;
}
CMakeTool *tool = CMakeKitAspect::cmakeTool(kit());
if (!tool || !tool->isValid()) {
emit addTask(BuildSystemTask(Task::Error,
Tr::tr("A CMake tool must be set up for building. "
"Configure a CMake tool in the kit options.")));
emitFaultyConfigurationMessage();
return false;
}
if (m_buildTargets.contains(QString())) {
RunConfiguration *rc = target()->activeRunConfiguration();
if (!rc || rc->buildKey().isEmpty()) {
@@ -274,18 +255,6 @@ bool CMakeBuildStep::init()
}
}
// Warn if doing out-of-source builds with a CMakeCache.txt is the source directory
const Utils::FilePath projectDirectory = bc->target()->project()->projectDirectory();
if (bc->buildDirectory() != projectDirectory) {
if (projectDirectory.pathAppended("CMakeCache.txt").exists()) {
emit addTask(BuildSystemTask(Task::Warning,
Tr::tr("There is a CMakeCache.txt file in \"%1\", which suggest an "
"in-source build was done before. You are now building in \"%2\", "
"and the CMakeCache.txt file might confuse CMake.")
.arg(projectDirectory.toUserOutput(), bc->buildDirectory().toUserOutput())));
}
}
setIgnoreReturnValue(m_buildTargets == QStringList(CMakeBuildStep::cleanTarget()));
return true;
@@ -313,7 +282,7 @@ void CMakeBuildStep::setupOutputFormatter(Utils::OutputFormatter *formatter)
p->setRedirectionDetector(progressParser);
formatter->addLineParsers(additionalParsers);
formatter->addSearchDir(processParameters()->effectiveWorkingDirectory());
AbstractProcessStep::setupOutputFormatter(formatter);
CMakeAbstractProcessStep::setupOutputFormatter(formatter);
}
void CMakeBuildStep::doRun()
@@ -337,7 +306,7 @@ void CMakeBuildStep::doRun()
void CMakeBuildStep::runImpl()
{
// Do the actual build:
AbstractProcessStep::doRun();
CMakeAbstractProcessStep::doRun();
}
void CMakeBuildStep::handleProjectWasParsed(bool success)

View File

@@ -3,7 +3,7 @@
#pragma once
#include <projectexplorer/abstractprocessstep.h>
#include "cmakeabstractprocessstep.h"
#include <utils/treemodel.h>
namespace Utils {
@@ -31,7 +31,7 @@ private:
bool m_special = false;
};
class CMakeBuildStep : public ProjectExplorer::AbstractProcessStep
class CMakeBuildStep : public CMakeAbstractProcessStep
{
Q_OBJECT

View File

@@ -0,0 +1,123 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "cmakeinstallstep.h"
#include "cmakebuildsystem.h"
#include "cmakekitinformation.h"
#include "cmakeparser.h"
#include "cmakeprojectconstants.h"
#include "cmakeprojectmanagertr.h"
#include "cmaketool.h"
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/processparameters.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/layoutbuilder.h>
using namespace Core;
using namespace ProjectExplorer;
using namespace Utils;
namespace CMakeProjectManager::Internal {
const char CMAKE_ARGUMENTS_KEY[] = "CMakeProjectManager.InstallStep.CMakeArguments";
// CMakeInstallStep
CMakeInstallStep::CMakeInstallStep(BuildStepList *bsl, Utils::Id id)
: CMakeAbstractProcessStep(bsl, id)
{
m_cmakeArguments = addAspect<StringAspect>();
m_cmakeArguments->setSettingsKey(CMAKE_ARGUMENTS_KEY);
m_cmakeArguments->setLabelText(Tr::tr("CMake arguments:"));
m_cmakeArguments->setDisplayStyle(StringAspect::LineEditDisplay);
setCommandLineProvider([this] { return cmakeCommand(); });
}
void CMakeInstallStep::setupOutputFormatter(Utils::OutputFormatter *formatter)
{
CMakeParser *cmakeParser = new CMakeParser;
cmakeParser->setSourceDirectory(project()->projectDirectory());
formatter->addLineParsers({cmakeParser});
formatter->addSearchDir(processParameters()->effectiveWorkingDirectory());
CMakeAbstractProcessStep::setupOutputFormatter(formatter);
}
CommandLine CMakeInstallStep::cmakeCommand() const
{
CommandLine cmd;
if (CMakeTool *tool = CMakeKitAspect::cmakeTool(kit()))
cmd.setExecutable(tool->cmakeExecutable());
FilePath buildDirectory = ".";
if (buildConfiguration())
buildDirectory = buildConfiguration()->buildDirectory();
cmd.addArgs({"--install", buildDirectory.onDevice(cmd.executable()).path()});
auto bs = qobject_cast<CMakeBuildSystem *>(buildSystem());
if (bs && bs->isMultiConfigReader()) {
cmd.addArg("--config");
cmd.addArg(bs->cmakeBuildType());
}
if (!m_cmakeArguments->value().isEmpty())
cmd.addArgs(m_cmakeArguments->value(), CommandLine::Raw);
return cmd;
}
void CMakeInstallStep::processFinished(bool success)
{
Q_UNUSED(success)
emit progress(100, {});
}
QWidget *CMakeInstallStep::createConfigWidget()
{
auto updateDetails = [this] {
ProcessParameters param;
setupProcessParameters(&param);
param.setCommandLine(cmakeCommand());
setSummaryText(param.summary(displayName()));
};
setDisplayName(Tr::tr("Install", "ConfigWidget display name."));
Layouting::Form builder;
builder.addRow(m_cmakeArguments);
auto widget = builder.emerge(Layouting::WithoutMargins);
updateDetails();
connect(m_cmakeArguments, &StringAspect::changed, this, updateDetails);
connect(ProjectExplorerPlugin::instance(),
&ProjectExplorerPlugin::settingsChanged,
this,
updateDetails);
connect(buildConfiguration(), &BuildConfiguration::buildDirectoryChanged, this, updateDetails);
connect(buildConfiguration(), &BuildConfiguration::buildTypeChanged, this, updateDetails);
return widget;
}
// CMakeInstallStepFactory
CMakeInstallStepFactory::CMakeInstallStepFactory()
{
registerStep<CMakeInstallStep>(Constants::CMAKE_INSTALL_STEP_ID);
setDisplayName(
Tr::tr("CMake Install", "Display name for CMakeProjectManager::CMakeInstallStep id."));
setSupportedProjectType(Constants::CMAKE_PROJECT_ID);
setSupportedStepLists({ProjectExplorer::Constants::BUILDSTEPS_DEPLOY});
}
} // namespace CMakeProjectManager::Internal

View File

@@ -0,0 +1,40 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#pragma once
#include "cmakeabstractprocessstep.h"
namespace Utils {
class CommandLine;
class StringAspect;
} // namespace Utils
namespace CMakeProjectManager::Internal {
class CMakeInstallStep : public CMakeAbstractProcessStep
{
Q_OBJECT
public:
CMakeInstallStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
private:
Utils::CommandLine cmakeCommand() const;
void processFinished(bool success) override;
void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
QWidget *createConfigWidget() override;
friend class CMakeInstallStepConfigWidget;
Utils::StringAspect *m_cmakeArguments = nullptr;
};
class CMakeInstallStepFactory : public ProjectExplorer::BuildStepFactory
{
public:
CMakeInstallStepFactory();
};
} // namespace CMakeProjectManager::Internal

View File

@@ -304,7 +304,7 @@ QSet<Id> CMakeKitAspect::availableFeatures(const Kit *k) const
QString CMakeKitAspect::msgUnsupportedVersion(const QByteArray &versionString)
{
return Tr::tr("CMake version %1 is unsupported. Update to "
"version 3.14 (with file-api) or later.")
"version 3.15 (with file-api) or later.")
.arg(QString::fromUtf8(versionString));
}

View File

@@ -52,6 +52,10 @@ const char BUILD_TARGET_CONTEXT_MENU[] = "CMake.BuildTargetContextMenu";
// Build Step
const char CMAKE_BUILD_STEP_ID[] = "CMakeProjectManager.MakeStep";
// Install Step
const char CMAKE_INSTALL_STEP_ID[] = "CMakeProjectManager.InstallStep";
// Features
const char CMAKE_FEATURE_ID[] = "CMakeProjectManager.Wizard.FeatureCMake";

View File

@@ -18,6 +18,8 @@ QtcPlugin {
"builddirparameters.cpp",
"builddirparameters.h",
"cmake_global.h",
"cmakeabstractprocessstep.cpp",
"cmakeabstractprocessstep.h",
"cmakebuildconfiguration.cpp",
"cmakebuildconfiguration.h",
"cmakebuildstep.cpp",
@@ -37,6 +39,8 @@ QtcPlugin {
"cmakeformatteroptionspage.h",
"cmakeformattersettings.cpp",
"cmakeformattersettings.h",
"cmakeinstallstep.cpp",
"cmakeinstallstep.h",
"cmakekitinformation.h",
"cmakekitinformation.cpp",
"cmakelocatorfilter.cpp",

View File

@@ -9,6 +9,7 @@
#include "cmakeeditor.h"
#include "cmakeformatter.h"
#include "cmakeformattersettings.h"
#include "cmakeinstallstep.h"
#include "cmakekitinformation.h"
#include "cmakelocatorfilter.h"
#include "cmakeproject.h"
@@ -79,6 +80,7 @@ public:
CMakeBuildStepFactory buildStepFactory;
CMakeBuildConfigurationFactory buildConfigFactory;
CMakeEditorFactory editorFactor;
CMakeInstallStepFactory installStepFactory;
BuildCMakeTargetLocatorFilter buildCMakeTargetLocatorFilter;
OpenCMakeTargetLocatorFilter openCMakeTargetLocationFilter;

View File

@@ -565,13 +565,6 @@ void CMakeTool::parseFromCapabilities(const QString &input) const
m_introspection->m_version.minor = versionInfo.value("minor").toInt();
m_introspection->m_version.patch = versionInfo.value("patch").toInt();
m_introspection->m_version.fullVersion = versionInfo.value("string").toByteArray();
// Fix up fileapi support for cmake 3.14:
if (m_introspection->m_version.major == 3 && m_introspection->m_version.minor == 14) {
m_introspection->m_fileApis.append({QString("codemodel"), {2, 0}});
m_introspection->m_fileApis.append({QString("cache"), {2, 0}});
m_introspection->m_fileApis.append({QString("cmakefiles"), {1, 0}});
}
}
} // namespace CMakeProjectManager