aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/cmakeprojectmanager/cmakebuildstep.cpp')
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildstep.cpp124
1 files changed, 112 insertions, 12 deletions
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
index ccb21ccfb3e..2d2501ab03b 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
@@ -31,6 +31,7 @@
#include <utils/layoutbuilder.h>
#include <QListWidget>
+#include <QRandomGenerator>
#include <QRegularExpression>
#include <QTreeView>
#include <QCheckBox>
@@ -44,6 +45,8 @@ namespace CMakeProjectManager::Internal {
const char BUILD_TARGETS_KEY[] = "CMakeProjectManager.MakeStep.BuildTargets";
const char CMAKE_ARGUMENTS_KEY[] = "CMakeProjectManager.MakeStep.CMakeArguments";
const char TOOL_ARGUMENTS_KEY[] = "CMakeProjectManager.MakeStep.AdditionalArguments";
+const char USE_STAGING_KEY[] = "CMakeProjectManager.MakeStep.UseStaging";
+const char STAGING_DIR_KEY[] = "CMakeProjectManager.MakeStep.StagingDir";
const char IOS_AUTOMATIC_PROVISIONG_UPDATES_ARGUMENTS_KEY[] =
"CMakeProjectManager.MakeStep.iOSAutomaticProvisioningUpdates";
const char CLEAR_SYSTEM_ENVIRONMENT_KEY[] = "CMakeProjectManager.MakeStep.ClearSystemEnvironment";
@@ -156,7 +159,27 @@ Qt::ItemFlags CMakeTargetItem::flags(int) const
// CMakeBuildStep
-CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, Utils::Id id) :
+static QString initialStagingDir()
+{
+ // Avoid actual file accesses.
+ auto rg = QRandomGenerator::global();
+ const qulonglong rand = rg->generate64();
+ char buf[sizeof(rand)];
+ memcpy(&buf, &rand, sizeof(rand));
+ const QByteArray ba = QByteArray(buf, sizeof(buf)).toHex();
+ return QString::fromUtf8("/tmp/Qt-Creator-staging-" + ba);
+}
+
+static bool buildAndRunOnSameDevice(Kit *kit)
+{
+ IDeviceConstPtr runDevice = DeviceKitAspect::device(kit);
+ IDeviceConstPtr buildDevice = BuildDeviceKitAspect::device(kit);
+ QTC_ASSERT(runDevice, return false);
+ QTC_ASSERT(buildDevice, return false);
+ return runDevice->id() == buildDevice->id();
+}
+
+CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, Id id) :
CMakeAbstractProcessStep(bsl, id)
{
m_cmakeArguments = addAspect<StringAspect>();
@@ -169,6 +192,16 @@ CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, Utils::Id id) :
m_toolArguments->setLabelText(Tr::tr("Tool arguments:"));
m_toolArguments->setDisplayStyle(StringAspect::LineEditDisplay);
+ m_useStaging = addAspect<BoolAspect>();
+ m_useStaging->setSettingsKey(USE_STAGING_KEY);
+ m_useStaging->setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBox);
+ m_useStaging->setDefaultValue(!buildAndRunOnSameDevice(kit()));
+
+ m_stagingDir = addAspect<FilePathAspect>();
+ m_stagingDir->setSettingsKey(STAGING_DIR_KEY);
+ m_stagingDir->setLabelText(Tr::tr("Staging directory:"));
+ m_stagingDir->setDefaultValue(initialStagingDir());
+
Kit *kit = buildConfiguration()->kit();
if (CMakeBuildConfiguration::isIos(kit)) {
m_useiOSAutomaticProvisioningUpdates = addAspect<BoolAspect>();
@@ -199,6 +232,9 @@ CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, Utils::Id id) :
if (!env.expandedValueForKey("NINJA_STATUS").startsWith(ninjaProgressString))
env.set("NINJA_STATUS", ninjaProgressString + "%o/sec] ");
env.modify(m_userEnvironmentChanges);
+
+ if (m_useStaging)
+ env.set("DESTDIR", currentStagingDir());
});
connect(target(), &Target::parsingFinished, this, [this](bool success) {
@@ -210,7 +246,6 @@ CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, Utils::Id id) :
this, &CMakeBuildStep::updateBuildTargetsModel);
}
-
QVariantMap CMakeBuildStep::toMap() const
{
QVariantMap map(CMakeAbstractProcessStep::toMap());
@@ -375,15 +410,13 @@ void CMakeBuildStep::setBuildTargets(const QStringList &buildTargets)
CommandLine CMakeBuildStep::cmakeCommand() const
{
- CommandLine cmd;
- if (CMakeTool *tool = CMakeKitAspect::cmakeTool(kit()))
- cmd.setExecutable(tool->cmakeExecutable());
+ CommandLine cmd{cmakeExecutable()};
FilePath buildDirectory = ".";
if (buildConfiguration())
buildDirectory = buildConfiguration()->buildDirectory();
- cmd.addArgs({"--build", buildDirectory.onDevice(cmd.executable()).path()});
+ cmd.addArgs({"--build", buildDirectory.path()});
cmd.addArg("--target");
cmd.addArgs(Utils::transform(m_buildTargets, [this](const QString &s) {
@@ -406,6 +439,9 @@ CommandLine CMakeBuildStep::cmakeCommand() const
if (!m_cmakeArguments->value().isEmpty())
cmd.addArgs(m_cmakeArguments->value(), CommandLine::Raw);
+ if (m_useStaging->value())
+ cmd.addArg("install");
+
bool toolArgumentsSpecified = false;
if (!m_toolArguments->value().isEmpty()) {
cmd.addArg("--");
@@ -466,6 +502,12 @@ QWidget *CMakeBuildStep::createConfigWidget()
QString summaryText = param.summary(displayName());
+ m_stagingDir->setEnabled(m_useStaging->value());
+ if (m_useStaging->value()) {
+ summaryText.append(" " + Tr::tr("and stage at %2 for %3")
+ .arg(currentStagingDir(), currentInstallPrefix()));
+ }
+
if (!m_buildPreset.isEmpty()) {
const CMakeProject *cp = static_cast<const CMakeProject *>(project());
@@ -519,28 +561,32 @@ QWidget *CMakeBuildStep::createConfigWidget()
envWidget->setBaseEnvironmentText(baseEnvironmentText());
});
- builder.addRow(clearBox);
- builder.addRow(envWidget);
+ builder.addRow({clearBox});
+ builder.addRow({envWidget});
};
Layouting::Form builder;
- builder.addRow(m_cmakeArguments);
- builder.addRow(m_toolArguments);
+ builder.addRow({m_cmakeArguments});
+ builder.addRow({m_toolArguments});
+ builder.addRow({Tr::tr("Stage for installation:"), Layouting::Row{m_useStaging, m_stagingDir}});
if (m_useiOSAutomaticProvisioningUpdates)
- builder.addRow(m_useiOSAutomaticProvisioningUpdates);
+ builder.addRow({m_useiOSAutomaticProvisioningUpdates});
builder.addRow({new QLabel(Tr::tr("Targets:")), frame});
if (!isCleanStep() && !m_buildPreset.isEmpty())
createAndAddEnvironmentWidgets(builder);
- auto widget = builder.emerge(Layouting::WithoutMargins);
+ builder.addItem(Layouting::noMargin);
+ auto widget = builder.emerge();
updateDetails();
connect(m_cmakeArguments, &StringAspect::changed, this, updateDetails);
connect(m_toolArguments, &StringAspect::changed, this, updateDetails);
+ connect(m_useStaging, &BoolAspect::changed, this, updateDetails);
+ connect(m_stagingDir, &StringAspect::changed, this, updateDetails);
if (m_useiOSAutomaticProvisioningUpdates)
connect(m_useiOSAutomaticProvisioningUpdates, &BoolAspect::changed, this, updateDetails);
@@ -683,8 +729,62 @@ QString CMakeBuildStep::baseEnvironmentText() const
return Tr::tr("System Environment");
}
+QString CMakeBuildStep::currentInstallPrefix() const
+{
+ auto bs = qobject_cast<CMakeBuildSystem *>(buildSystem());
+ QTC_ASSERT(bs, return {});
+ const CMakeConfig config = bs->configurationFromCMake();
+ return QString::fromUtf8(config.valueOf("CMAKE_INSTALL_PREFIX"));
+}
+
+QString CMakeBuildStep::currentStagingDir() const
+{
+ return m_stagingDir->filePath().path();
+}
+
+FilePath CMakeBuildStep::cmakeExecutable() const
+{
+ CMakeTool *tool = CMakeKitAspect::cmakeTool(kit());
+ return tool ? tool->cmakeExecutable() : FilePath();
+}
+
+void CMakeBuildStep::updateDeploymentData()
+{
+ if (!m_useStaging->value())
+ return;
+
+ QString install = currentInstallPrefix();
+ QString stagingDir = currentStagingDir();
+ FilePath rootDir = cmakeExecutable().withNewPath(stagingDir);
+ Q_UNUSED(install);
+
+ DeploymentData deploymentData;
+ deploymentData.setLocalInstallRoot(rootDir);
+
+ const int startPos = rootDir.path().length();
+
+ const auto appFileNames = transform<QSet<QString>>(buildSystem()->applicationTargets(),
+ [](const BuildTargetInfo &appTarget) { return appTarget.targetFilePath.fileName(); });
+
+ auto handleFile = [&appFileNames, startPos, &deploymentData](const FilePath &filePath) {
+ const DeployableFile::Type type = appFileNames.contains(filePath.fileName())
+ ? DeployableFile::TypeExecutable
+ : DeployableFile::TypeNormal;
+ const QString targetDir = filePath.parentDir().path().mid(startPos);
+ deploymentData.addFile(filePath, targetDir, type);
+ return IterationPolicy::Continue;
+ };
+
+ rootDir.iterateDirectory(handleFile,
+ {{}, QDir::Files | QDir::Hidden, QDirIterator::Subdirectories});
+
+ buildSystem()->setDeploymentData(deploymentData);
+}
+
void CMakeBuildStep::finish(ProcessResult result)
{
+ updateDeploymentData();
+
emit progress(100, {});
AbstractProcessStep::finish(result);
}