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
|
2013-04-25 16:02:17 +02:00
|
|
|
|
|
|
|
|
#include "iosdeploystep.h"
|
2020-02-20 13:21:52 +01:00
|
|
|
|
2013-04-25 16:02:17 +02:00
|
|
|
#include "iosconstants.h"
|
2020-02-20 13:21:52 +01:00
|
|
|
#include "iosdevice.h"
|
2013-04-25 16:02:17 +02:00
|
|
|
#include "iosrunconfiguration.h"
|
2020-02-20 13:21:52 +01:00
|
|
|
#include "iossimulator.h"
|
2013-04-25 16:02:17 +02:00
|
|
|
#include "iostoolhandler.h"
|
2022-12-20 13:39:23 +01:00
|
|
|
#include "iostr.h"
|
2013-04-25 16:02:17 +02:00
|
|
|
|
|
|
|
|
#include <projectexplorer/buildconfiguration.h>
|
|
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
|
|
|
|
#include <projectexplorer/target.h>
|
2013-11-04 22:45:52 +01:00
|
|
|
#include <projectexplorer/taskhub.h>
|
2023-08-11 09:18:56 +02:00
|
|
|
#include <projectexplorer/kitaspects.h>
|
2014-05-13 16:09:11 +02:00
|
|
|
#include <projectexplorer/kitmanager.h>
|
|
|
|
|
#include <projectexplorer/devicesupport/devicemanager.h>
|
2013-04-25 16:02:17 +02:00
|
|
|
|
2023-07-14 11:37:50 +02:00
|
|
|
#include <solutions/tasking/tasktree.h>
|
|
|
|
|
|
2024-01-12 15:50:15 +01:00
|
|
|
#include <utils/process.h>
|
2017-01-19 16:44:22 +01:00
|
|
|
#include <utils/temporaryfile.h>
|
|
|
|
|
|
2014-05-08 13:43:25 +02:00
|
|
|
#include <QFile>
|
2024-01-12 15:50:15 +01:00
|
|
|
#include <QJsonArray>
|
|
|
|
|
#include <QJsonDocument>
|
2014-05-08 13:43:25 +02:00
|
|
|
#include <QSettings>
|
2013-04-25 16:02:17 +02:00
|
|
|
|
|
|
|
|
using namespace ProjectExplorer;
|
2023-07-14 11:37:50 +02:00
|
|
|
using namespace Tasking;
|
2019-05-15 15:49:19 +02:00
|
|
|
using namespace Utils;
|
2013-04-25 16:02:17 +02:00
|
|
|
|
2022-12-20 13:39:23 +01:00
|
|
|
namespace Ios::Internal {
|
2013-04-25 16:02:17 +02:00
|
|
|
|
2023-07-14 11:37:50 +02:00
|
|
|
class IosTransfer : public QObject
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
void setDeviceType(const IosDeviceType &deviceType) { m_deviceType = deviceType; }
|
|
|
|
|
void setBundlePath(const FilePath &bundlePath) { m_bundlePath = bundlePath; }
|
|
|
|
|
void setExpectSuccess(bool success) { m_expectSuccess = success; }
|
|
|
|
|
void start()
|
|
|
|
|
{
|
2023-11-15 10:33:31 +01:00
|
|
|
QTC_ASSERT(m_deviceType, emit done(DoneResult::Error); return);
|
2023-07-14 11:37:50 +02:00
|
|
|
QTC_ASSERT(!m_toolHandler, return);
|
|
|
|
|
|
|
|
|
|
m_toolHandler.reset(new IosToolHandler(*m_deviceType));
|
|
|
|
|
connect(m_toolHandler.get(), &IosToolHandler::isTransferringApp, this,
|
|
|
|
|
[this](IosToolHandler *, const FilePath &, const QString &,
|
|
|
|
|
int progress, int maxProgress, const QString &info) {
|
|
|
|
|
emit progressValueChanged(progress * 100 / maxProgress, info);
|
|
|
|
|
});
|
|
|
|
|
connect(m_toolHandler.get(), &IosToolHandler::errorMsg, this,
|
|
|
|
|
[this](IosToolHandler *, const QString &message) {
|
|
|
|
|
if (message.contains(QLatin1String("AMDeviceInstallApplication returned -402653103")))
|
|
|
|
|
TaskHub::addTask(DeploymentTask(Task::Warning, Tr::tr("The Info.plist might be incorrect.")));
|
|
|
|
|
emit errorMessage(message);
|
|
|
|
|
});
|
|
|
|
|
connect(m_toolHandler.get(), &IosToolHandler::didTransferApp, this,
|
|
|
|
|
[this](IosToolHandler *, const FilePath &, const QString &,
|
|
|
|
|
IosToolHandler::OpStatus status) {
|
|
|
|
|
disconnect(m_toolHandler.get(), nullptr, this, nullptr);
|
|
|
|
|
m_toolHandler.release()->deleteLater();
|
|
|
|
|
if (status != IosToolHandler::Success && m_expectSuccess) {
|
|
|
|
|
TaskHub::addTask(DeploymentTask(Task::Error, Tr::tr("Deployment failed. "
|
|
|
|
|
"The settings in the Devices window of Xcode might be incorrect.")));
|
|
|
|
|
}
|
2023-11-15 10:33:31 +01:00
|
|
|
emit done(toDoneResult(status == IosToolHandler::Success));
|
2023-07-14 11:37:50 +02:00
|
|
|
});
|
|
|
|
|
connect(m_toolHandler.get(), &IosToolHandler::finished, this, [this] {
|
|
|
|
|
disconnect(m_toolHandler.get(), nullptr, this, nullptr);
|
|
|
|
|
m_toolHandler.release()->deleteLater();
|
|
|
|
|
TaskHub::addTask(DeploymentTask(Task::Error, Tr::tr("Deployment failed.")));
|
2023-11-15 10:33:31 +01:00
|
|
|
emit done(DoneResult::Error);
|
2023-07-14 11:37:50 +02:00
|
|
|
});
|
|
|
|
|
m_toolHandler->requestTransferApp(m_bundlePath, m_deviceType->identifier);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
signals:
|
2023-11-15 10:33:31 +01:00
|
|
|
void done(DoneResult result);
|
2023-07-14 11:37:50 +02:00
|
|
|
void progressValueChanged(int progress, const QString &info); // progress in %
|
|
|
|
|
void errorMessage(const QString &message);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::optional<IosDeviceType> m_deviceType;
|
|
|
|
|
FilePath m_bundlePath;
|
|
|
|
|
bool m_expectSuccess = true;
|
|
|
|
|
std::unique_ptr<IosToolHandler> m_toolHandler;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class IosTransferTaskAdapter : public TaskAdapter<IosTransfer>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
IosTransferTaskAdapter() { connect(task(), &IosTransfer::done, this, &TaskInterface::done); }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void start() final { task()->start(); }
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-17 11:08:21 +02:00
|
|
|
using IosTransferTask = CustomTask<IosTransferTaskAdapter>;
|
2023-07-14 11:37:50 +02:00
|
|
|
|
2024-01-12 15:50:15 +01:00
|
|
|
GroupItem createDeviceCtlDeployTask(
|
|
|
|
|
const IosDevice::ConstPtr &device,
|
|
|
|
|
const FilePath &bundlePath,
|
|
|
|
|
const std::function<void(int)> &progressHandler,
|
|
|
|
|
const std::function<void(QString, std::optional<Task::TaskType>)> &errorHandler)
|
|
|
|
|
{
|
|
|
|
|
const auto onSetup = [=](Process &process) {
|
|
|
|
|
if (!device) {
|
|
|
|
|
TaskHub::addTask(
|
|
|
|
|
DeploymentTask(Task::Error, Tr::tr("Deployment failed. No iOS device found.")));
|
|
|
|
|
return SetupResult::StopWithError;
|
|
|
|
|
}
|
|
|
|
|
process.setCommand({FilePath::fromString("/usr/bin/xcrun"),
|
|
|
|
|
{"devicectl",
|
|
|
|
|
"device",
|
|
|
|
|
"install",
|
|
|
|
|
"app",
|
|
|
|
|
"--device",
|
|
|
|
|
device->uniqueInternalDeviceId(),
|
|
|
|
|
"--quiet",
|
|
|
|
|
"--json-output",
|
|
|
|
|
"-",
|
|
|
|
|
bundlePath.path()}});
|
|
|
|
|
// TODO Use process.setStdOutCallback to parse progress information.
|
|
|
|
|
// Progress information looks like
|
|
|
|
|
// 1%... 2%... 3%... 4%... 5%...
|
|
|
|
|
progressHandler(0);
|
|
|
|
|
return SetupResult::Continue;
|
|
|
|
|
};
|
|
|
|
|
const auto onDone = [=](const Process &process, DoneWith result) -> DoneResult {
|
|
|
|
|
if (result == DoneWith::Cancel) {
|
|
|
|
|
errorHandler(Tr::tr("Deployment canceled."), {});
|
|
|
|
|
return DoneResult::Error;
|
|
|
|
|
}
|
|
|
|
|
if (process.error() != QProcess::UnknownError) {
|
|
|
|
|
errorHandler(Tr::tr("Failed to run devicectl: %1.").arg(process.errorString()),
|
|
|
|
|
Task::Error);
|
|
|
|
|
return DoneResult::Error;
|
|
|
|
|
}
|
|
|
|
|
const QByteArray rawOutput = process.rawStdOut();
|
|
|
|
|
// there can be crap (progress info) at front and/or end
|
|
|
|
|
const int firstCurly = rawOutput.indexOf('{');
|
|
|
|
|
const int start = std::max(firstCurly, 0);
|
|
|
|
|
const int lastCurly = rawOutput.lastIndexOf('}');
|
|
|
|
|
const int end = lastCurly >= 0 ? lastCurly : rawOutput.size() - 1;
|
|
|
|
|
QJsonParseError parseError;
|
|
|
|
|
auto jsonOutput = QJsonDocument::fromJson(rawOutput.sliced(start, end - start + 1),
|
|
|
|
|
&parseError);
|
|
|
|
|
if (jsonOutput.isNull()) {
|
|
|
|
|
// parse error
|
|
|
|
|
errorHandler(Tr::tr("Failed to parse devicectl output: %1.")
|
|
|
|
|
.arg(parseError.errorString()),
|
|
|
|
|
Task::Error);
|
|
|
|
|
return DoneResult::Error;
|
|
|
|
|
}
|
|
|
|
|
const QJsonValue errorValue = jsonOutput["error"];
|
|
|
|
|
if (!errorValue.isUndefined()) {
|
|
|
|
|
// error
|
|
|
|
|
QString error
|
|
|
|
|
= Tr::tr("Deployment failed: %1.")
|
|
|
|
|
.arg(errorValue["userInfo"]["NSLocalizedDescription"]["string"].toString());
|
|
|
|
|
const QJsonValue userInfo
|
|
|
|
|
= errorValue["userInfo"]["NSUnderlyingError"]["error"]["userInfo"];
|
|
|
|
|
const QList<QJsonValue> moreInfo{userInfo["NSLocalizedDescription"]["string"],
|
|
|
|
|
userInfo["NSLocalizedFailureReason"]["string"],
|
|
|
|
|
userInfo["NSLocalizedRecoverySuggestion"]["string"]};
|
|
|
|
|
for (const QJsonValue &v : moreInfo) {
|
|
|
|
|
if (!v.isUndefined())
|
|
|
|
|
error += "\n" + v.toString();
|
|
|
|
|
}
|
|
|
|
|
errorHandler(error, Task::Error);
|
|
|
|
|
return DoneResult::Error;
|
|
|
|
|
}
|
|
|
|
|
if (jsonOutput["result"]["installedApplications"].isUndefined()) {
|
|
|
|
|
// something unexpected happened ... proceed anyway
|
|
|
|
|
errorHandler(
|
|
|
|
|
Tr::tr("devicectl returned unexpected output ... deployment might have failed."),
|
|
|
|
|
Task::Error);
|
|
|
|
|
return DoneResult::Success;
|
|
|
|
|
}
|
|
|
|
|
return DoneResult::Success;
|
|
|
|
|
};
|
|
|
|
|
return ProcessTask(onSetup, onDone);
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-20 13:21:52 +01:00
|
|
|
class IosDeployStep final : public BuildStep
|
|
|
|
|
{
|
|
|
|
|
public:
|
2020-06-26 13:59:38 +02:00
|
|
|
IosDeployStep(BuildStepList *bc, Utils::Id id);
|
2020-02-20 13:21:52 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void cleanup();
|
|
|
|
|
|
2023-11-19 14:50:55 +01:00
|
|
|
GroupItem runRecipe() final;
|
2020-02-20 13:21:52 +01:00
|
|
|
|
|
|
|
|
void updateDisplayNames();
|
|
|
|
|
|
|
|
|
|
bool init() final;
|
2020-10-02 17:53:39 +02:00
|
|
|
QWidget *createConfigWidget() final;
|
2020-02-20 13:21:52 +01:00
|
|
|
IosDevice::ConstPtr iosdevice() const;
|
|
|
|
|
IosSimulator::ConstPtr iossimulator() const;
|
|
|
|
|
|
|
|
|
|
QString deviceId() const;
|
2023-07-14 12:57:23 +02:00
|
|
|
bool checkProvisioningProfile();
|
2020-02-20 13:21:52 +01:00
|
|
|
|
|
|
|
|
IDevice::ConstPtr m_device;
|
|
|
|
|
FilePath m_bundlePath;
|
|
|
|
|
IosDeviceType m_deviceType;
|
|
|
|
|
};
|
|
|
|
|
|
2020-06-26 13:59:38 +02:00
|
|
|
IosDeployStep::IosDeployStep(BuildStepList *parent, Utils::Id id)
|
2019-12-20 17:05:30 +01:00
|
|
|
: BuildStep(parent, id)
|
2013-04-25 16:02:17 +02:00
|
|
|
{
|
2018-10-22 17:56:04 +02:00
|
|
|
setImmutable(true);
|
2014-05-13 16:09:11 +02:00
|
|
|
updateDisplayNames();
|
2016-06-29 19:35:23 +03:00
|
|
|
connect(DeviceManager::instance(), &DeviceManager::updated,
|
|
|
|
|
this, &IosDeployStep::updateDisplayNames);
|
|
|
|
|
connect(target(), &Target::kitChanged,
|
|
|
|
|
this, &IosDeployStep::updateDisplayNames);
|
2014-05-13 16:09:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IosDeployStep::updateDisplayNames()
|
|
|
|
|
{
|
2020-09-07 15:56:18 +02:00
|
|
|
IDevice::ConstPtr dev = DeviceKitAspect::device(kit());
|
2014-05-13 16:09:11 +02:00
|
|
|
const QString devName = dev.isNull() ? IosDevice::name() : dev->displayName();
|
2022-12-20 13:39:23 +01:00
|
|
|
setDisplayName(Tr::tr("Deploy to %1").arg(devName));
|
2013-04-25 16:02:17 +02:00
|
|
|
}
|
|
|
|
|
|
2019-01-10 15:31:44 +01:00
|
|
|
bool IosDeployStep::init()
|
2013-04-25 16:02:17 +02:00
|
|
|
{
|
2020-09-07 15:56:18 +02:00
|
|
|
m_device = DeviceKitAspect::device(kit());
|
2018-11-12 19:55:59 +01:00
|
|
|
auto runConfig = qobject_cast<const IosRunConfiguration *>(
|
|
|
|
|
this->target()->activeRunConfiguration());
|
2014-05-17 22:53:00 +02:00
|
|
|
QTC_ASSERT(runConfig, return false);
|
2019-05-15 15:49:19 +02:00
|
|
|
m_bundlePath = runConfig->bundleDirectory();
|
2016-09-26 12:40:09 +02:00
|
|
|
|
|
|
|
|
if (iosdevice()) {
|
|
|
|
|
m_deviceType = IosDeviceType(IosDeviceType::IosDevice, deviceId());
|
|
|
|
|
} else if (iossimulator()) {
|
|
|
|
|
m_deviceType = runConfig->deviceType();
|
|
|
|
|
} else {
|
2022-12-20 13:39:23 +01:00
|
|
|
emit addOutput(Tr::tr("Error: no device available, deploy failed."),
|
2020-02-20 13:21:52 +01:00
|
|
|
OutputFormat::ErrorMessage);
|
2013-10-07 16:07:16 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2013-04-25 16:02:17 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-14 12:32:06 +02:00
|
|
|
GroupItem IosDeployStep::runRecipe()
|
|
|
|
|
{
|
2024-01-12 15:50:15 +01:00
|
|
|
static const QString transferringMessage = Tr::tr("Transferring application");
|
|
|
|
|
if (iosdevice() && iosdevice()->handler() == IosDevice::Handler::DeviceCtl) {
|
|
|
|
|
const auto handleProgress = [this](int value) { emit progress(value, transferringMessage); };
|
|
|
|
|
const auto handleError = [this](const QString &error,
|
|
|
|
|
const std::optional<Task::TaskType> &taskType) {
|
|
|
|
|
emit addOutput(error, OutputFormat::ErrorMessage);
|
|
|
|
|
if (taskType)
|
|
|
|
|
TaskHub::addTask(DeploymentTask(*taskType, error));
|
|
|
|
|
};
|
|
|
|
|
return createDeviceCtlDeployTask(iosdevice(), m_bundlePath, handleProgress, handleError);
|
|
|
|
|
}
|
|
|
|
|
// otherwise use iostool:
|
2023-07-14 12:32:06 +02:00
|
|
|
const auto onSetup = [this](IosTransfer &transfer) {
|
|
|
|
|
if (m_device.isNull()) {
|
|
|
|
|
TaskHub::addTask(
|
|
|
|
|
DeploymentTask(Task::Error, Tr::tr("Deployment failed. No iOS device found.")));
|
|
|
|
|
return SetupResult::StopWithError;
|
|
|
|
|
}
|
|
|
|
|
transfer.setDeviceType(m_deviceType);
|
|
|
|
|
transfer.setBundlePath(m_bundlePath);
|
|
|
|
|
transfer.setExpectSuccess(checkProvisioningProfile());
|
2024-01-12 15:50:15 +01:00
|
|
|
emit progress(0, transferringMessage);
|
2023-07-14 12:32:06 +02:00
|
|
|
connect(&transfer, &IosTransfer::progressValueChanged, this, &IosDeployStep::progress);
|
|
|
|
|
connect(&transfer, &IosTransfer::errorMessage, this, [this](const QString &message) {
|
|
|
|
|
emit addOutput(message, OutputFormat::ErrorMessage);
|
|
|
|
|
});
|
|
|
|
|
return SetupResult::Continue;
|
|
|
|
|
};
|
|
|
|
|
return IosTransferTask(onSetup);
|
2013-10-07 16:07:16 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-02 17:53:39 +02:00
|
|
|
QWidget *IosDeployStep::createConfigWidget()
|
2013-04-25 16:02:17 +02:00
|
|
|
{
|
2020-10-02 17:53:39 +02:00
|
|
|
auto widget = new QWidget;
|
2019-04-23 18:18:03 +02:00
|
|
|
|
|
|
|
|
widget->setObjectName("IosDeployStepWidget");
|
|
|
|
|
|
|
|
|
|
connect(this, &ProjectConfiguration::displayNameChanged,
|
2020-09-14 12:37:32 +02:00
|
|
|
this, &BuildStep::updateSummary);
|
2019-04-23 18:18:03 +02:00
|
|
|
|
|
|
|
|
return widget;
|
2013-04-25 16:02:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString IosDeployStep::deviceId() const
|
|
|
|
|
{
|
|
|
|
|
if (iosdevice().isNull())
|
|
|
|
|
return QString();
|
|
|
|
|
return iosdevice()->uniqueDeviceID();
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-14 12:57:23 +02:00
|
|
|
bool IosDeployStep::checkProvisioningProfile()
|
2014-05-08 13:43:25 +02:00
|
|
|
{
|
|
|
|
|
IosDevice::ConstPtr device = iosdevice();
|
|
|
|
|
if (device.isNull())
|
2023-07-14 12:57:23 +02:00
|
|
|
return true;
|
2014-05-08 13:43:25 +02:00
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
const FilePath provisioningFilePath = m_bundlePath.pathAppended("embedded.mobileprovision");
|
2014-05-08 13:43:25 +02:00
|
|
|
// the file is a signed plist stored in DER format
|
|
|
|
|
// we simply search for start and end of the plist instead of decoding the DER payload
|
2014-10-24 13:15:54 +02:00
|
|
|
if (!provisioningFilePath.exists())
|
2023-07-14 12:57:23 +02:00
|
|
|
return true;
|
|
|
|
|
|
2014-05-08 13:43:25 +02:00
|
|
|
QFile provisionFile(provisioningFilePath.toString());
|
|
|
|
|
if (!provisionFile.open(QIODevice::ReadOnly))
|
2023-07-14 12:57:23 +02:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
const QByteArray provisionData = provisionFile.readAll();
|
|
|
|
|
const int start = provisionData.indexOf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
2014-05-08 13:43:25 +02:00
|
|
|
int end = provisionData.indexOf("</plist>");
|
|
|
|
|
if (start == -1 || end == -1)
|
2023-07-14 12:57:23 +02:00
|
|
|
return true;
|
2014-05-08 13:43:25 +02:00
|
|
|
|
2023-07-14 12:57:23 +02:00
|
|
|
end += 8;
|
2020-02-20 13:21:52 +01:00
|
|
|
TemporaryFile f("iosdeploy");
|
2014-05-08 13:43:25 +02:00
|
|
|
if (!f.open())
|
2023-07-14 12:57:23 +02:00
|
|
|
return true;
|
|
|
|
|
|
2014-05-08 13:43:25 +02:00
|
|
|
f.write(provisionData.mid(start, end - start));
|
|
|
|
|
f.flush();
|
2023-07-14 12:57:23 +02:00
|
|
|
const QSettings provisionPlist(f.fileName(), QSettings::NativeFormat);
|
2014-05-08 13:43:25 +02:00
|
|
|
if (!provisionPlist.contains(QLatin1String("ProvisionedDevices")))
|
2023-07-14 12:57:23 +02:00
|
|
|
return true;
|
|
|
|
|
|
2020-02-18 17:50:44 +01:00
|
|
|
const QStringList deviceIds = provisionPlist.value("ProvisionedDevices").toStringList();
|
|
|
|
|
const QString targetId = device->uniqueDeviceID();
|
|
|
|
|
for (const QString &deviceId : deviceIds) {
|
2014-05-08 13:43:25 +02:00
|
|
|
if (deviceId == targetId)
|
2023-07-14 12:57:23 +02:00
|
|
|
return true;
|
2014-05-08 13:43:25 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-13 11:19:23 +02:00
|
|
|
const QString provisioningProfile = provisionPlist.value(QLatin1String("Name")).toString();
|
|
|
|
|
const QString provisioningUid = provisionPlist.value(QLatin1String("UUID")).toString();
|
2023-07-14 12:57:23 +02:00
|
|
|
const CompileTask task(Task::Warning,
|
2022-12-20 13:39:23 +01:00
|
|
|
Tr::tr("The provisioning profile \"%1\" (%2) used to sign the application "
|
2023-07-14 12:57:23 +02:00
|
|
|
"does not cover the device %3 (%4). Deployment to it will fail.")
|
|
|
|
|
.arg(provisioningProfile, provisioningUid, device->displayName(), targetId));
|
2014-05-08 13:43:25 +02:00
|
|
|
emit addTask(task);
|
2023-07-14 12:57:23 +02:00
|
|
|
return false;
|
2014-05-08 13:43:25 +02:00
|
|
|
}
|
|
|
|
|
|
2013-04-25 16:02:17 +02:00
|
|
|
IosDevice::ConstPtr IosDeployStep::iosdevice() const
|
|
|
|
|
{
|
|
|
|
|
return m_device.dynamicCast<const IosDevice>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IosSimulator::ConstPtr IosDeployStep::iossimulator() const
|
|
|
|
|
{
|
|
|
|
|
return m_device.dynamicCast<const IosSimulator>();
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-20 13:21:52 +01:00
|
|
|
// IosDeployStepFactory
|
|
|
|
|
|
|
|
|
|
IosDeployStepFactory::IosDeployStepFactory()
|
|
|
|
|
{
|
2020-08-18 11:33:37 +02:00
|
|
|
registerStep<IosDeployStep>(Constants::IOS_DEPLOY_STEP_ID);
|
2022-12-20 13:39:23 +01:00
|
|
|
setDisplayName(Tr::tr("Deploy to iOS device"));
|
2020-02-20 13:21:52 +01:00
|
|
|
setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY);
|
|
|
|
|
setSupportedDeviceTypes({Constants::IOS_DEVICE_TYPE, Constants::IOS_SIMULATOR_TYPE});
|
|
|
|
|
setRepeatable(false);
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-20 13:39:23 +01:00
|
|
|
} // Ios::Internal
|
2023-07-14 11:37:50 +02:00
|
|
|
|
|
|
|
|
#include "iosdeploystep.moc"
|