QbsRunConfiguration: Re-model based on RemoteLinux precedence

Task-number: QTCREATORBUG-19985
Change-Id: Ifd95187b72fed3565552ecd14f3353b7e7df0069
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
hjk
2018-02-21 12:30:09 +01:00
parent 7bbe5979a1
commit 9541aa7772
8 changed files with 199 additions and 255 deletions

View File

@@ -28,6 +28,7 @@
#include "projectexplorer_export.h" #include "projectexplorer_export.h"
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <QList> #include <QList>
@@ -40,28 +41,32 @@ class PROJECTEXPLORER_EXPORT BuildTargetInfo
public: public:
BuildTargetInfo() = default; BuildTargetInfo() = default;
BuildTargetInfo(const QString &targetName, const Utils::FileName &targetFilePath, BuildTargetInfo(const QString &targetName, const Utils::FileName &targetFilePath,
const Utils::FileName &projectFilePath) : const Utils::FileName &projectFilePath, bool isQtcRunnable = true) :
targetName(targetName), targetName(targetName),
targetFilePath(targetFilePath), targetFilePath(targetFilePath),
projectFilePath(projectFilePath) projectFilePath(projectFilePath),
isQtcRunnable(isQtcRunnable)
{ } { }
QString targetName; QString targetName;
QString displayName; QString displayName;
QString buildKey; // Used to identify this BuildTargetInfo object in its list.
Utils::FileName targetFilePath; Utils::FileName targetFilePath;
Utils::FileName projectFilePath; Utils::FileName projectFilePath;
bool isQtcRunnable = true;
bool isAutoRunnable = true;
bool usesTerminal = false; bool usesTerminal = false;
bool isValid() const { return !targetName.isEmpty(); } std::function<void(Utils::Environment &, bool)> runEnvModifier;
}; };
inline bool operator==(const BuildTargetInfo &ti1, const BuildTargetInfo &ti2) inline bool operator==(const BuildTargetInfo &ti1, const BuildTargetInfo &ti2)
{ {
return ti1.targetName == ti2.targetName && ti1.targetFilePath == ti2.targetFilePath return ti1.targetName == ti2.targetName
&& ti1.projectFilePath == ti2.projectFilePath; && ti1.displayName == ti2.displayName
&& ti1.buildKey == ti2.buildKey
&& ti1.targetFilePath == ti2.targetFilePath
&& ti1.projectFilePath == ti2.projectFilePath;
} }
inline bool operator!=(const BuildTargetInfo &ti1, const BuildTargetInfo &ti2) inline bool operator!=(const BuildTargetInfo &ti1, const BuildTargetInfo &ti2)
@@ -71,7 +76,7 @@ inline bool operator!=(const BuildTargetInfo &ti1, const BuildTargetInfo &ti2)
inline uint qHash(const BuildTargetInfo &ti) inline uint qHash(const BuildTargetInfo &ti)
{ {
return qHash(ti.targetName); return qHash(ti.targetName) ^ qHash(ti.displayName) ^ qHash(ti.buildKey);
} }
class PROJECTEXPLORER_EXPORT BuildTargetInfoList class PROJECTEXPLORER_EXPORT BuildTargetInfoList
@@ -104,6 +109,12 @@ public:
}).targetFilePath; }).targetFilePath;
} }
BuildTargetInfo buildTargetInfo(const QString &buildKey) {
return Utils::findOrDefault(list, [&buildKey](const BuildTargetInfo &ti) {
return ti.buildKey == buildKey;
});
}
QList<BuildTargetInfo> list; QList<BuildTargetInfo> list;
}; };

View File

@@ -470,14 +470,20 @@ QString RunConfigurationFactory::decoratedTargetName(const QString targetName, T
QList<RunConfigurationCreationInfo> QList<RunConfigurationCreationInfo>
RunConfigurationFactory::availableCreators(Target *parent) const RunConfigurationFactory::availableCreators(Target *parent) const
{ {
return Utils::transform(parent->applicationTargets().list, [parent, this](const BuildTargetInfo &ti) { const QList<BuildTargetInfo> buildTargets = parent->applicationTargets().list;
const bool hasAnyQtcRunnable = Utils::anyOf(buildTargets,
Utils::equal(&BuildTargetInfo::isQtcRunnable, true));
return Utils::transform(buildTargets, [&](const BuildTargetInfo &ti) {
QString displayName = ti.displayName; QString displayName = ti.displayName;
if (displayName.isEmpty()) if (displayName.isEmpty())
displayName = decoratedTargetName(ti.targetName, parent); displayName = decoratedTargetName(ti.targetName, parent);
return RunConfigurationCreationInfo(this, m_runConfigBaseId, ti.targetName, displayName, RunConfigurationCreationInfo rci(this, m_runConfigBaseId, ti.targetName, displayName);
ti.isAutoRunnable ? RunConfigurationCreationInfo::AlwaysCreate rci.creationMode = ti.isQtcRunnable || !hasAnyQtcRunnable
: RunConfigurationCreationInfo::ManualCreationOnly, ? RunConfigurationCreationInfo::AlwaysCreate
ti.usesTerminal); : RunConfigurationCreationInfo::ManualCreationOnly;
rci.useTerminal = ti.usesTerminal;
rci.buildKey = ti.buildKey;
return rci;
}); });
} }

View File

@@ -302,6 +302,7 @@ public:
Core::Id id; Core::Id id;
QString extra; QString extra;
QString displayName; QString displayName;
QString buildKey;
CreationMode creationMode = AlwaysCreate; CreationMode creationMode = AlwaysCreate;
bool useTerminal = false; bool useTerminal = false;
}; };

View File

@@ -563,7 +563,8 @@ void Target::updateDefaultRunConfigurations()
foreach (RunConfiguration *rc, existingConfigured) { foreach (RunConfiguration *rc, existingConfigured) {
bool present = false; bool present = false;
for (const RunConfigurationCreationInfo &item : creators) { for (const RunConfigurationCreationInfo &item : creators) {
if (item.id == rc->id() && item.extra == rc->extraId()) { QString rcExtraId = rc->extraId();
if (item.id == rc->id() && (item.extra == rcExtraId || item.buildKey == rcExtraId)) {
existing.append(item); existing.append(item);
present = true; present = true;
} }

View File

@@ -94,6 +94,8 @@ static const char CONFIG_SYSTEM_INCLUDEPATHS[] = "systemIncludePaths";
static const char CONFIG_FRAMEWORKPATHS[] = "frameworkPaths"; static const char CONFIG_FRAMEWORKPATHS[] = "frameworkPaths";
static const char CONFIG_SYSTEM_FRAMEWORKPATHS[] = "systemFrameworkPaths"; static const char CONFIG_SYSTEM_FRAMEWORKPATHS[] = "systemFrameworkPaths";
static QString rcNameSeparator() { return QLatin1String("---Qbs.RC.NameSeparator---"); }
class OpTimer class OpTimer
{ {
public: public:
@@ -135,10 +137,18 @@ QbsProject::QbsProject(const FileName &fileName) :
rebuildProjectTree(); rebuildProjectTree();
connect(this, &Project::activeTargetChanged, this, &QbsProject::changeActiveTarget); connect(this, &Project::activeTargetChanged, this, &QbsProject::changeActiveTarget);
connect(this, &Project::addedTarget, connect(this, &Project::addedTarget, this, [this](Target *t) {
this, [this](Target *t) { m_qbsProjects.insert(t, qbs::Project()); }); m_qbsProjects.insert(t, qbs::Project());
connect(this, &Project::removedTarget, });
this, [this](Target *t) {m_qbsProjects.remove(t); }); connect(this, &Project::removedTarget, this, [this](Target *t) {
const auto it = m_qbsProjects.find(t);
QTC_ASSERT(it != m_qbsProjects.end(), return);
if (it.value() == m_qbsProject) {
m_qbsProject = qbs::Project();
m_projectData = qbs::ProjectData();
}
m_qbsProjects.erase(it);
});
auto delayedParsing = [this]() { auto delayedParsing = [this]() {
if (static_cast<ProjectConfiguration *>(sender())->isActive()) if (static_cast<ProjectConfiguration *>(sender())->isActive())
delayParsing(); delayParsing();
@@ -1104,20 +1114,52 @@ void QbsProject::updateApplicationTargets()
foreach (const qbs::ProductData &productData, m_projectData.allProducts()) { foreach (const qbs::ProductData &productData, m_projectData.allProducts()) {
if (!productData.isEnabled() || !productData.isRunnable()) if (!productData.isEnabled() || !productData.isRunnable())
continue; continue;
const QString displayName = productData.fullDisplayName(); const bool isQtcRunnable = productData.properties().value("qtcRunnable").toBool();
QString taName; const bool usesTerminal = productData.properties().value("consoleApplication").toBool();
const QString projectFile = productData.location().filePath();
QString targetFile;
foreach (const qbs::ArtifactData &ta, productData.targetArtifacts()) { foreach (const qbs::ArtifactData &ta, productData.targetArtifacts()) {
QTC_ASSERT(ta.isValid(), continue); QTC_ASSERT(ta.isValid(), continue);
if (ta.isExecutable()) { if (ta.isExecutable()) {
taName = ta.filePath(); targetFile = ta.filePath();
break; break;
} }
} }
applications.list BuildTargetInfo bti;
<< BuildTargetInfo(displayName, FileName::fromString(taName), bti.targetName = productData.fullDisplayName();
FileName::fromString(productData.location().filePath())); bti.buildKey = QbsProject::uniqueProductName(productData)
+ rcNameSeparator()
+ productData.fullDisplayName();
bti.targetFilePath = FileName::fromString(targetFile);
bti.projectFilePath = FileName::fromString(projectFile);
bti.isQtcRunnable = isQtcRunnable; // Fixed up below.
bti.usesTerminal = usesTerminal;
bti.displayName = productData.fullDisplayName();
bti.runEnvModifier = [targetFile, productData, this](Utils::Environment &env, bool usingLibraryPaths) {
QProcessEnvironment procEnv = env.toProcessEnvironment();
procEnv.insert(QLatin1String("QBS_RUN_FILE_PATH"), targetFile);
QStringList setupRunEnvConfig;
if (!usingLibraryPaths)
setupRunEnvConfig << QLatin1String("ignore-lib-dependencies");
qbs::RunEnvironment qbsRunEnv = qbsProject().getRunEnvironment(productData,
qbs::InstallOptions(), procEnv, setupRunEnvConfig, QbsManager::settings());
qbs::ErrorInfo error;
procEnv = qbsRunEnv.runEnvironment(&error);
if (error.hasError()) {
Core::MessageManager::write(tr("Error retrieving run environment: %1")
.arg(error.toString()));
}
if (!procEnv.isEmpty()) {
env = Utils::Environment();
foreach (const QString &key, procEnv.keys())
env.set(key, procEnv.value(key));
}
};
applications.list.append(bti);
} }
activeTarget()->setApplicationTargets(applications); if (activeTarget())
activeTarget()->setApplicationTargets(applications);
} }
void QbsProject::updateDeploymentInfo() void QbsProject::updateDeploymentInfo()
@@ -1129,7 +1171,8 @@ void QbsProject::updateDeploymentInfo()
f.isExecutable() ? DeployableFile::TypeExecutable : DeployableFile::TypeNormal); f.isExecutable() ? DeployableFile::TypeExecutable : DeployableFile::TypeNormal);
} }
} }
activeTarget()->setDeploymentData(deploymentData); if (activeTarget())
activeTarget()->setDeploymentData(deploymentData);
} }
void QbsProject::updateBuildTargetData() void QbsProject::updateBuildTargetData()

View File

@@ -141,8 +141,8 @@ private:
const QStringList &productNames, QString &error); const QStringList &productNames, QString &error);
QHash<ProjectExplorer::Target *, qbs::Project> m_qbsProjects; QHash<ProjectExplorer::Target *, qbs::Project> m_qbsProjects;
qbs::Project m_qbsProject; qbs::Project m_qbsProject; // for activeTarget()
qbs::ProjectData m_projectData; qbs::ProjectData m_projectData; // Cached m_qbsProject.projectData()
QSet<Core::IDocument *> m_qbsDocuments; QSet<Core::IDocument *> m_qbsDocuments;
QbsProjectParser *m_qbsProjectParser; QbsProjectParser *m_qbsProjectParser;

View File

@@ -26,42 +26,34 @@
#include "qbsrunconfiguration.h" #include "qbsrunconfiguration.h"
#include "qbsprojectmanagerconstants.h" #include "qbsprojectmanagerconstants.h"
#include "qbsdeployconfigurationfactory.h"
#include "qbsinstallstep.h"
#include "qbsproject.h"
#include <coreplugin/messagemanager.h> #include <coreplugin/messagemanager.h>
#include <coreplugin/variablechooser.h> #include <coreplugin/variablechooser.h>
#include <projectexplorer/buildmanager.h> #include <projectexplorer/buildmanager.h>
#include <projectexplorer/buildstep.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/deployconfiguration.h> #include <projectexplorer/deployconfiguration.h>
#include <projectexplorer/localenvironmentaspect.h> #include <projectexplorer/localenvironmentaspect.h>
#include <projectexplorer/project.h>
#include <projectexplorer/runconfigurationaspects.h> #include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <utils/algorithm.h> #include <qtsupport/qtkitinformation.h>
#include <utils/qtcprocess.h>
#include <utils/pathchooser.h>
#include <utils/detailswidget.h>
#include <utils/stringutils.h>
#include <utils/persistentsettings.h>
#include <utils/utilsicons.h>
#include <qtsupport/qtoutputformatter.h> #include <qtsupport/qtoutputformatter.h>
#include <qtsupport/qtsupportconstants.h> #include <qtsupport/qtsupportconstants.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/algorithm.h>
#include <utils/detailswidget.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/pathchooser.h>
#include <utils/persistentsettings.h>
#include <utils/stringutils.h>
#include <utils/utilsicons.h>
#include "api/runenvironment.h" #include <QCheckBox>
#include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QFormLayout> #include <QFormLayout>
#include <QLabel> #include <QLabel>
#include <QLineEdit>
#include <QCheckBox>
#include <QToolButton>
#include <QComboBox>
#include <QDir>
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
@@ -75,15 +67,6 @@ static QString rcNameSeparator() { return QLatin1String("---Qbs.RC.NameSeparator
static QString usingLibraryPathsKey() { return QString("Qbs.RunConfiguration.UsingLibraryPaths"); } static QString usingLibraryPathsKey() { return QString("Qbs.RunConfiguration.UsingLibraryPaths"); }
const qbs::ProductData findProduct(const qbs::ProjectData &pro, const QString &uniqeName)
{
foreach (const qbs::ProductData &product, pro.allProducts()) {
if (QbsProject::uniqueProductName(product) == uniqeName)
return product;
}
return qbs::ProductData();
}
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// QbsRunConfiguration: // QbsRunConfiguration:
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@@ -96,22 +79,22 @@ QbsRunConfiguration::QbsRunConfiguration(Target *target)
static_cast<QbsRunConfiguration *>(rc)->addToBaseEnvironment(env); static_cast<QbsRunConfiguration *>(rc)->addToBaseEnvironment(env);
}); });
addExtraAspect(envAspect); addExtraAspect(envAspect);
connect(static_cast<QbsProject *>(target->project()), &Project::parsingFinished, this,
connect(project(), &Project::parsingFinished, this,
[envAspect]() { envAspect->buildEnvironmentHasChanged(); }); [envAspect]() { envAspect->buildEnvironmentHasChanged(); });
addExtraAspect(new ArgumentsAspect(this, "Qbs.RunConfiguration.CommandLineArguments")); addExtraAspect(new ArgumentsAspect(this, "Qbs.RunConfiguration.CommandLineArguments"));
addExtraAspect(new WorkingDirectoryAspect(this, "Qbs.RunConfiguration.WorkingDirectory")); addExtraAspect(new WorkingDirectoryAspect(this, "Qbs.RunConfiguration.WorkingDirectory"));
addExtraAspect(new TerminalAspect(this, "Qbs.RunConfiguration.UseTerminal", isConsoleApplication())); addExtraAspect(new TerminalAspect(this, "Qbs.RunConfiguration.UseTerminal", isConsoleApplication()));
QbsProject *project = static_cast<QbsProject *>(target->project()); connect(project(), &Project::parsingFinished, this, [this](bool success) {
connect(project, &Project::parsingFinished, this, [this](bool success) {
auto terminalAspect = extraAspect<TerminalAspect>(); auto terminalAspect = extraAspect<TerminalAspect>();
if (success && !terminalAspect->isUserSet()) if (success && !terminalAspect->isUserSet())
terminalAspect->setUseTerminal(isConsoleApplication()); terminalAspect->setUseTerminal(isConsoleApplication());
}); });
connect(BuildManager::instance(), &BuildManager::buildStateChanged, this, connect(BuildManager::instance(), &BuildManager::buildStateChanged, this,
[this, project](Project *p) { [this](Project *p) {
if (p == project && !BuildManager::isBuilding(p)) { if (p == project() && !BuildManager::isBuilding(p)) {
const QString defaultWorkingDir = baseWorkingDirectory(); const QString defaultWorkingDir = baseWorkingDirectory();
if (!defaultWorkingDir.isEmpty()) { if (!defaultWorkingDir.isEmpty()) {
extraAspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory( extraAspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(
@@ -122,8 +105,17 @@ QbsRunConfiguration::QbsRunConfiguration(Target *target)
} }
); );
connect(target, &Target::activeDeployConfigurationChanged, connect(target, &Target::deploymentDataChanged,
this, &QbsRunConfiguration::installStepChanged); this, &QbsRunConfiguration::handleBuildSystemDataUpdated);
connect(target, &Target::applicationTargetsChanged,
this, &QbsRunConfiguration::handleBuildSystemDataUpdated);
// Handles device changes, etc.
connect(target, &Target::kitChanged,
this, &QbsRunConfiguration::handleBuildSystemDataUpdated);
}
QbsRunConfiguration::~QbsRunConfiguration()
{
} }
QVariantMap QbsRunConfiguration::toMap() const QVariantMap QbsRunConfiguration::toMap() const
@@ -138,16 +130,14 @@ bool QbsRunConfiguration::fromMap(const QVariantMap &map)
if (!RunConfiguration::fromMap(map)) if (!RunConfiguration::fromMap(map))
return false; return false;
QString extraId = ProjectExplorer::idFromMap(map).suffixAfter(id()); m_buildKey = ProjectExplorer::idFromMap(map).suffixAfter(id());
if (!extraId.isEmpty()) { m_usingLibraryPaths = map.value(usingLibraryPathsKey(), true).toBool();
const int sepPos = extraId.indexOf(rcNameSeparator());
m_uniqueProductName = extraId.left(sepPos); const int sepPos = m_buildKey.indexOf(rcNameSeparator());
m_productDisplayName = sepPos == -1 ? QString() : extraId.mid(sepPos + rcNameSeparator().size()); m_productDisplayName = sepPos == -1 ? QString() : m_buildKey.mid(sepPos + rcNameSeparator().size());
} m_uniqueProductName = m_buildKey.left(sepPos);
setDefaultDisplayName(defaultDisplayName()); setDefaultDisplayName(defaultDisplayName());
m_usingLibraryPaths = map.value(usingLibraryPathsKey(), true).toBool();
installStepChanged();
return true; return true;
} }
@@ -157,59 +147,22 @@ QString QbsRunConfiguration::extraId() const
return m_uniqueProductName + rcNameSeparator() + m_productDisplayName; return m_uniqueProductName + rcNameSeparator() + m_productDisplayName;
} }
void QbsRunConfiguration::doAdditionalSetup(const RunConfigurationCreationInfo &rci)
{
m_buildKey = rci.buildKey;
const int sepPos = m_buildKey.indexOf(rcNameSeparator());
m_productDisplayName = sepPos == -1 ? QString() : m_buildKey.mid(sepPos + rcNameSeparator().size());
m_uniqueProductName = m_buildKey.left(sepPos);
setDefaultDisplayName(defaultDisplayName());
}
QWidget *QbsRunConfiguration::createConfigurationWidget() QWidget *QbsRunConfiguration::createConfigurationWidget()
{ {
return new QbsRunConfigurationWidget(this); return new QbsRunConfigurationWidget(this);
} }
void QbsRunConfiguration::installStepChanged()
{
if (m_currentInstallStep) {
disconnect(m_currentInstallStep, &QbsInstallStep::changed,
this, &QbsRunConfiguration::targetInformationChanged);
}
if (m_currentBuildStepList) {
disconnect(m_currentBuildStepList, &BuildStepList::stepInserted,
this, &QbsRunConfiguration::installStepChanged);
disconnect(m_currentBuildStepList, &BuildStepList::stepRemoved,
this, &QbsRunConfiguration::installStepChanged);
disconnect(m_currentBuildStepList, &BuildStepList::stepMoved,
this, &QbsRunConfiguration::installStepChanged);
}
QbsDeployConfiguration *activeDc = qobject_cast<QbsDeployConfiguration *>(target()->activeDeployConfiguration());
m_currentBuildStepList = activeDc ? activeDc->stepList() : 0;
if (m_currentInstallStep) {
connect(m_currentInstallStep, &QbsInstallStep::changed,
this, &QbsRunConfiguration::targetInformationChanged);
}
if (m_currentBuildStepList) {
connect(m_currentBuildStepList, &BuildStepList::stepInserted,
this, &QbsRunConfiguration::installStepChanged);
connect(m_currentBuildStepList, &BuildStepList::aboutToRemoveStep, this,
&QbsRunConfiguration::installStepToBeRemoved);
connect(m_currentBuildStepList, &BuildStepList::stepRemoved,
this, &QbsRunConfiguration::installStepChanged);
connect(m_currentBuildStepList, &BuildStepList::stepMoved,
this, &QbsRunConfiguration::installStepChanged);
}
emit targetInformationChanged();
}
void QbsRunConfiguration::installStepToBeRemoved(int pos)
{
QTC_ASSERT(m_currentBuildStepList, return);
// TODO: Our logic is rather broken. Users can create as many qbs install steps as they want,
// but we ignore all but the first one.
if (m_currentBuildStepList->steps().at(pos) != m_currentInstallStep)
return;
disconnect(m_currentInstallStep, &QbsInstallStep::changed,
this, &QbsRunConfiguration::targetInformationChanged);
m_currentInstallStep = 0;
}
Runnable QbsRunConfiguration::runnable() const Runnable QbsRunConfiguration::runnable() const
{ {
StandardRunnable r; StandardRunnable r;
@@ -223,20 +176,14 @@ Runnable QbsRunConfiguration::runnable() const
QString QbsRunConfiguration::executable() const QString QbsRunConfiguration::executable() const
{ {
QbsProject *pro = static_cast<QbsProject *>(target()->project()); BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(m_buildKey);
const qbs::ProductData product = findProduct(pro->qbsProjectData(), uniqueProductName()); return bti.targetFilePath.toString();
if (!product.isValid() || !pro->qbsProject().isValid())
return QString();
return product.targetExecutable();
} }
bool QbsRunConfiguration::isConsoleApplication() const bool QbsRunConfiguration::isConsoleApplication() const
{ {
QbsProject *pro = static_cast<QbsProject *>(target()->project()); BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(m_buildKey);
const qbs::ProductData product = findProduct(pro->qbsProjectData(), uniqueProductName()); return bti.usesTerminal;
return product.properties().value(QLatin1String("consoleApplication"), false).toBool();
} }
void QbsRunConfiguration::setUsingLibraryPaths(bool useLibPaths) void QbsRunConfiguration::setUsingLibraryPaths(bool useLibPaths)
@@ -255,35 +202,14 @@ QString QbsRunConfiguration::baseWorkingDirectory() const
void QbsRunConfiguration::addToBaseEnvironment(Utils::Environment &env) const void QbsRunConfiguration::addToBaseEnvironment(Utils::Environment &env) const
{ {
QbsProject *project = static_cast<QbsProject *>(target()->project()); BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(m_buildKey);
if (project && project->qbsProject().isValid()) { if (bti.runEnvModifier)
const qbs::ProductData product = findProduct(project->qbsProjectData(), uniqueProductName()); bti.runEnvModifier(env, m_usingLibraryPaths);
if (product.isValid()) {
QProcessEnvironment procEnv = env.toProcessEnvironment();
procEnv.insert(QLatin1String("QBS_RUN_FILE_PATH"), executable());
QStringList setupRunEnvConfig;
if (!m_usingLibraryPaths)
setupRunEnvConfig << QLatin1String("ignore-lib-dependencies");
qbs::RunEnvironment qbsRunEnv = project->qbsProject().getRunEnvironment(product,
qbs::InstallOptions(), procEnv, setupRunEnvConfig, QbsManager::settings());
qbs::ErrorInfo error;
procEnv = qbsRunEnv.runEnvironment(&error);
if (error.hasError()) {
Core::MessageManager::write(tr("Error retrieving run environment: %1")
.arg(error.toString()));
}
if (!procEnv.isEmpty()) {
env = Utils::Environment();
foreach (const QString &key, procEnv.keys())
env.set(key, procEnv.value(key));
}
}
}
} }
QString QbsRunConfiguration::buildSystemTarget() const QString QbsRunConfiguration::buildSystemTarget() const
{ {
return m_productDisplayName; return m_buildKey;
} }
QString QbsRunConfiguration::uniqueProductName() const QString QbsRunConfiguration::uniqueProductName() const
@@ -304,64 +230,78 @@ Utils::OutputFormatter *QbsRunConfiguration::createOutputFormatter() const
return new QtSupport::QtOutputFormatter(target()->project()); return new QtSupport::QtOutputFormatter(target()->project());
} }
void QbsRunConfiguration::handleBuildSystemDataUpdated()
{
emit targetInformationChanged();
emit enabledChanged();
}
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// QbsRunConfigurationWidget: // QbsRunConfigurationWidget:
// -------------------------------------------------------------------- // --------------------------------------------------------------------
QbsRunConfigurationWidget::QbsRunConfigurationWidget(QbsRunConfiguration *rc) class QbsRunConfigurationWidgetPrivate
: m_rc(rc)
{ {
auto vboxTopLayout = new QVBoxLayout(this); public:
vboxTopLayout->setMargin(0); QbsRunConfiguration *runConfiguration = nullptr;
QLabel *executableLineLabel = nullptr;
};
QbsRunConfigurationWidget::QbsRunConfigurationWidget(QbsRunConfiguration *rc)
: d(new QbsRunConfigurationWidgetPrivate)
{
d->runConfiguration = rc;
auto mainLayout = new QVBoxLayout(this);
mainLayout->setMargin(0);
auto detailsContainer = new Utils::DetailsWidget(this); auto detailsContainer = new Utils::DetailsWidget(this);
detailsContainer->setState(Utils::DetailsWidget::NoSummary); detailsContainer->setState(Utils::DetailsWidget::NoSummary);
vboxTopLayout->addWidget(detailsContainer);
mainLayout->addWidget(detailsContainer);
auto detailsWidget = new QWidget(detailsContainer); auto detailsWidget = new QWidget(detailsContainer);
detailsContainer->setWidget(detailsWidget); detailsContainer->setWidget(detailsWidget);
auto toplayout = new QFormLayout(detailsWidget); auto toplayout = new QFormLayout(detailsWidget);
toplayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); toplayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
toplayout->setMargin(0); toplayout->setMargin(0);
m_executableLineLabel = new QLabel(this); d->executableLineLabel = new QLabel(this);
m_executableLineLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); d->executableLineLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
setExecutableLineText(); toplayout->addRow(tr("Executable:"), d->executableLineLabel);
toplayout->addRow(tr("Executable:"), m_executableLineLabel);
m_rc->extraAspect<ArgumentsAspect>()->addToMainConfigurationWidget(this, toplayout); d->runConfiguration->extraAspect<ArgumentsAspect>()->addToMainConfigurationWidget(this, toplayout);
m_rc->extraAspect<WorkingDirectoryAspect>()->addToMainConfigurationWidget(this, toplayout); d->runConfiguration->extraAspect<WorkingDirectoryAspect>()->addToMainConfigurationWidget(this, toplayout);
d->runConfiguration->extraAspect<TerminalAspect>()->addToMainConfigurationWidget(this, toplayout);
m_rc->extraAspect<TerminalAspect>()->addToMainConfigurationWidget(this, toplayout); auto usingLibPathsCheckBox = new QCheckBox(tr("Add library paths to run environment"));
m_usingLibPathsCheckBox = new QCheckBox(tr("Add library paths to run environment")); usingLibPathsCheckBox->setChecked(d->runConfiguration->usingLibraryPaths());
m_usingLibPathsCheckBox->setChecked(m_rc->usingLibraryPaths()); connect(usingLibPathsCheckBox, &QCheckBox::toggled,
connect(m_usingLibPathsCheckBox, &QCheckBox::toggled, m_rc, d->runConfiguration, &QbsRunConfiguration::setUsingLibraryPaths);
&QbsRunConfiguration::setUsingLibraryPaths); toplayout->addRow(QString(), usingLibPathsCheckBox);
toplayout->addRow(QString(), m_usingLibPathsCheckBox);
connect(m_rc, &QbsRunConfiguration::targetInformationChanged, connect(d->runConfiguration, &QbsRunConfiguration::targetInformationChanged,
this, &QbsRunConfigurationWidget::targetInformationHasChanged, Qt::QueuedConnection); this, &QbsRunConfigurationWidget::targetInformationHasChanged, Qt::QueuedConnection);
connect(m_rc, &RunConfiguration::enabledChanged, connect(d->runConfiguration, &RunConfiguration::enabledChanged,
this, &QbsRunConfigurationWidget::targetInformationHasChanged); this, &QbsRunConfigurationWidget::targetInformationHasChanged);
targetInformationHasChanged();
Core::VariableChooser::addSupportForChildWidgets(this, rc->macroExpander()); Core::VariableChooser::addSupportForChildWidgets(this, rc->macroExpander());
targetInformationHasChanged();
} }
void QbsRunConfigurationWidget::targetInformationHasChanged() void QbsRunConfigurationWidget::targetInformationHasChanged()
{ {
m_ignoreChange = true; WorkingDirectoryAspect *aspect = d->runConfiguration->extraAspect<WorkingDirectoryAspect>();
setExecutableLineText(m_rc->executable()); aspect->pathChooser()->setBaseFileName(d->runConfiguration->target()->project()->projectDirectory());
WorkingDirectoryAspect *aspect = m_rc->extraAspect<WorkingDirectoryAspect>(); QString text = d->runConfiguration->executable();
aspect->pathChooser()->setBaseFileName(m_rc->target()->project()->projectDirectory()); d->executableLineLabel->setText(text.isEmpty() ? tr("<unknown>") : text);
m_ignoreChange = false;
} }
void QbsRunConfigurationWidget::setExecutableLineText(const QString &text) QbsRunConfigurationWidget::~QbsRunConfigurationWidget()
{ {
const QString newText = text.isEmpty() ? tr("<unknown>") : text; delete d;
m_executableLineLabel->setText(newText);
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@@ -375,46 +315,5 @@ QbsRunConfigurationFactory::QbsRunConfigurationFactory()
addSupportedTargetDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE); addSupportedTargetDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
} }
bool QbsRunConfigurationFactory::canCreateHelper(Target *parent, const QString &buildTarget) const
{
QbsProject *project = static_cast<QbsProject *>(parent->project());
QString product = buildTarget.left(buildTarget.indexOf(rcNameSeparator()));
return findProduct(project->qbsProjectData(), product).isValid();
}
QList<RunConfigurationCreationInfo>
QbsRunConfigurationFactory::availableCreators(Target *parent) const
{
QList<qbs::ProductData> products;
QbsProject *project = static_cast<QbsProject *>(parent->project());
if (!project || !project->qbsProject().isValid())
return {};
foreach (const qbs::ProductData &product, project->qbsProjectData().allProducts()) {
if (product.isRunnable() && product.isEnabled())
products << product;
}
const auto isQtcRunnable = [](const qbs::ProductData &product) {
return product.properties().value("qtcRunnable").toBool();
};
const bool hasAnyQtcRunnable = Utils::anyOf(products, isQtcRunnable);
return Utils::transform(products, [&](const qbs::ProductData &product) {
const QString displayName = product.fullDisplayName();
const QString targetName = QbsProject::uniqueProductName(product) + rcNameSeparator() + displayName;
return RunConfigurationCreationInfo {
this,
runConfigurationBaseId(),
targetName,
displayName,
(hasAnyQtcRunnable && !isQtcRunnable(product))
? RunConfigurationCreationInfo::ManualCreationOnly
: RunConfigurationCreationInfo::AlwaysCreate
};
});
}
} // namespace Internal } // namespace Internal
} // namespace QbsProjectManager } // namespace QbsProjectManager

View File

@@ -32,25 +32,19 @@
#include <QStringList> #include <QStringList>
#include <QWidget> #include <QWidget>
namespace qbs { class InstallOptions; }
namespace ProjectExplorer { class BuildStepList; }
namespace QbsProjectManager { namespace QbsProjectManager {
namespace Internal { namespace Internal {
class QbsInstallStep;
class QbsRunConfiguration : public ProjectExplorer::RunConfiguration class QbsRunConfiguration : public ProjectExplorer::RunConfiguration
{ {
Q_OBJECT Q_OBJECT
// to change the display name and arguments and set the userenvironmentchanges // to change the display name and arguments and set the userenvironmentchanges
friend class QbsRunConfigurationWidget; friend class QbsRunConfigurationWidget;
friend class ProjectExplorer::RunConfigurationFactory;
public: public:
explicit QbsRunConfiguration(ProjectExplorer::Target *target); explicit QbsRunConfiguration(ProjectExplorer::Target *target);
~QbsRunConfiguration();
QWidget *createConfigurationWidget() override; QWidget *createConfigurationWidget() override;
@@ -72,22 +66,23 @@ signals:
void usingDyldImageSuffixChanged(bool); void usingDyldImageSuffixChanged(bool);
private: private:
QVariantMap toMap() const final; QVariantMap toMap() const;
bool fromMap(const QVariantMap &map) final; bool fromMap(const QVariantMap &map) final;
QString extraId() const final; QString extraId() const final;
void doAdditionalSetup(const ProjectExplorer::RunConfigurationCreationInfo &rci);
void installStepChanged();
void installStepToBeRemoved(int pos);
QString baseWorkingDirectory() const; QString baseWorkingDirectory() const;
QString defaultDisplayName(); QString defaultDisplayName();
void handleBuildSystemDataUpdated();
void updateTarget();
QbsInstallStep *m_currentInstallStep = nullptr; // We do not take ownership!
ProjectExplorer::BuildStepList *m_currentBuildStepList = nullptr; // We do not take ownership!
QString m_uniqueProductName;
QString m_productDisplayName;
bool m_usingLibraryPaths = true; bool m_usingLibraryPaths = true;
QString m_buildKey;
// m_buildKey consists of the two below initially, but
// m_productDisplayName main be changed for clones etc.
QString m_productDisplayName;
QString m_uniqueProductName;
}; };
class QbsRunConfigurationWidget : public QWidget class QbsRunConfigurationWidget : public QWidget
@@ -95,31 +90,19 @@ class QbsRunConfigurationWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
QbsRunConfigurationWidget(QbsRunConfiguration *rc); explicit QbsRunConfigurationWidget(QbsRunConfiguration *rc);
~QbsRunConfigurationWidget();
private: private:
void runConfigurationEnabledChange();
void targetInformationHasChanged(); void targetInformationHasChanged();
void setExecutableLineText(const QString &text = QString());
QbsRunConfiguration *m_rc; class QbsRunConfigurationWidgetPrivate * const d;
QLabel *m_executableLineLabel;
QCheckBox *m_usingLibPathsCheckBox;
bool m_ignoreChange = false;
bool m_isShown = false;
}; };
class QbsRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory class QbsRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory
{ {
Q_OBJECT
public: public:
QbsRunConfigurationFactory(); QbsRunConfigurationFactory();
bool canCreateHelper(ProjectExplorer::Target *parent, const QString &suffix) const override;
QList<ProjectExplorer::RunConfigurationCreationInfo>
availableCreators(ProjectExplorer::Target *parent) const override;
}; };
} // namespace Internal } // namespace Internal