2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2010-01-14 17:41:29 +01:00
|
|
|
|
2016-01-07 12:33:52 +01:00
|
|
|
#include "cmakebuildstep.h"
|
2010-01-14 17:41:29 +01:00
|
|
|
|
2013-07-10 21:43:49 +03:00
|
|
|
#include "cmakebuildconfiguration.h"
|
2019-10-25 09:55:32 +02:00
|
|
|
#include "cmakebuildsystem.h"
|
2023-08-21 17:20:02 +02:00
|
|
|
#include "cmakekitaspect.h"
|
2013-07-10 21:43:49 +03:00
|
|
|
#include "cmakeparser.h"
|
2022-09-05 20:09:12 +02:00
|
|
|
#include "cmakeproject.h"
|
2008-12-04 13:06:02 +01:00
|
|
|
#include "cmakeprojectconstants.h"
|
2022-09-29 15:26:31 +02:00
|
|
|
#include "cmakeprojectmanagertr.h"
|
2016-01-07 13:15:29 +01:00
|
|
|
#include "cmaketool.h"
|
2024-01-31 09:49:56 +01:00
|
|
|
#include "cmaketoolmanager.h"
|
2008-12-04 13:06:02 +01:00
|
|
|
|
2023-06-16 21:47:39 +02:00
|
|
|
#include <android/androidconstants.h>
|
|
|
|
|
|
2023-08-14 16:39:02 +02:00
|
|
|
#include <baremetal/baremetalconstants.h>
|
|
|
|
|
|
2023-06-16 21:47:39 +02:00
|
|
|
#include <ios/iosconstants.h>
|
|
|
|
|
|
2023-07-13 19:36:33 +02:00
|
|
|
#include <webassembly/webassemblyconstants.h>
|
|
|
|
|
|
2020-04-17 15:30:05 +02:00
|
|
|
#include <coreplugin/find/itemviewfind.h>
|
2010-07-16 14:00:41 +02:00
|
|
|
#include <projectexplorer/buildsteplist.h>
|
2022-09-05 20:09:12 +02:00
|
|
|
#include <projectexplorer/devicesupport/idevice.h>
|
|
|
|
|
#include <projectexplorer/environmentwidget.h>
|
2016-02-12 12:34:35 +01:00
|
|
|
#include <projectexplorer/gnumakeparser.h>
|
2023-08-11 09:18:56 +02:00
|
|
|
#include <projectexplorer/kitaspects.h>
|
2018-11-17 21:19:04 +02:00
|
|
|
#include <projectexplorer/processparameters.h>
|
2020-04-17 15:30:05 +02:00
|
|
|
#include <projectexplorer/project.h>
|
2013-07-10 21:43:49 +03:00
|
|
|
#include <projectexplorer/projectexplorer.h>
|
2022-06-22 15:43:33 +02:00
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
2023-02-09 11:43:49 +01:00
|
|
|
#include <projectexplorer/projectexplorertr.h>
|
2020-04-17 15:30:05 +02:00
|
|
|
#include <projectexplorer/runconfiguration.h>
|
2012-04-24 15:49:09 +02:00
|
|
|
#include <projectexplorer/target.h>
|
2021-11-15 15:11:43 +01:00
|
|
|
#include <projectexplorer/xcodebuildparser.h>
|
2021-05-31 11:28:12 +00:00
|
|
|
|
2020-06-02 19:37:25 +02:00
|
|
|
#include <utils/algorithm.h>
|
2020-09-18 12:11:40 +02:00
|
|
|
#include <utils/layoutbuilder.h>
|
2020-06-02 19:37:25 +02:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QListWidget>
|
2023-04-05 14:16:00 +02:00
|
|
|
#include <QRandomGenerator>
|
2020-07-30 13:16:43 +02:00
|
|
|
#include <QRegularExpression>
|
2020-09-10 17:01:32 +02:00
|
|
|
#include <QTreeView>
|
2022-09-05 20:09:12 +02:00
|
|
|
#include <QCheckBox>
|
2008-12-09 15:25:01 +01:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
using namespace Core;
|
2009-10-27 14:16:28 +01:00
|
|
|
using namespace ProjectExplorer;
|
2023-08-17 11:08:21 +02:00
|
|
|
using namespace Tasking;
|
2020-08-13 16:48:44 +02:00
|
|
|
using namespace Utils;
|
2008-12-04 13:06:02 +01:00
|
|
|
|
2022-09-29 15:26:31 +02:00
|
|
|
namespace CMakeProjectManager::Internal {
|
2020-02-20 18:04:36 +01:00
|
|
|
|
2012-08-03 15:24:33 +02:00
|
|
|
const char BUILD_TARGETS_KEY[] = "CMakeProjectManager.MakeStep.BuildTargets";
|
2020-06-02 17:23:47 +02:00
|
|
|
const char CMAKE_ARGUMENTS_KEY[] = "CMakeProjectManager.MakeStep.CMakeArguments";
|
2016-01-07 13:15:29 +01:00
|
|
|
const char TOOL_ARGUMENTS_KEY[] = "CMakeProjectManager.MakeStep.AdditionalArguments";
|
2023-04-05 14:16:00 +02:00
|
|
|
const char USE_STAGING_KEY[] = "CMakeProjectManager.MakeStep.UseStaging";
|
|
|
|
|
const char STAGING_DIR_KEY[] = "CMakeProjectManager.MakeStep.StagingDir";
|
CMake: iOS: Enable automatic provisioning updates
By default xcodebuild does not try create / download a provisioning
profile for a project if a valid one does not exist locally
in ~/Library/MobileDevice/Provisioning Profiles, even if the
Xcode CODE_SIGN_STYLE attribute is set to Automatic.
Starting with Xcode 9, xcodebuild accepts a new
-allowProvisioningUpdates option.
When passed, xcodebuild will request a new provisioning profile
from Apple's servers for the current project and use it during
the build. The provisioning profile is only needed when building
for a real device, not the simulator.
When building an iOS project with qmake, the option is embedded in the
wrapping Makefile generated by qmake, so Qt Creator can simply call
make (which it does).
For CMake, there is no wrapping Makefile, so we need to pass the new
option explicitly as an additional build tool argument.
There might be cases where automatic provisioning is not desired,
which is why there is now a new checkbox in the CMake build step
configuration widget. It's default value is 'enabled', to match
qmake's behavior.
As an implementation detail, isiOS had to be moved to a header file so
it's accessible to both the build configuration and the build step.
Fixes: QTCREATORBUG-26246
Change-Id: Ic80cd965ba095d0ff379e13ad2ffb8c298c9f7c4
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-05-05 16:26:11 +02:00
|
|
|
const char IOS_AUTOMATIC_PROVISIONG_UPDATES_ARGUMENTS_KEY[] =
|
|
|
|
|
"CMakeProjectManager.MakeStep.iOSAutomaticProvisioningUpdates";
|
2022-09-05 20:09:12 +02:00
|
|
|
const char CLEAR_SYSTEM_ENVIRONMENT_KEY[] = "CMakeProjectManager.MakeStep.ClearSystemEnvironment";
|
|
|
|
|
const char USER_ENVIRONMENT_CHANGES_KEY[] = "CMakeProjectManager.MakeStep.UserEnvironmentChanges";
|
|
|
|
|
const char BUILD_PRESET_KEY[] = "CMakeProjectManager.MakeStep.BuildPreset";
|
2020-09-10 17:01:32 +02:00
|
|
|
|
2023-08-17 11:08:21 +02:00
|
|
|
class ProjectParserTaskAdapter : public TaskAdapter<QPointer<Target>>
|
2023-07-12 08:54:53 +02:00
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
void start() final {
|
|
|
|
|
Target *target = *task();
|
|
|
|
|
if (!target) {
|
2023-11-15 10:33:31 +01:00
|
|
|
emit done(DoneResult::Error);
|
2023-07-12 08:54:53 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2023-11-15 10:33:31 +01:00
|
|
|
connect(target, &Target::parsingFinished, this, [this](bool success) {
|
|
|
|
|
emit done(toDoneResult(success));
|
|
|
|
|
});
|
2023-07-12 08:54:53 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-17 11:08:21 +02:00
|
|
|
using ProjectParserTask = CustomTask<ProjectParserTaskAdapter>;
|
2020-02-20 18:04:36 +01:00
|
|
|
|
2020-07-30 13:16:43 +02:00
|
|
|
class CmakeProgressParser : public Utils::OutputLineParser
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
signals:
|
|
|
|
|
void progress(int percentage);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Result handleLine(const QString &line, Utils::OutputFormat format) override
|
|
|
|
|
{
|
|
|
|
|
if (format != Utils::StdOutFormat)
|
|
|
|
|
return Status::NotHandled;
|
|
|
|
|
|
|
|
|
|
static const QRegularExpression percentProgress("^\\[\\s*(\\d*)%\\]");
|
|
|
|
|
static const QRegularExpression ninjaProgress("^\\[\\s*(\\d*)/\\s*(\\d*)");
|
|
|
|
|
|
|
|
|
|
QRegularExpressionMatch match = percentProgress.match(line);
|
|
|
|
|
if (match.hasMatch()) {
|
|
|
|
|
bool ok = false;
|
|
|
|
|
const int percent = match.captured(1).toInt(&ok);
|
|
|
|
|
if (ok)
|
|
|
|
|
emit progress(percent);
|
|
|
|
|
return Status::Done;
|
|
|
|
|
}
|
|
|
|
|
match = ninjaProgress.match(line);
|
|
|
|
|
if (match.hasMatch()) {
|
|
|
|
|
m_useNinja = true;
|
|
|
|
|
bool ok = false;
|
|
|
|
|
const int done = match.captured(1).toInt(&ok);
|
|
|
|
|
if (ok) {
|
|
|
|
|
const int all = match.captured(2).toInt(&ok);
|
|
|
|
|
if (ok && all != 0) {
|
|
|
|
|
const int percent = static_cast<int>(100.0 * done / all);
|
|
|
|
|
emit progress(percent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Status::Done;
|
|
|
|
|
}
|
|
|
|
|
return Status::NotHandled;
|
|
|
|
|
}
|
|
|
|
|
bool hasDetectedRedirection() const override { return m_useNinja; }
|
|
|
|
|
|
|
|
|
|
// TODO: Shouldn't we know the backend in advance? Then we could merge this class
|
|
|
|
|
// with CmakeParser.
|
|
|
|
|
bool m_useNinja = false;
|
|
|
|
|
};
|
|
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
|
|
|
|
|
// CmakeTargetItem
|
|
|
|
|
|
|
|
|
|
CMakeTargetItem::CMakeTargetItem(const QString &target, CMakeBuildStep *step, bool special)
|
|
|
|
|
: m_target(target), m_step(step), m_special(special)
|
2020-02-20 18:04:36 +01:00
|
|
|
{
|
2020-09-10 17:01:32 +02:00
|
|
|
}
|
2020-02-20 18:04:36 +01:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
QVariant CMakeTargetItem::data(int column, int role) const
|
|
|
|
|
{
|
|
|
|
|
if (column == 0) {
|
|
|
|
|
if (role == Qt::DisplayRole) {
|
|
|
|
|
if (m_target.isEmpty())
|
2022-09-29 15:26:31 +02:00
|
|
|
return Tr::tr("Current executable");
|
2020-09-10 17:01:32 +02:00
|
|
|
return m_target;
|
|
|
|
|
}
|
2020-02-20 18:04:36 +01:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
if (role == Qt::ToolTipRole) {
|
|
|
|
|
if (m_target.isEmpty()) {
|
2022-09-29 15:26:31 +02:00
|
|
|
return Tr::tr("Build the executable used in the active run "
|
2020-09-10 17:01:32 +02:00
|
|
|
"configuration. Currently: %1")
|
|
|
|
|
.arg(m_step->activeRunConfigTarget());
|
|
|
|
|
}
|
2022-09-29 15:26:31 +02:00
|
|
|
return Tr::tr("Target: %1").arg(m_target);
|
2020-09-10 17:01:32 +02:00
|
|
|
}
|
2020-02-20 18:04:36 +01:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
if (role == Qt::CheckStateRole)
|
|
|
|
|
return m_step->buildsBuildTarget(m_target) ? Qt::Checked : Qt::Unchecked;
|
2010-01-14 17:41:29 +01:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
if (role == Qt::FontRole) {
|
|
|
|
|
if (m_special) {
|
|
|
|
|
QFont italics;
|
|
|
|
|
italics.setItalic(true);
|
|
|
|
|
return italics;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return QVariant();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CMakeTargetItem::setData(int column, const QVariant &data, int role)
|
2016-04-22 15:54:16 +02:00
|
|
|
{
|
2020-09-10 17:01:32 +02:00
|
|
|
if (column == 0 && role == Qt::CheckStateRole) {
|
|
|
|
|
m_step->setBuildsBuildTarget(m_target, data.value<Qt::CheckState>() == Qt::Checked);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return TreeItem::setData(column, data, role);
|
2016-04-22 15:54:16 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
Qt::ItemFlags CMakeTargetItem::flags(int) const
|
|
|
|
|
{
|
|
|
|
|
return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CMakeBuildStep
|
|
|
|
|
|
2023-06-14 15:59:25 +02:00
|
|
|
static QString initialStagingDir(Kit *kit)
|
2023-04-05 14:16:00 +02:00
|
|
|
{
|
|
|
|
|
// 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();
|
2023-06-14 15:59:25 +02:00
|
|
|
IDeviceConstPtr buildDevice = BuildDeviceKitAspect::device(kit);
|
|
|
|
|
if (buildDevice && buildDevice->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
|
|
|
|
|
return TemporaryDirectory::masterDirectoryPath() + "/staging-" + ba;
|
2023-04-05 14:16:00 +02:00
|
|
|
return QString::fromUtf8("/tmp/Qt-Creator-staging-" + ba);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-16 21:47:39 +02:00
|
|
|
static bool supportsStageForInstallation(const Kit *kit)
|
2023-04-05 14:16:00 +02:00
|
|
|
{
|
|
|
|
|
IDeviceConstPtr runDevice = DeviceKitAspect::device(kit);
|
2023-08-23 11:51:30 +02:00
|
|
|
Id runDeviceType = DeviceTypeKitAspect::deviceTypeId(kit);
|
2023-04-05 14:16:00 +02:00
|
|
|
IDeviceConstPtr buildDevice = BuildDeviceKitAspect::device(kit);
|
2023-08-23 11:51:30 +02:00
|
|
|
QTC_ASSERT(runDeviceType.isValid(), return false);
|
2023-05-22 12:01:30 +02:00
|
|
|
QTC_ASSERT(buildDevice, return false);
|
2023-08-23 11:51:30 +02:00
|
|
|
return (!runDevice || runDevice->id() != buildDevice->id())
|
|
|
|
|
&& runDeviceType != Android::Constants::ANDROID_DEVICE_TYPE
|
|
|
|
|
&& runDeviceType != Ios::Constants::IOS_DEVICE_TYPE
|
|
|
|
|
&& runDeviceType != Ios::Constants::IOS_SIMULATOR_TYPE
|
|
|
|
|
&& runDeviceType != BareMetal::Constants::BareMetalOsType
|
|
|
|
|
&& runDeviceType != WebAssembly::Constants::WEBASSEMBLY_DEVICE_TYPE;
|
2023-04-05 14:16:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, Id id) :
|
2022-12-09 18:44:42 +01:00
|
|
|
CMakeAbstractProcessStep(bsl, id)
|
2010-01-14 17:41:29 +01:00
|
|
|
{
|
2023-07-13 16:21:49 +02:00
|
|
|
cmakeArguments.setSettingsKey(CMAKE_ARGUMENTS_KEY);
|
|
|
|
|
cmakeArguments.setLabelText(Tr::tr("CMake arguments:"));
|
|
|
|
|
cmakeArguments.setDisplayStyle(StringAspect::LineEditDisplay);
|
|
|
|
|
|
|
|
|
|
toolArguments.setSettingsKey(TOOL_ARGUMENTS_KEY);
|
|
|
|
|
toolArguments.setLabelText(Tr::tr("Tool arguments:"));
|
|
|
|
|
toolArguments.setDisplayStyle(StringAspect::LineEditDisplay);
|
|
|
|
|
|
|
|
|
|
useStaging.setSettingsKey(USE_STAGING_KEY);
|
|
|
|
|
useStaging.setLabel(Tr::tr("Stage for installation"), BoolAspect::LabelPlacement::AtCheckBox);
|
|
|
|
|
useStaging.setDefaultValue(supportsStageForInstallation(kit()));
|
|
|
|
|
|
|
|
|
|
stagingDir.setSettingsKey(STAGING_DIR_KEY);
|
|
|
|
|
stagingDir.setLabelText(Tr::tr("Staging directory:"));
|
2023-08-17 12:51:13 +02:00
|
|
|
stagingDir.setDefaultValue(initialStagingDir(kit()));
|
2023-12-07 08:35:57 +01:00
|
|
|
stagingDir.setExpectedKind(PathChooser::Kind::Directory);
|
2023-04-05 14:16:00 +02:00
|
|
|
|
CMake: iOS: Enable automatic provisioning updates
By default xcodebuild does not try create / download a provisioning
profile for a project if a valid one does not exist locally
in ~/Library/MobileDevice/Provisioning Profiles, even if the
Xcode CODE_SIGN_STYLE attribute is set to Automatic.
Starting with Xcode 9, xcodebuild accepts a new
-allowProvisioningUpdates option.
When passed, xcodebuild will request a new provisioning profile
from Apple's servers for the current project and use it during
the build. The provisioning profile is only needed when building
for a real device, not the simulator.
When building an iOS project with qmake, the option is embedded in the
wrapping Makefile generated by qmake, so Qt Creator can simply call
make (which it does).
For CMake, there is no wrapping Makefile, so we need to pass the new
option explicitly as an additional build tool argument.
There might be cases where automatic provisioning is not desired,
which is why there is now a new checkbox in the CMake build step
configuration widget. It's default value is 'enabled', to match
qmake's behavior.
As an implementation detail, isiOS had to be moved to a header file so
it's accessible to both the build configuration and the build step.
Fixes: QTCREATORBUG-26246
Change-Id: Ic80cd965ba095d0ff379e13ad2ffb8c298c9f7c4
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-05-05 16:26:11 +02:00
|
|
|
Kit *kit = buildConfiguration()->kit();
|
2024-01-19 15:08:32 +01:00
|
|
|
if (CMakeBuildConfiguration::isIos(kit) && CMakeGeneratorKitAspect::generator(kit) == "Xcode") {
|
2023-07-13 16:21:49 +02:00
|
|
|
useiOSAutomaticProvisioningUpdates.setDefaultValue(true);
|
|
|
|
|
useiOSAutomaticProvisioningUpdates.setSettingsKey(
|
|
|
|
|
IOS_AUTOMATIC_PROVISIONG_UPDATES_ARGUMENTS_KEY);
|
|
|
|
|
useiOSAutomaticProvisioningUpdates.setLabel(
|
|
|
|
|
Tr::tr("Enable automatic provisioning updates:"));
|
|
|
|
|
useiOSAutomaticProvisioningUpdates.setToolTip(
|
|
|
|
|
Tr::tr("Tells xcodebuild to create and download a provisioning profile "
|
|
|
|
|
"if a valid one does not exist."));
|
|
|
|
|
} else {
|
|
|
|
|
useiOSAutomaticProvisioningUpdates.setVisible(false);
|
CMake: iOS: Enable automatic provisioning updates
By default xcodebuild does not try create / download a provisioning
profile for a project if a valid one does not exist locally
in ~/Library/MobileDevice/Provisioning Profiles, even if the
Xcode CODE_SIGN_STYLE attribute is set to Automatic.
Starting with Xcode 9, xcodebuild accepts a new
-allowProvisioningUpdates option.
When passed, xcodebuild will request a new provisioning profile
from Apple's servers for the current project and use it during
the build. The provisioning profile is only needed when building
for a real device, not the simulator.
When building an iOS project with qmake, the option is embedded in the
wrapping Makefile generated by qmake, so Qt Creator can simply call
make (which it does).
For CMake, there is no wrapping Makefile, so we need to pass the new
option explicitly as an additional build tool argument.
There might be cases where automatic provisioning is not desired,
which is why there is now a new checkbox in the CMake build step
configuration widget. It's default value is 'enabled', to match
qmake's behavior.
As an implementation detail, isiOS had to be moved to a header file so
it's accessible to both the build configuration and the build step.
Fixes: QTCREATORBUG-26246
Change-Id: Ic80cd965ba095d0ff379e13ad2ffb8c298c9f7c4
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-05-05 16:26:11 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-29 15:26:31 +02:00
|
|
|
m_buildTargetModel.setHeader({Tr::tr("Target")});
|
2020-09-10 17:01:32 +02:00
|
|
|
|
|
|
|
|
setBuildTargets({defaultBuildTarget()});
|
2021-09-16 17:28:47 +02:00
|
|
|
auto *bs = qobject_cast<CMakeBuildSystem *>(buildSystem());
|
|
|
|
|
if (bs && !bs->buildTargets().isEmpty())
|
|
|
|
|
recreateBuildTargetsModel();
|
2017-04-26 15:34:04 +02:00
|
|
|
|
2019-10-09 21:29:12 +03:00
|
|
|
setLowPriority();
|
2019-09-10 23:39:29 +03:00
|
|
|
|
2020-09-14 17:17:55 +02:00
|
|
|
setCommandLineProvider([this] { return cmakeCommand(); });
|
|
|
|
|
|
2022-09-05 20:09:12 +02:00
|
|
|
setEnvironmentModifier([this](Environment &env) {
|
2020-08-13 16:48:44 +02:00
|
|
|
const QString ninjaProgressString = "[%f/%t "; // ninja: [33/100
|
2021-05-20 11:57:21 +02:00
|
|
|
env.setupEnglishOutput();
|
2020-08-13 16:48:44 +02:00
|
|
|
if (!env.expandedValueForKey("NINJA_STATUS").startsWith(ninjaProgressString))
|
|
|
|
|
env.set("NINJA_STATUS", ninjaProgressString + "%o/sec] ");
|
2022-09-05 20:09:12 +02:00
|
|
|
env.modify(m_userEnvironmentChanges);
|
2023-04-05 14:16:00 +02:00
|
|
|
|
2023-10-14 14:35:07 +02:00
|
|
|
env.setFallback("CLICOLOR_FORCE", "1");
|
|
|
|
|
|
2023-07-13 16:21:49 +02:00
|
|
|
if (useStaging())
|
|
|
|
|
env.set("DESTDIR", stagingDir().path());
|
2020-08-13 16:48:44 +02:00
|
|
|
});
|
|
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
connect(target(), &Target::parsingFinished, this, [this](bool success) {
|
|
|
|
|
if (success) // Do not change when parsing failed.
|
|
|
|
|
recreateBuildTargetsModel();
|
2020-06-02 19:37:25 +02:00
|
|
|
});
|
2020-09-10 17:01:32 +02:00
|
|
|
|
|
|
|
|
connect(target(), &Target::activeRunConfigurationChanged,
|
|
|
|
|
this, &CMakeBuildStep::updateBuildTargetsModel);
|
2013-08-26 16:01:24 +02:00
|
|
|
}
|
|
|
|
|
|
2023-08-23 16:53:06 +02:00
|
|
|
void CMakeBuildStep::toMap(Utils::Store &map) const
|
2009-10-15 19:06:51 +02:00
|
|
|
{
|
2023-07-21 17:44:01 +02:00
|
|
|
CMakeAbstractProcessStep::toMap(map);
|
2020-09-10 17:01:32 +02:00
|
|
|
map.insert(BUILD_TARGETS_KEY, m_buildTargets);
|
2023-08-24 16:14:26 +02:00
|
|
|
map.insert(CLEAR_SYSTEM_ENVIRONMENT_KEY, m_clearSystemEnvironment);
|
|
|
|
|
map.insert(USER_ENVIRONMENT_CHANGES_KEY, EnvironmentItem::toStringList(m_userEnvironmentChanges));
|
|
|
|
|
map.insert(BUILD_PRESET_KEY, m_buildPreset);
|
2009-10-15 19:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
2023-08-23 16:53:06 +02:00
|
|
|
void CMakeBuildStep::fromMap(const Utils::Store &map)
|
2009-10-15 19:06:51 +02:00
|
|
|
{
|
2020-09-10 17:01:32 +02:00
|
|
|
setBuildTargets(map.value(BUILD_TARGETS_KEY).toStringList());
|
2022-09-05 20:09:12 +02:00
|
|
|
|
2023-08-24 16:14:26 +02:00
|
|
|
m_clearSystemEnvironment = map.value(CLEAR_SYSTEM_ENVIRONMENT_KEY).toBool();
|
2022-09-05 20:09:12 +02:00
|
|
|
m_userEnvironmentChanges = EnvironmentItem::fromStringList(
|
2023-08-24 16:14:26 +02:00
|
|
|
map.value(USER_ENVIRONMENT_CHANGES_KEY).toStringList());
|
2022-09-05 20:09:12 +02:00
|
|
|
|
|
|
|
|
updateAndEmitEnvironmentChanged();
|
|
|
|
|
|
2023-08-24 16:14:26 +02:00
|
|
|
m_buildPreset = map.value(BUILD_PRESET_KEY).toString();
|
2022-09-05 20:09:12 +02:00
|
|
|
|
2023-07-21 18:23:50 +02:00
|
|
|
BuildStep::fromMap(map);
|
2009-10-15 19:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
2019-01-10 15:31:44 +01:00
|
|
|
bool CMakeBuildStep::init()
|
2008-12-04 13:06:02 +01:00
|
|
|
{
|
2022-12-09 18:44:42 +01:00
|
|
|
if (!CMakeAbstractProcessStep::init())
|
2020-09-14 17:17:55 +02:00
|
|
|
return false;
|
|
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
if (m_buildTargets.contains(QString())) {
|
|
|
|
|
RunConfiguration *rc = target()->activeRunConfiguration();
|
|
|
|
|
if (!rc || rc->buildKey().isEmpty()) {
|
|
|
|
|
emit addTask(BuildSystemTask(Task::Error,
|
2023-02-09 11:43:49 +01:00
|
|
|
::ProjectExplorer::Tr::tr(
|
2016-01-11 11:40:24 +01:00
|
|
|
"You asked to build the current Run Configuration's build target only, "
|
|
|
|
|
"but it is not associated with a build target. "
|
2020-01-15 08:56:11 +01:00
|
|
|
"Update the Make Step in your build settings.")));
|
2020-09-10 17:01:32 +02:00
|
|
|
emitFaultyConfigurationMessage();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2012-09-06 13:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2020-06-02 19:37:25 +02:00
|
|
|
setIgnoreReturnValue(m_buildTargets == QStringList(CMakeBuildStep::cleanTarget()));
|
2009-06-22 16:11:45 +02:00
|
|
|
|
2020-09-14 17:17:55 +02:00
|
|
|
return true;
|
2008-12-04 13:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-16 13:53:05 +02:00
|
|
|
void CMakeBuildStep::setupOutputFormatter(Utils::OutputFormatter *formatter)
|
|
|
|
|
{
|
|
|
|
|
CMakeParser *cmakeParser = new CMakeParser;
|
2020-07-30 13:16:43 +02:00
|
|
|
CmakeProgressParser * const progressParser = new CmakeProgressParser;
|
|
|
|
|
connect(progressParser, &CmakeProgressParser::progress, this, [this](int percent) {
|
|
|
|
|
emit progress(percent, {});
|
|
|
|
|
});
|
|
|
|
|
formatter->addLineParser(progressParser);
|
2022-09-30 17:21:09 +02:00
|
|
|
cmakeParser->setSourceDirectory(project()->projectDirectory());
|
2020-04-16 13:53:05 +02:00
|
|
|
formatter->addLineParsers({cmakeParser, new GnuMakeParser});
|
2023-12-11 11:42:00 +01:00
|
|
|
Toolchain *tc = ToolchainKitAspect::cxxToolchain(kit());
|
2021-11-15 15:11:43 +01:00
|
|
|
OutputTaskParser *xcodeBuildParser = nullptr;
|
|
|
|
|
if (tc && tc->targetAbi().os() == Abi::DarwinOS) {
|
|
|
|
|
xcodeBuildParser = new XcodebuildParser;
|
|
|
|
|
formatter->addLineParser(xcodeBuildParser);
|
|
|
|
|
progressParser->setRedirectionDetector(xcodeBuildParser);
|
|
|
|
|
}
|
2020-09-07 15:56:18 +02:00
|
|
|
const QList<Utils::OutputLineParser *> additionalParsers = kit()->createOutputParsers();
|
2020-07-30 13:16:43 +02:00
|
|
|
for (Utils::OutputLineParser * const p : additionalParsers)
|
|
|
|
|
p->setRedirectionDetector(progressParser);
|
|
|
|
|
formatter->addLineParsers(additionalParsers);
|
2020-04-16 13:53:05 +02:00
|
|
|
formatter->addSearchDir(processParameters()->effectiveWorkingDirectory());
|
2022-12-09 18:44:42 +01:00
|
|
|
CMakeAbstractProcessStep::setupOutputFormatter(formatter);
|
2020-04-16 13:53:05 +02:00
|
|
|
}
|
|
|
|
|
|
2023-08-17 11:08:21 +02:00
|
|
|
GroupItem CMakeBuildStep::runRecipe()
|
2016-02-25 14:18:05 +01:00
|
|
|
{
|
2023-07-12 08:54:53 +02:00
|
|
|
const auto onParserSetup = [this](QPointer<Target> &parseTarget) {
|
|
|
|
|
// Make sure CMake state was written to disk before trying to build:
|
|
|
|
|
auto bs = qobject_cast<CMakeBuildSystem *>(buildSystem());
|
|
|
|
|
QTC_ASSERT(bs, return SetupResult::StopWithError);
|
|
|
|
|
QString message;
|
|
|
|
|
if (bs->persistCMakeState())
|
|
|
|
|
message = Tr::tr("Persisting CMake state...");
|
|
|
|
|
else if (bs->isWaitingForParse())
|
|
|
|
|
message = Tr::tr("Running CMake in preparation to build...");
|
|
|
|
|
else
|
2023-11-04 12:57:23 +01:00
|
|
|
return SetupResult::StopWithSuccess;
|
2023-07-12 08:54:53 +02:00
|
|
|
emit addOutput(message, OutputFormat::NormalMessage);
|
|
|
|
|
parseTarget = target();
|
|
|
|
|
return SetupResult::Continue;
|
|
|
|
|
};
|
2023-11-02 23:19:49 +01:00
|
|
|
const auto onParserError = [this] {
|
2022-12-02 14:56:08 +01:00
|
|
|
emit addOutput(Tr::tr("Project did not parse successfully, cannot build."),
|
|
|
|
|
OutputFormat::ErrorMessage);
|
2023-07-12 08:54:53 +02:00
|
|
|
};
|
2023-10-20 15:00:44 +02:00
|
|
|
Group root {
|
2023-11-04 12:44:19 +01:00
|
|
|
ignoreReturnValue() ? finishAllAndSuccess : stopOnError,
|
2023-11-02 18:47:38 +01:00
|
|
|
ProjectParserTask(onParserSetup, onParserError, CallDoneIf::Error),
|
2023-07-12 08:54:53 +02:00
|
|
|
defaultProcessTask(),
|
2023-11-03 18:50:32 +01:00
|
|
|
onGroupDone([this] { updateDeploymentData(); })
|
2023-07-12 08:54:53 +02:00
|
|
|
};
|
2023-07-12 16:30:33 +02:00
|
|
|
return root;
|
2016-02-25 14:18:05 +01:00
|
|
|
}
|
|
|
|
|
|
2019-07-23 13:05:07 +02:00
|
|
|
QString CMakeBuildStep::defaultBuildTarget() const
|
|
|
|
|
{
|
2019-08-16 12:16:17 +02:00
|
|
|
const BuildStepList *const bsl = stepList();
|
|
|
|
|
QTC_ASSERT(bsl, return {});
|
2020-06-26 13:59:38 +02:00
|
|
|
const Utils::Id parentId = bsl->id();
|
2019-07-23 13:05:07 +02:00
|
|
|
if (parentId == ProjectExplorer::Constants::BUILDSTEPS_CLEAN)
|
|
|
|
|
return cleanTarget();
|
|
|
|
|
if (parentId == ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
|
|
|
|
|
return installTarget();
|
|
|
|
|
return allTarget();
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-05 20:09:12 +02:00
|
|
|
bool CMakeBuildStep::isCleanStep() const
|
|
|
|
|
{
|
|
|
|
|
const BuildStepList *const bsl = stepList();
|
|
|
|
|
QTC_ASSERT(bsl, return false);
|
|
|
|
|
const Utils::Id parentId = bsl->id();
|
|
|
|
|
return parentId == ProjectExplorer::Constants::BUILDSTEPS_CLEAN;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-02 19:37:25 +02:00
|
|
|
QStringList CMakeBuildStep::buildTargets() const
|
2011-10-21 23:17:58 +02:00
|
|
|
{
|
2020-06-02 19:37:25 +02:00
|
|
|
return m_buildTargets;
|
2011-10-21 23:17:58 +02:00
|
|
|
}
|
|
|
|
|
|
2016-01-07 12:33:52 +01:00
|
|
|
bool CMakeBuildStep::buildsBuildTarget(const QString &target) const
|
2009-01-12 15:10:33 +01:00
|
|
|
{
|
2020-06-02 19:37:25 +02:00
|
|
|
return m_buildTargets.contains(target);
|
2009-01-12 15:10:33 +01:00
|
|
|
}
|
|
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
void CMakeBuildStep::setBuildsBuildTarget(const QString &target, bool on)
|
|
|
|
|
{
|
|
|
|
|
QStringList targets = m_buildTargets;
|
|
|
|
|
if (on && !m_buildTargets.contains(target))
|
|
|
|
|
targets.append(target);
|
|
|
|
|
if (!on)
|
|
|
|
|
targets.removeAll(target);
|
|
|
|
|
setBuildTargets(targets);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-02 19:37:25 +02:00
|
|
|
void CMakeBuildStep::setBuildTargets(const QStringList &buildTargets)
|
2011-10-21 23:17:58 +02:00
|
|
|
{
|
2020-09-10 17:01:32 +02:00
|
|
|
if (buildTargets.isEmpty())
|
|
|
|
|
m_buildTargets = QStringList(defaultBuildTarget());
|
|
|
|
|
else
|
|
|
|
|
m_buildTargets = buildTargets;
|
|
|
|
|
updateBuildTargetsModel();
|
2011-10-21 23:17:58 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
CommandLine CMakeBuildStep::cmakeCommand() const
|
2015-11-26 19:50:39 +01:00
|
|
|
{
|
2023-04-05 14:16:00 +02:00
|
|
|
CommandLine cmd{cmakeExecutable()};
|
2015-11-26 19:50:39 +01:00
|
|
|
|
2021-10-18 10:23:35 +02:00
|
|
|
FilePath buildDirectory = ".";
|
2021-01-25 20:00:53 +01:00
|
|
|
if (buildConfiguration())
|
2021-10-18 10:23:35 +02:00
|
|
|
buildDirectory = buildConfiguration()->buildDirectory();
|
|
|
|
|
|
2024-01-31 09:49:56 +01:00
|
|
|
cmd.addArgs({"--build", CMakeToolManager::mappedFilePath(buildDirectory).path()});
|
2015-11-26 19:50:39 +01:00
|
|
|
|
2020-06-02 19:37:25 +02:00
|
|
|
cmd.addArg("--target");
|
2020-09-10 17:01:32 +02:00
|
|
|
cmd.addArgs(Utils::transform(m_buildTargets, [this](const QString &s) {
|
|
|
|
|
if (s.isEmpty()) {
|
|
|
|
|
if (RunConfiguration *rc = target()->activeRunConfiguration())
|
|
|
|
|
return rc->buildKey();
|
2019-07-29 13:51:43 +02:00
|
|
|
}
|
2020-09-10 17:01:32 +02:00
|
|
|
return s;
|
2020-06-02 19:37:25 +02:00
|
|
|
}));
|
2023-07-13 16:21:49 +02:00
|
|
|
if (useStaging())
|
2023-06-14 15:41:20 +02:00
|
|
|
cmd.addArg("install");
|
2016-01-07 13:15:29 +01:00
|
|
|
|
2023-06-14 15:41:20 +02:00
|
|
|
auto bs = qobject_cast<CMakeBuildSystem *>(buildSystem());
|
2022-05-02 18:02:37 +02:00
|
|
|
if (bs && bs->isMultiConfigReader()) {
|
2021-01-14 16:38:55 +01:00
|
|
|
cmd.addArg("--config");
|
2022-09-05 20:09:12 +02:00
|
|
|
if (m_configuration)
|
|
|
|
|
cmd.addArg(m_configuration.value());
|
|
|
|
|
else
|
|
|
|
|
cmd.addArg(bs->cmakeBuildType());
|
2021-01-14 16:38:55 +01:00
|
|
|
}
|
|
|
|
|
|
2023-07-13 16:21:49 +02:00
|
|
|
cmd.addArgs(cmakeArguments(), CommandLine::Raw);
|
2016-03-30 13:06:21 +02:00
|
|
|
|
CMake: iOS: Enable automatic provisioning updates
By default xcodebuild does not try create / download a provisioning
profile for a project if a valid one does not exist locally
in ~/Library/MobileDevice/Provisioning Profiles, even if the
Xcode CODE_SIGN_STYLE attribute is set to Automatic.
Starting with Xcode 9, xcodebuild accepts a new
-allowProvisioningUpdates option.
When passed, xcodebuild will request a new provisioning profile
from Apple's servers for the current project and use it during
the build. The provisioning profile is only needed when building
for a real device, not the simulator.
When building an iOS project with qmake, the option is embedded in the
wrapping Makefile generated by qmake, so Qt Creator can simply call
make (which it does).
For CMake, there is no wrapping Makefile, so we need to pass the new
option explicitly as an additional build tool argument.
There might be cases where automatic provisioning is not desired,
which is why there is now a new checkbox in the CMake build step
configuration widget. It's default value is 'enabled', to match
qmake's behavior.
As an implementation detail, isiOS had to be moved to a header file so
it's accessible to both the build configuration and the build step.
Fixes: QTCREATORBUG-26246
Change-Id: Ic80cd965ba095d0ff379e13ad2ffb8c298c9f7c4
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-05-05 16:26:11 +02:00
|
|
|
bool toolArgumentsSpecified = false;
|
2023-07-13 16:21:49 +02:00
|
|
|
if (!toolArguments().isEmpty()) {
|
2019-05-29 18:54:45 +02:00
|
|
|
cmd.addArg("--");
|
2023-07-13 16:21:49 +02:00
|
|
|
cmd.addArgs(toolArguments(), CommandLine::Raw);
|
CMake: iOS: Enable automatic provisioning updates
By default xcodebuild does not try create / download a provisioning
profile for a project if a valid one does not exist locally
in ~/Library/MobileDevice/Provisioning Profiles, even if the
Xcode CODE_SIGN_STYLE attribute is set to Automatic.
Starting with Xcode 9, xcodebuild accepts a new
-allowProvisioningUpdates option.
When passed, xcodebuild will request a new provisioning profile
from Apple's servers for the current project and use it during
the build. The provisioning profile is only needed when building
for a real device, not the simulator.
When building an iOS project with qmake, the option is embedded in the
wrapping Makefile generated by qmake, so Qt Creator can simply call
make (which it does).
For CMake, there is no wrapping Makefile, so we need to pass the new
option explicitly as an additional build tool argument.
There might be cases where automatic provisioning is not desired,
which is why there is now a new checkbox in the CMake build step
configuration widget. It's default value is 'enabled', to match
qmake's behavior.
As an implementation detail, isiOS had to be moved to a header file so
it's accessible to both the build configuration and the build step.
Fixes: QTCREATORBUG-26246
Change-Id: Ic80cd965ba095d0ff379e13ad2ffb8c298c9f7c4
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-05-05 16:26:11 +02:00
|
|
|
toolArgumentsSpecified = true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-13 16:21:49 +02:00
|
|
|
if (useiOSAutomaticProvisioningUpdates()) {
|
CMake: iOS: Enable automatic provisioning updates
By default xcodebuild does not try create / download a provisioning
profile for a project if a valid one does not exist locally
in ~/Library/MobileDevice/Provisioning Profiles, even if the
Xcode CODE_SIGN_STYLE attribute is set to Automatic.
Starting with Xcode 9, xcodebuild accepts a new
-allowProvisioningUpdates option.
When passed, xcodebuild will request a new provisioning profile
from Apple's servers for the current project and use it during
the build. The provisioning profile is only needed when building
for a real device, not the simulator.
When building an iOS project with qmake, the option is embedded in the
wrapping Makefile generated by qmake, so Qt Creator can simply call
make (which it does).
For CMake, there is no wrapping Makefile, so we need to pass the new
option explicitly as an additional build tool argument.
There might be cases where automatic provisioning is not desired,
which is why there is now a new checkbox in the CMake build step
configuration widget. It's default value is 'enabled', to match
qmake's behavior.
As an implementation detail, isiOS had to be moved to a header file so
it's accessible to both the build configuration and the build step.
Fixes: QTCREATORBUG-26246
Change-Id: Ic80cd965ba095d0ff379e13ad2ffb8c298c9f7c4
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-05-05 16:26:11 +02:00
|
|
|
// Only add the double dash if it wasn't added before.
|
|
|
|
|
if (!toolArgumentsSpecified)
|
|
|
|
|
cmd.addArg("--");
|
|
|
|
|
cmd.addArgs("-allowProvisioningUpdates", CommandLine::Raw);
|
2016-01-07 13:15:29 +01:00
|
|
|
}
|
2014-04-03 16:33:04 +02:00
|
|
|
|
2019-05-29 18:54:45 +02:00
|
|
|
return cmd;
|
2014-10-02 17:51:02 +02:00
|
|
|
}
|
|
|
|
|
|
2021-01-14 16:38:55 +01:00
|
|
|
QString CMakeBuildStep::cleanTarget() const
|
2016-01-07 12:09:59 +01:00
|
|
|
{
|
2017-04-28 08:23:57 +02:00
|
|
|
return QString("clean");
|
2016-01-07 12:09:59 +01:00
|
|
|
}
|
|
|
|
|
|
2021-01-14 16:38:55 +01:00
|
|
|
QString CMakeBuildStep::allTarget() const
|
2020-12-22 16:57:54 +01:00
|
|
|
{
|
2021-01-14 16:38:55 +01:00
|
|
|
return m_allTarget;
|
2020-12-22 16:57:54 +01:00
|
|
|
}
|
|
|
|
|
|
2021-01-14 16:38:55 +01:00
|
|
|
QString CMakeBuildStep::installTarget() const
|
2017-06-02 09:11:39 +02:00
|
|
|
{
|
2021-01-14 16:38:55 +01:00
|
|
|
return m_installTarget;
|
2017-06-02 09:11:39 +02:00
|
|
|
}
|
|
|
|
|
|
2021-01-14 16:38:55 +01:00
|
|
|
QStringList CMakeBuildStep::specialTargets(bool allCapsTargets)
|
2017-04-26 15:27:01 +02:00
|
|
|
{
|
2021-01-14 16:38:55 +01:00
|
|
|
if (!allCapsTargets)
|
|
|
|
|
return {"all", "clean", "install", "install/strip", "package", "test"};
|
|
|
|
|
else
|
|
|
|
|
return {"ALL_BUILD", "clean", "INSTALL", "PACKAGE", "RUN_TESTS"};
|
2016-03-30 13:06:21 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
QString CMakeBuildStep::activeRunConfigTarget() const
|
|
|
|
|
{
|
|
|
|
|
RunConfiguration *rc = target()->activeRunConfiguration();
|
|
|
|
|
return rc ? rc->buildKey() : QString();
|
|
|
|
|
}
|
2009-03-12 15:51:44 +01:00
|
|
|
|
2022-09-05 20:09:12 +02:00
|
|
|
void CMakeBuildStep::setBuildPreset(const QString &preset)
|
|
|
|
|
{
|
|
|
|
|
m_buildPreset = preset;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-02 17:53:39 +02:00
|
|
|
QWidget *CMakeBuildStep::createConfigWidget()
|
2009-01-12 15:10:33 +01:00
|
|
|
{
|
2020-09-14 12:37:32 +02:00
|
|
|
auto updateDetails = [this] {
|
2020-09-10 17:01:32 +02:00
|
|
|
ProcessParameters param;
|
|
|
|
|
setupProcessParameters(¶m);
|
|
|
|
|
param.setCommandLine(cmakeCommand());
|
2022-09-05 20:09:12 +02:00
|
|
|
|
|
|
|
|
QString summaryText = param.summary(displayName());
|
|
|
|
|
|
2023-07-13 16:21:49 +02:00
|
|
|
stagingDir.setEnabled(useStaging());
|
|
|
|
|
if (useStaging()) {
|
2023-06-13 15:36:21 +02:00
|
|
|
//: Stage (for installation) at <staging_dir> for <installation_dir>
|
|
|
|
|
summaryText.append(
|
|
|
|
|
"; "
|
2023-07-13 16:21:49 +02:00
|
|
|
+ Tr::tr("Stage at %2 for %3").arg(stagingDir().path(), currentInstallPrefix()));
|
2023-04-05 14:16:00 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-05 20:09:12 +02:00
|
|
|
if (!m_buildPreset.isEmpty()) {
|
|
|
|
|
const CMakeProject *cp = static_cast<const CMakeProject *>(project());
|
|
|
|
|
|
|
|
|
|
const auto buildPresets = cp->presetsData().buildPresets;
|
|
|
|
|
const PresetsDetails::BuildPreset preset
|
|
|
|
|
= Utils::findOrDefault(buildPresets, [this](const PresetsDetails::BuildPreset &bp) {
|
|
|
|
|
return bp.name == m_buildPreset;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const QString presetDisplayName = preset.displayName ? preset.displayName.value()
|
|
|
|
|
: preset.name;
|
|
|
|
|
if (!presetDisplayName.isEmpty())
|
|
|
|
|
summaryText.append(QString("<br><b>Preset</b>: %1").arg(presetDisplayName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setSummaryText(summaryText);
|
2020-09-10 17:01:32 +02:00
|
|
|
};
|
2018-10-12 17:52:09 +02:00
|
|
|
|
2022-09-29 15:26:31 +02:00
|
|
|
setDisplayName(Tr::tr("Build", "ConfigWidget display name."));
|
2009-03-12 15:51:44 +01:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
auto buildTargetsView = new QTreeView;
|
|
|
|
|
buildTargetsView->setMinimumHeight(200);
|
|
|
|
|
buildTargetsView->setModel(&m_buildTargetModel);
|
|
|
|
|
buildTargetsView->setRootIsDecorated(false);
|
|
|
|
|
buildTargetsView->setHeaderHidden(true);
|
|
|
|
|
|
|
|
|
|
auto frame = ItemViewFind::createSearchableWrapper(buildTargetsView,
|
|
|
|
|
ItemViewFind::LightColored);
|
2014-08-04 12:16:04 +02:00
|
|
|
|
2022-09-05 20:09:12 +02:00
|
|
|
auto createAndAddEnvironmentWidgets = [this](Layouting::Form &builder) {
|
2022-09-29 15:26:31 +02:00
|
|
|
auto clearBox = new QCheckBox(Tr::tr("Clear system environment"));
|
2022-09-05 20:09:12 +02:00
|
|
|
clearBox->setChecked(useClearEnvironment());
|
|
|
|
|
|
|
|
|
|
auto envWidget = new EnvironmentWidget(nullptr, EnvironmentWidget::TypeLocal, clearBox);
|
|
|
|
|
envWidget->setBaseEnvironment(baseEnvironment());
|
|
|
|
|
envWidget->setBaseEnvironmentText(baseEnvironmentText());
|
|
|
|
|
envWidget->setUserChanges(userEnvironmentChanges());
|
|
|
|
|
|
|
|
|
|
connect(envWidget, &EnvironmentWidget::userChangesChanged, this, [this, envWidget] {
|
|
|
|
|
setUserEnvironmentChanges(envWidget->userChanges());
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
connect(clearBox, &QAbstractButton::toggled, this, [this, envWidget](bool checked) {
|
|
|
|
|
setUseClearEnvironment(checked);
|
|
|
|
|
envWidget->setBaseEnvironment(baseEnvironment());
|
|
|
|
|
envWidget->setBaseEnvironmentText(baseEnvironmentText());
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
connect(this, &CMakeBuildStep::environmentChanged, this, [this, envWidget] {
|
|
|
|
|
envWidget->setBaseEnvironment(baseEnvironment());
|
|
|
|
|
envWidget->setBaseEnvironmentText(baseEnvironmentText());
|
|
|
|
|
});
|
|
|
|
|
|
2023-04-24 17:06:32 +02:00
|
|
|
builder.addRow({clearBox});
|
|
|
|
|
builder.addRow({envWidget});
|
2022-09-05 20:09:12 +02:00
|
|
|
};
|
|
|
|
|
|
2021-03-11 19:02:42 +01:00
|
|
|
Layouting::Form builder;
|
2023-07-13 16:21:49 +02:00
|
|
|
builder.addRow({cmakeArguments});
|
|
|
|
|
builder.addRow({toolArguments});
|
|
|
|
|
builder.addRow({useStaging});
|
|
|
|
|
builder.addRow({stagingDir});
|
|
|
|
|
builder.addRow({useiOSAutomaticProvisioningUpdates});
|
CMake: iOS: Enable automatic provisioning updates
By default xcodebuild does not try create / download a provisioning
profile for a project if a valid one does not exist locally
in ~/Library/MobileDevice/Provisioning Profiles, even if the
Xcode CODE_SIGN_STYLE attribute is set to Automatic.
Starting with Xcode 9, xcodebuild accepts a new
-allowProvisioningUpdates option.
When passed, xcodebuild will request a new provisioning profile
from Apple's servers for the current project and use it during
the build. The provisioning profile is only needed when building
for a real device, not the simulator.
When building an iOS project with qmake, the option is embedded in the
wrapping Makefile generated by qmake, so Qt Creator can simply call
make (which it does).
For CMake, there is no wrapping Makefile, so we need to pass the new
option explicitly as an additional build tool argument.
There might be cases where automatic provisioning is not desired,
which is why there is now a new checkbox in the CMake build step
configuration widget. It's default value is 'enabled', to match
qmake's behavior.
As an implementation detail, isiOS had to be moved to a header file so
it's accessible to both the build configuration and the build step.
Fixes: QTCREATORBUG-26246
Change-Id: Ic80cd965ba095d0ff379e13ad2ffb8c298c9f7c4
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-05-05 16:26:11 +02:00
|
|
|
|
2022-09-29 15:26:31 +02:00
|
|
|
builder.addRow({new QLabel(Tr::tr("Targets:")), frame});
|
2022-09-05 20:09:12 +02:00
|
|
|
|
|
|
|
|
if (!isCleanStep() && !m_buildPreset.isEmpty())
|
|
|
|
|
createAndAddEnvironmentWidgets(builder);
|
|
|
|
|
|
2023-05-02 12:51:03 +02:00
|
|
|
builder.addItem(Layouting::noMargin);
|
|
|
|
|
auto widget = builder.emerge();
|
2009-01-12 15:10:33 +01:00
|
|
|
|
2011-05-30 13:30:10 +02:00
|
|
|
updateDetails();
|
|
|
|
|
|
2023-07-13 16:21:49 +02:00
|
|
|
connect(&cmakeArguments, &BaseAspect::changed, this, updateDetails);
|
|
|
|
|
connect(&toolArguments, &BaseAspect::changed, this, updateDetails);
|
|
|
|
|
connect(&useStaging, &BaseAspect::changed, this, updateDetails);
|
|
|
|
|
connect(&stagingDir, &BaseAspect::changed, this, updateDetails);
|
|
|
|
|
connect(&useiOSAutomaticProvisioningUpdates, &BaseAspect::changed, this, updateDetails);
|
CMake: iOS: Enable automatic provisioning updates
By default xcodebuild does not try create / download a provisioning
profile for a project if a valid one does not exist locally
in ~/Library/MobileDevice/Provisioning Profiles, even if the
Xcode CODE_SIGN_STYLE attribute is set to Automatic.
Starting with Xcode 9, xcodebuild accepts a new
-allowProvisioningUpdates option.
When passed, xcodebuild will request a new provisioning profile
from Apple's servers for the current project and use it during
the build. The provisioning profile is only needed when building
for a real device, not the simulator.
When building an iOS project with qmake, the option is embedded in the
wrapping Makefile generated by qmake, so Qt Creator can simply call
make (which it does).
For CMake, there is no wrapping Makefile, so we need to pass the new
option explicitly as an additional build tool argument.
There might be cases where automatic provisioning is not desired,
which is why there is now a new checkbox in the CMake build step
configuration widget. It's default value is 'enabled', to match
qmake's behavior.
As an implementation detail, isiOS had to be moved to a header file so
it's accessible to both the build configuration and the build step.
Fixes: QTCREATORBUG-26246
Change-Id: Ic80cd965ba095d0ff379e13ad2ffb8c298c9f7c4
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-05-05 16:26:11 +02:00
|
|
|
|
2016-01-07 12:33:52 +01:00
|
|
|
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
|
2020-09-10 17:01:32 +02:00
|
|
|
this, updateDetails);
|
2014-10-02 17:51:02 +02:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
connect(buildConfiguration(), &BuildConfiguration::environmentChanged,
|
|
|
|
|
this, updateDetails);
|
|
|
|
|
|
|
|
|
|
connect(this, &CMakeBuildStep::buildTargetsChanged, widget, updateDetails);
|
|
|
|
|
|
|
|
|
|
return widget;
|
2009-01-12 15:10:33 +01:00
|
|
|
}
|
2008-12-04 13:06:02 +01:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
void CMakeBuildStep::recreateBuildTargetsModel()
|
2017-03-31 17:17:20 +02:00
|
|
|
{
|
2020-09-10 17:01:32 +02:00
|
|
|
auto addItem = [this](const QString &target, bool special = false) {
|
|
|
|
|
auto item = new CMakeTargetItem(target, this, special);
|
|
|
|
|
m_buildTargetModel.rootItem()->appendChild(item);
|
|
|
|
|
};
|
2020-06-02 19:37:25 +02:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
m_buildTargetModel.clear();
|
2018-07-20 12:17:36 +02:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
auto bs = qobject_cast<CMakeBuildSystem *>(buildSystem());
|
|
|
|
|
QStringList targetList = bs ? bs->buildTargetTitles() : QStringList();
|
2017-03-31 17:17:20 +02:00
|
|
|
|
2021-01-14 16:38:55 +01:00
|
|
|
bool usesAllCapsTargets = bs ? bs->usesAllCapsTargets() : false;
|
|
|
|
|
if (usesAllCapsTargets) {
|
|
|
|
|
m_allTarget = "ALL_BUILD";
|
|
|
|
|
m_installTarget = "INSTALL";
|
|
|
|
|
|
|
|
|
|
int idx = m_buildTargets.indexOf(QString("all"));
|
|
|
|
|
if (idx != -1)
|
|
|
|
|
m_buildTargets[idx] = QString("ALL_BUILD");
|
|
|
|
|
idx = m_buildTargets.indexOf(QString("install"));
|
|
|
|
|
if (idx != -1)
|
|
|
|
|
m_buildTargets[idx] = QString("INSTALL");
|
|
|
|
|
}
|
|
|
|
|
targetList.removeDuplicates();
|
2016-03-30 13:06:21 +02:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
addItem(QString(), true);
|
2017-04-26 15:29:54 +02:00
|
|
|
|
2021-03-31 17:58:09 +02:00
|
|
|
// Remove the targets that do not exist in the build system
|
|
|
|
|
// This can result when selected targets get renamed
|
|
|
|
|
if (!targetList.empty()) {
|
2021-04-27 14:27:53 +02:00
|
|
|
Utils::erase(m_buildTargets, [targetList](const QString &bt) {
|
|
|
|
|
return !bt.isEmpty() /* "current executable" */ && !targetList.contains(bt);
|
|
|
|
|
});
|
2021-03-31 17:58:09 +02:00
|
|
|
if (m_buildTargets.empty())
|
|
|
|
|
m_buildTargets.push_back(m_allTarget);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-07 14:46:06 +02:00
|
|
|
for (const QString &buildTarget : std::as_const(targetList))
|
2021-01-14 16:38:55 +01:00
|
|
|
addItem(buildTarget, specialTargets(usesAllCapsTargets).contains(buildTarget));
|
2016-03-30 13:06:21 +02:00
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
updateBuildTargetsModel();
|
2009-08-06 17:26:38 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-10 17:01:32 +02:00
|
|
|
void CMakeBuildStep::updateBuildTargetsModel()
|
2013-08-26 16:01:24 +02:00
|
|
|
{
|
2020-09-10 17:01:32 +02:00
|
|
|
emit m_buildTargetModel.layoutChanged();
|
|
|
|
|
emit buildTargetsChanged();
|
2013-08-26 16:01:24 +02:00
|
|
|
}
|
2018-07-20 12:17:36 +02:00
|
|
|
|
2022-09-05 20:09:12 +02:00
|
|
|
void CMakeBuildStep::setConfiguration(const QString &configuration)
|
|
|
|
|
{
|
|
|
|
|
m_configuration = configuration;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeBuildStep::setToolArguments(const QStringList &nativeToolArguments)
|
|
|
|
|
{
|
2023-07-13 16:21:49 +02:00
|
|
|
toolArguments.setValue(nativeToolArguments.join(" "));
|
2022-09-05 20:09:12 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-13 16:21:49 +02:00
|
|
|
void CMakeBuildStep::setCMakeArguments(const QStringList &cmakeArgs)
|
2022-09-05 20:09:12 +02:00
|
|
|
{
|
2023-07-13 16:21:49 +02:00
|
|
|
cmakeArguments.setValue(cmakeArgs.join(" "));
|
2022-09-05 20:09:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Environment CMakeBuildStep::environment() const
|
|
|
|
|
{
|
|
|
|
|
return m_environment;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeBuildStep::setUserEnvironmentChanges(const Utils::EnvironmentItems &diff)
|
|
|
|
|
{
|
|
|
|
|
if (m_userEnvironmentChanges == diff)
|
|
|
|
|
return;
|
|
|
|
|
m_userEnvironmentChanges = diff;
|
|
|
|
|
updateAndEmitEnvironmentChanged();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EnvironmentItems CMakeBuildStep::userEnvironmentChanges() const
|
|
|
|
|
{
|
|
|
|
|
return m_userEnvironmentChanges;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CMakeBuildStep::useClearEnvironment() const
|
|
|
|
|
{
|
|
|
|
|
return m_clearSystemEnvironment;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeBuildStep::setUseClearEnvironment(bool b)
|
|
|
|
|
{
|
|
|
|
|
if (useClearEnvironment() == b)
|
|
|
|
|
return;
|
|
|
|
|
m_clearSystemEnvironment = b;
|
|
|
|
|
updateAndEmitEnvironmentChanged();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeBuildStep::updateAndEmitEnvironmentChanged()
|
|
|
|
|
{
|
|
|
|
|
Environment env = baseEnvironment();
|
|
|
|
|
env.modify(userEnvironmentChanges());
|
|
|
|
|
if (env == m_environment)
|
|
|
|
|
return;
|
|
|
|
|
m_environment = env;
|
|
|
|
|
emit environmentChanged();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Environment CMakeBuildStep::baseEnvironment() const
|
|
|
|
|
{
|
|
|
|
|
Environment result;
|
|
|
|
|
if (!useClearEnvironment()) {
|
|
|
|
|
ProjectExplorer::IDevice::ConstPtr devicePtr = BuildDeviceKitAspect::device(kit());
|
|
|
|
|
result = devicePtr ? devicePtr->systemEnvironment() : Environment::systemEnvironment();
|
|
|
|
|
}
|
|
|
|
|
buildConfiguration()->addToEnvironment(result);
|
|
|
|
|
kit()->addToBuildEnvironment(result);
|
|
|
|
|
result.modify(project()->additionalEnvironment());
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString CMakeBuildStep::baseEnvironmentText() const
|
|
|
|
|
{
|
|
|
|
|
if (useClearEnvironment())
|
2022-09-29 15:26:31 +02:00
|
|
|
return Tr::tr("Clean Environment");
|
2022-09-05 20:09:12 +02:00
|
|
|
else
|
2022-09-29 15:26:31 +02:00
|
|
|
return Tr::tr("System Environment");
|
2022-09-05 20:09:12 +02:00
|
|
|
}
|
|
|
|
|
|
2023-04-05 14:16:00 +02:00
|
|
|
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"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FilePath CMakeBuildStep::cmakeExecutable() const
|
|
|
|
|
{
|
|
|
|
|
CMakeTool *tool = CMakeKitAspect::cmakeTool(kit());
|
|
|
|
|
return tool ? tool->cmakeExecutable() : FilePath();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMakeBuildStep::updateDeploymentData()
|
|
|
|
|
{
|
2023-07-13 16:21:49 +02:00
|
|
|
if (!useStaging())
|
2023-04-05 14:16:00 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
QString install = currentInstallPrefix();
|
2023-07-13 16:21:49 +02:00
|
|
|
FilePath rootDir = cmakeExecutable().withNewPath(stagingDir().path());
|
2023-04-05 14:16:00 +02:00
|
|
|
Q_UNUSED(install);
|
|
|
|
|
|
|
|
|
|
DeploymentData deploymentData;
|
|
|
|
|
deploymentData.setLocalInstallRoot(rootDir);
|
|
|
|
|
|
2023-10-24 09:15:02 +02:00
|
|
|
IDeviceConstPtr runDevice = DeviceKitAspect::device(buildSystem()->kit());
|
2023-04-05 14:16:00 +02:00
|
|
|
|
2023-11-07 11:03:55 +01:00
|
|
|
if (!runDevice)
|
|
|
|
|
return;
|
|
|
|
|
|
2023-04-05 14:16:00 +02:00
|
|
|
const auto appFileNames = transform<QSet<QString>>(buildSystem()->applicationTargets(),
|
|
|
|
|
[](const BuildTargetInfo &appTarget) { return appTarget.targetFilePath.fileName(); });
|
|
|
|
|
|
2023-10-24 09:15:02 +02:00
|
|
|
auto handleFile =
|
|
|
|
|
[&appFileNames, rootDir, &deploymentData, runDevice](const FilePath &filePath) {
|
|
|
|
|
const DeployableFile::Type type = appFileNames.contains(filePath.fileName())
|
|
|
|
|
? DeployableFile::TypeExecutable
|
|
|
|
|
: DeployableFile::TypeNormal;
|
2023-06-20 15:00:35 +02:00
|
|
|
|
2023-10-24 09:15:02 +02:00
|
|
|
FilePath targetDirPath = filePath.parentDir().relativePathFrom(rootDir);
|
2023-06-20 15:00:35 +02:00
|
|
|
|
2023-10-24 09:15:02 +02:00
|
|
|
const FilePath targetDir = runDevice->rootPath().pathAppended(targetDirPath.path());
|
|
|
|
|
deploymentData.addFile(filePath, targetDir.nativePath(), type);
|
|
|
|
|
return IterationPolicy::Continue;
|
|
|
|
|
};
|
2023-04-05 14:16:00 +02:00
|
|
|
|
|
|
|
|
rootDir.iterateDirectory(handleFile,
|
|
|
|
|
{{}, QDir::Files | QDir::Hidden, QDirIterator::Subdirectories});
|
|
|
|
|
|
|
|
|
|
buildSystem()->setDeploymentData(deploymentData);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-07 12:33:52 +01:00
|
|
|
// CMakeBuildStepFactory
|
2008-12-04 13:06:02 +01:00
|
|
|
|
2024-01-29 14:27:33 +01:00
|
|
|
class CMakeBuildStepFactory final : public BuildStepFactory
|
2010-01-14 17:41:29 +01:00
|
|
|
{
|
2024-01-29 14:27:33 +01:00
|
|
|
public:
|
|
|
|
|
CMakeBuildStepFactory()
|
|
|
|
|
{
|
|
|
|
|
registerStep<CMakeBuildStep>(Constants::CMAKE_BUILD_STEP_ID);
|
|
|
|
|
setDisplayName(Tr::tr("CMake Build", "Display name for CMakeProjectManager::CMakeBuildStep id."));
|
|
|
|
|
setSupportedProjectType(Constants::CMAKE_PROJECT_ID);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void setupCMakeBuildStep()
|
|
|
|
|
{
|
|
|
|
|
static CMakeBuildStepFactory theCMakeBuildStepFactory;
|
2010-01-14 17:41:29 +01:00
|
|
|
}
|
|
|
|
|
|
2022-09-29 15:26:31 +02:00
|
|
|
} // CMakeProjectManager::Internal
|
2020-07-30 13:16:43 +02:00
|
|
|
|
|
|
|
|
#include <cmakebuildstep.moc>
|