From 9ae2ce76297ef899e9c4444f736ede4706c7ece4 Mon Sep 17 00:00:00 2001
From: hjk <hjk@theqtcompany.com>
Date: Mon, 25 Jan 2016 15:00:20 +0100
Subject: [PATCH] ProjectExplorer: Drop LocalApplicationRunConfiguration

The functionality can be provided by producing a suitable Runnable
in the derived classes directly.

Change-Id: I7b8e8fe33fffd2b00176b6cf6633eca4e152e466
Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
---
 src/plugins/autotest/testconfiguration.cpp    | 41 ++++++++------
 .../cmakerunconfiguration.cpp                 | 39 +++++---------
 .../cmakerunconfiguration.h                   | 20 ++-----
 src/plugins/debugger/debuggerplugin.cpp       |  2 +-
 src/plugins/debugger/debuggerruncontrol.cpp   | 21 ++++----
 .../debugger/unstartedappwatcherdialog.cpp    | 48 ++++++++++-------
 .../localapplicationrunconfiguration.h        | 54 -------------------
 .../localapplicationruncontrol.cpp            | 30 +++++------
 .../localapplicationruncontrol.h              |  2 -
 .../localenvironmentaspect.cpp                | 17 +++---
 .../projectexplorer/localenvironmentaspect.h  |  5 +-
 .../projectexplorer/projectexplorer.pro       |  3 +-
 .../projectexplorer/projectexplorer.qbs       |  2 +-
 ...cationrunconfiguration.cpp => runnables.h} | 36 ++++++-------
 .../pythoneditor/pythoneditorplugin.cpp       |  2 +-
 .../qbsprojectmanager/qbsrunconfiguration.cpp | 35 ++++++------
 .../qbsprojectmanager/qbsrunconfiguration.h   | 12 ++---
 .../desktopqmakerunconfiguration.cpp          | 39 +++++++-------
 .../desktopqmakerunconfiguration.h            | 12 ++---
 .../qmlprofiler/localqmlprofilerrunner.cpp    |  1 -
 .../qmlprofiler/qmlprofilerruncontrol.cpp     |  2 +-
 .../qmlprofilerruncontrolfactory.cpp          | 24 +++++----
 src/plugins/qmlprofiler/qmlprofilertool.cpp   |  2 +-
 .../qmlprojectrunconfiguration.cpp            | 25 ++++-----
 .../qmlprojectrunconfiguration.h              | 13 ++---
 .../customexecutablerunconfiguration.cpp      | 35 ++++++------
 .../customexecutablerunconfiguration.h        | 12 ++---
 .../valgrind/valgrindruncontrolfactory.cpp    | 26 +++++----
 28 files changed, 243 insertions(+), 317 deletions(-)
 delete mode 100644 src/plugins/projectexplorer/localapplicationrunconfiguration.h
 rename src/plugins/projectexplorer/{localapplicationrunconfiguration.cpp => runnables.h} (67%)

diff --git a/src/plugins/autotest/testconfiguration.cpp b/src/plugins/autotest/testconfiguration.cpp
index 063aa5980ea..e770b238f00 100644
--- a/src/plugins/autotest/testconfiguration.cpp
+++ b/src/plugins/autotest/testconfiguration.cpp
@@ -30,8 +30,9 @@
 
 #include <projectexplorer/buildtargetinfo.h>
 #include <projectexplorer/environmentaspect.h>
-#include <projectexplorer/localapplicationrunconfiguration.h>
+#include <projectexplorer/kitinformation.h>
 #include <projectexplorer/project.h>
+#include <projectexplorer/runnables.h>
 #include <projectexplorer/runconfiguration.h>
 #include <projectexplorer/session.h>
 #include <projectexplorer/target.h>
@@ -94,20 +95,17 @@ void basicProjectInformation(Project *project, const QString &proFile, QString *
     }
 }
 
-void extractEnvironmentInformation(LocalApplicationRunConfiguration *localRunConfiguration,
-                                   QString *workDir, Utils::Environment *env)
+static bool isLocal(RunConfiguration *runConfiguration)
 {
-    *workDir = Utils::FileUtils::normalizePathName(localRunConfiguration->workingDirectory());
-    if (auto environmentAspect = localRunConfiguration->extraAspect<EnvironmentAspect>())
-        *env = environmentAspect->environment();
+    Target *target = runConfiguration ? runConfiguration->target() : 0;
+    Kit *kit = target ? target->kit() : 0;
+    return DeviceTypeKitInformation::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
 }
 
 void TestConfiguration::completeTestInformation()
 {
     QTC_ASSERT(!m_mainFilePath.isEmpty() || !m_proFile.isEmpty(), return);
 
-    typedef LocalApplicationRunConfiguration LocalRunConfig;
-
     Project *project = SessionManager::startupProject();
     if (!project)
         return;
@@ -144,21 +142,30 @@ void TestConfiguration::completeTestInformation()
 
     QList<RunConfiguration *> rcs = target->runConfigurations();
     foreach (RunConfiguration *rc, rcs) {
-        auto config = qobject_cast<LocalRunConfig *>(rc);
-        if (config && config->executable() == targetFile) {
-            extractEnvironmentInformation(config, &workDir, &env);
-            hasDesktopTarget = true;
-            break;
+        Runnable runnable = rc->runnable();
+        if (isLocal(rc) && runnable.is<StandardRunnable>()) {
+            StandardRunnable stdRunnable = runnable.as<StandardRunnable>();
+            if (stdRunnable.executable == targetFile) {
+                workDir = Utils::FileUtils::normalizePathName(stdRunnable.workingDirectory);
+                env = stdRunnable.environment;
+                hasDesktopTarget = true;
+                break;
+            }
         }
     }
 
     // if we could not figure out the run configuration
     // try to use the run configuration of the parent project
     if (!hasDesktopTarget && targetProject && !targetFile.isEmpty()) {
-        if (auto config = qobject_cast<LocalRunConfig *>(target->activeRunConfiguration())) {
-            extractEnvironmentInformation(config, &workDir, &env);
-            hasDesktopTarget = true;
-            guessedRunConfiguration = true;
+        if (auto rc = target->activeRunConfiguration()) {
+            Runnable runnable = rc->runnable();
+            if (isLocal(rc) && runnable.is<StandardRunnable>()) {
+                StandardRunnable stdRunnable = runnable.as<StandardRunnable>();
+                workDir = Utils::FileUtils::normalizePathName(stdRunnable.workingDirectory);
+                env = stdRunnable.environment;
+                hasDesktopTarget = true;
+                guessedRunConfiguration = true;
+            }
         }
     }
 
diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
index d15852a0995..f48209b35b7 100644
--- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
@@ -61,11 +61,11 @@ const char TITLE_KEY[] = "CMakeProjectManager.CMakeRunConfiguation.Title";
 
 CMakeRunConfiguration::CMakeRunConfiguration(Target *parent, Core::Id id, const QString &target,
                                              const QString &workingDirectory, const QString &title) :
-    LocalApplicationRunConfiguration(parent, id),
+    RunConfiguration(parent, id),
     m_buildTarget(target),
     m_title(title)
 {
-    addExtraAspect(new LocalEnvironmentAspect(this));
+    addExtraAspect(new LocalEnvironmentAspect(this, LocalEnvironmentAspect::BaseEnvironmentModifier()));
     addExtraAspect(new ArgumentsAspect(this, QStringLiteral("CMakeProjectManager.CMakeRunConfiguration.Arguments")));
     addExtraAspect(new TerminalAspect(this, QStringLiteral("CMakeProjectManager.CMakeRunConfiguration.UseTerminal")));
 
@@ -77,7 +77,7 @@ CMakeRunConfiguration::CMakeRunConfiguration(Target *parent, Core::Id id, const
 }
 
 CMakeRunConfiguration::CMakeRunConfiguration(Target *parent, CMakeRunConfiguration *source) :
-    LocalApplicationRunConfiguration(parent, source),
+    RunConfiguration(parent, source),
     m_buildTarget(source->m_buildTarget),
     m_title(source->m_title),
     m_enabled(source->m_enabled)
@@ -90,36 +90,25 @@ void CMakeRunConfiguration::ctor()
     setDefaultDisplayName(defaultDisplayName());
 }
 
-QString CMakeRunConfiguration::executable() const
+Runnable CMakeRunConfiguration::runnable() const
 {
-    return m_buildTarget;
-}
-
-ApplicationLauncher::Mode CMakeRunConfiguration::runMode() const
-{
-    return extraAspect<TerminalAspect>()->runMode();
-}
-
-QString CMakeRunConfiguration::workingDirectory() const
-{
-    const auto *wdAspect = extraAspect<WorkingDirectoryAspect>();
-    QTC_ASSERT(wdAspect, return baseWorkingDirectory());
-    return wdAspect->workingDirectory().toString();
+    StandardRunnable r;
+    r.executable = m_buildTarget;
+    r.commandLineArguments = extraAspect<ArgumentsAspect>()->arguments();
+    r.workingDirectory = extraAspect<WorkingDirectoryAspect>()->workingDirectory().toString();
+    r.environment = extraAspect<LocalEnvironmentAspect>()->environment();
+    r.runMode = extraAspect<TerminalAspect>()->runMode();
+    return r;
 }
 
 QString CMakeRunConfiguration::baseWorkingDirectory() const
 {
-    const QString exe = executable();
+    const QString exe = m_buildTarget;
     if (!exe.isEmpty())
-        return QFileInfo(executable()).absolutePath();
+        return QFileInfo(m_buildTarget).absolutePath();
     return QString();
 }
 
-QString CMakeRunConfiguration::commandLineArguments() const
-{
-    return extraAspect<ArgumentsAspect>()->arguments();
-}
-
 QString CMakeRunConfiguration::title() const
 {
     return m_title;
@@ -138,7 +127,7 @@ void CMakeRunConfiguration::setBaseWorkingDirectory(const QString &wd)
 
 QVariantMap CMakeRunConfiguration::toMap() const
 {
-    QVariantMap map(LocalApplicationRunConfiguration::toMap());
+    QVariantMap map(RunConfiguration::toMap());
     map.insert(QLatin1String(TITLE_KEY), m_title);
     return map;
 }
diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h
index eb87684eccc..af531daac29 100644
--- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h
+++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h
@@ -26,24 +26,13 @@
 #ifndef CMAKERUNCONFIGURATION_H
 #define CMAKERUNCONFIGURATION_H
 
-#include <projectexplorer/localapplicationrunconfiguration.h>
+#include <projectexplorer/runnables.h>
 #include <utils/environment.h>
 
-QT_BEGIN_NAMESPACE
-class QComboBox;
-QT_END_NAMESPACE
-
-namespace Utils {
-class PathChooser;
-class DetailsWidget;
-}
-
 namespace CMakeProjectManager {
 namespace Internal {
 
-class CMakeTarget;
-
-class CMakeRunConfiguration : public ProjectExplorer::LocalApplicationRunConfiguration
+class CMakeRunConfiguration : public ProjectExplorer::RunConfiguration
 {
     Q_OBJECT
     friend class CMakeRunConfigurationWidget;
@@ -53,10 +42,7 @@ public:
     CMakeRunConfiguration(ProjectExplorer::Target *parent, Core::Id id, const QString &target,
                           const QString &workingDirectory, const QString &title);
 
-    QString executable() const override;
-    ProjectExplorer::ApplicationLauncher::Mode runMode() const override;
-    QString workingDirectory() const override;
-    QString commandLineArguments() const override;
+    ProjectExplorer::Runnable runnable() const override;
     QWidget *createConfigurationWidget() override;
 
     void setExecutable(const QString &executable);
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index d5f42db84bf..edd6a6fb8ca 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -87,7 +87,6 @@
 
 #include <extensionsystem/invoker.h>
 
-#include <projectexplorer/localapplicationrunconfiguration.h>
 #include <projectexplorer/buildmanager.h>
 #include <projectexplorer/taskhub.h>
 #include <projectexplorer/toolchain.h>
@@ -98,6 +97,7 @@
 #include <projectexplorer/projecttree.h>
 #include <projectexplorer/projectexplorersettings.h>
 #include <projectexplorer/project.h>
+#include <projectexplorer/runnables.h>
 #include <projectexplorer/session.h>
 #include <projectexplorer/target.h>
 
diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp
index 25cbc7d1e33..9f04610e973 100644
--- a/src/plugins/debugger/debuggerruncontrol.cpp
+++ b/src/plugins/debugger/debuggerruncontrol.cpp
@@ -40,9 +40,9 @@
 #include <projectexplorer/devicesupport/deviceprocessesdialog.h>
 #include <projectexplorer/devicesupport/deviceprocesslist.h>
 #include <projectexplorer/environmentaspect.h> // For the environment
-#include <projectexplorer/localapplicationrunconfiguration.h> // For LocalApplication*
 #include <projectexplorer/project.h>
 #include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/runnables.h>
 #include <projectexplorer/target.h>
 #include <projectexplorer/taskhub.h>
 #include <projectexplorer/toolchain.h>
@@ -331,12 +331,13 @@ void DebuggerRunControlCreator::enrich(const RunConfiguration *runConfig, const
         m_runConfig = runConfig;
 
     // Extract as much as possible from available RunConfiguration.
-    if (auto localRc = qobject_cast<const LocalApplicationRunConfiguration *>(m_runConfig)) {
-        m_rp.executable = localRc->executable();
-        m_rp.processArgs = localRc->commandLineArguments();
-        m_rp.useTerminal = localRc->runMode() == ApplicationLauncher::Console;
+    if (m_runConfig->runnable().is<StandardRunnable>()) {
+        auto runnable = m_runConfig->runnable().as<StandardRunnable>();
+        m_rp.executable = runnable.executable;
+        m_rp.processArgs = runnable.commandLineArguments;
+        m_rp.useTerminal = runnable.runMode == ApplicationLauncher::Console;
         // Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...)
-        m_rp.workingDirectory = FileUtils::normalizePathName(localRc->workingDirectory());
+        m_rp.workingDirectory = FileUtils::normalizePathName(runnable.workingDirectory);
     }
 
     // Find a Kit and Target. Either could be missing.
@@ -630,9 +631,11 @@ public:
 
     bool canRun(RunConfiguration *runConfig, Core::Id mode) const override
     {
-        return (mode == DebugRunMode || mode == DebugRunModeWithBreakOnMain)
-            && (qobject_cast<LocalApplicationRunConfiguration *>(runConfig)
-                || isDebuggableScript(runConfig));
+        if (!(mode == DebugRunMode || mode == DebugRunModeWithBreakOnMain))
+            return false;
+        return DeviceTypeKitInformation::deviceTypeId(runConfig->target()->kit())
+                    == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE
+                 || isDebuggableScript(runConfig);
     }
 
     IRunConfigurationAspect *createRunConfigurationAspect(RunConfiguration *rc) override
diff --git a/src/plugins/debugger/unstartedappwatcherdialog.cpp b/src/plugins/debugger/unstartedappwatcherdialog.cpp
index 7e5e323517c..763fba865fa 100644
--- a/src/plugins/debugger/unstartedappwatcherdialog.cpp
+++ b/src/plugins/debugger/unstartedappwatcherdialog.cpp
@@ -38,7 +38,7 @@
 #include <projectexplorer/projecttree.h>
 #include <projectexplorer/runconfiguration.h>
 #include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/localapplicationrunconfiguration.h>
+#include <projectexplorer/runnables.h>
 
 #include <QVBoxLayout>
 #include <QHBoxLayout>
@@ -56,6 +56,13 @@ using namespace ProjectExplorer;
 namespace Debugger {
 namespace Internal {
 
+static bool isLocal(RunConfiguration *runConfiguration)
+{
+    Target *target = runConfiguration ? runConfiguration->target() : 0;
+    Kit *kit = target ? target->kit() : 0;
+    return DeviceTypeKitInformation::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
+}
+
 /*!
     \class Debugger::Internal::UnstartedAppWatcherDialog
 
@@ -88,8 +95,11 @@ UnstartedAppWatcherDialog::UnstartedAppWatcherDialog(QWidget *parent)
     m_kitChooser->setVisible(true);
 
     Project *project = ProjectTree::currentProject();
-    if (project && project->activeTarget() && project->activeTarget()->kit())
-        m_kitChooser->setCurrentKitId(project->activeTarget()->kit()->id());
+    Target *activeTarget = project ? project->activeTarget() : 0;
+    Kit *kit = activeTarget ? activeTarget->kit() : 0;
+
+    if (kit)
+        m_kitChooser->setCurrentKitId(kit->id());
     else if (KitManager::defaultKit())
         m_kitChooser->setCurrentKitId(KitManager::defaultKit()->id());
 
@@ -97,13 +107,12 @@ UnstartedAppWatcherDialog::UnstartedAppWatcherDialog(QWidget *parent)
     m_pathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
     m_pathChooser->setHistoryCompleter(QLatin1String("LocalExecutable"));
 
-    if (project && project->activeTarget() && project->activeTarget()->activeRunConfiguration()) {
-        LocalApplicationRunConfiguration *localAppRC =
-                qobject_cast<LocalApplicationRunConfiguration *>
-                             (project->activeTarget()->activeRunConfiguration());
-
-        if (localAppRC)
-            m_pathChooser->setPath(localAppRC->executable());
+    if (activeTarget) {
+        if (RunConfiguration *runConfig = activeTarget->activeRunConfiguration()) {
+            const Runnable runnable = runConfig->runnable();
+            if (runnable.is<StandardRunnable>() && isLocal(runConfig))
+                m_pathChooser->setPath(runnable.as<StandardRunnable>().executable);
+        }
     }
 
     m_hideOnAttachCheckBox = new QCheckBox(tr("Reopen dialog when application finishes"), this);
@@ -171,20 +180,19 @@ void UnstartedAppWatcherDialog::selectExecutable()
     QString path;
 
     Project *project = ProjectTree::currentProject();
+    Target *activeTarget = project ? project->activeTarget() : 0;
 
-    if (project && project->activeTarget() && project->activeTarget()->activeRunConfiguration()) {
-
-        LocalApplicationRunConfiguration *localAppRC =
-                qobject_cast<LocalApplicationRunConfiguration *>
-                             (project->activeTarget()->activeRunConfiguration());
-        if (localAppRC)
-            path = QFileInfo(localAppRC->executable()).path();
+    if (activeTarget) {
+        if (RunConfiguration *runConfig = activeTarget->activeRunConfiguration()) {
+            const Runnable runnable = runConfig->runnable();
+            if (runnable.is<StandardRunnable>() && isLocal(runConfig))
+                path = QFileInfo(runnable.as<StandardRunnable>().executable).path();
+        }
     }
 
     if (path.isEmpty()) {
-        if (project && project->activeTarget() &&
-                project->activeTarget()->activeBuildConfiguration()) {
-            path = project->activeTarget()->activeBuildConfiguration()->buildDirectory().toString();
+        if (activeTarget && activeTarget->activeBuildConfiguration()) {
+            path = activeTarget->activeBuildConfiguration()->buildDirectory().toString();
         } else if (project) {
             path = project->projectDirectory().toString();
         }
diff --git a/src/plugins/projectexplorer/localapplicationrunconfiguration.h b/src/plugins/projectexplorer/localapplicationrunconfiguration.h
deleted file mode 100644
index 21778dc5a84..00000000000
--- a/src/plugins/projectexplorer/localapplicationrunconfiguration.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#ifndef LOCALAPPLICATIONRUNCONFIGURATION_H
-#define LOCALAPPLICATIONRUNCONFIGURATION_H
-
-#include "runconfiguration.h"
-#include "applicationlauncher.h"
-
-namespace Utils { class Environment; }
-
-namespace ProjectExplorer {
-
-class PROJECTEXPLORER_EXPORT LocalApplicationRunConfiguration : public RunConfiguration
-{
-    Q_OBJECT
-public:
-    virtual QString executable() const = 0;
-    virtual ApplicationLauncher::Mode runMode() const = 0;
-    virtual QString workingDirectory() const = 0;
-    virtual QString commandLineArguments() const = 0;
-
-    virtual void addToBaseEnvironment(Utils::Environment &env) const;
-
-protected:
-    explicit LocalApplicationRunConfiguration(Target *target, Core::Id id);
-    explicit LocalApplicationRunConfiguration(Target *target, LocalApplicationRunConfiguration *rc);
-};
-
-} // namespace ProjectExplorer
-
-#endif // LOCALAPPLICATIONRUNCONFIGURATION_H
diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.cpp b/src/plugins/projectexplorer/localapplicationruncontrol.cpp
index de39eb0bba8..bf7ea838e83 100644
--- a/src/plugins/projectexplorer/localapplicationruncontrol.cpp
+++ b/src/plugins/projectexplorer/localapplicationruncontrol.cpp
@@ -24,11 +24,14 @@
 ****************************************************************************/
 
 #include "localapplicationruncontrol.h"
-#include "localapplicationrunconfiguration.h"
+#include "runnables.h"
 #include "environmentaspect.h"
 
 #include <projectexplorer/projectexplorerconstants.h>
 #include <projectexplorer/projectexplorericons.h>
+#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/target.h>
+
 #include <utils/qtcassert.h>
 #include <utils/environment.h>
 
@@ -37,30 +40,27 @@
 namespace ProjectExplorer {
 namespace Internal {
 
-LocalApplicationRunControlFactory::LocalApplicationRunControlFactory()
-{
-}
-
-LocalApplicationRunControlFactory::~LocalApplicationRunControlFactory()
+static bool isLocal(RunConfiguration *runConfiguration)
 {
+    Target *target = runConfiguration ? runConfiguration->target() : 0;
+    Kit *kit = target ? target->kit() : 0;
+    return DeviceTypeKitInformation::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
 }
 
 bool LocalApplicationRunControlFactory::canRun(RunConfiguration *runConfiguration, Core::Id mode) const
 {
-    return mode == Constants::NORMAL_RUN_MODE && qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
+    return mode == Constants::NORMAL_RUN_MODE && isLocal(runConfiguration);
 }
 
 RunControl *LocalApplicationRunControlFactory::create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage)
 {
     Q_UNUSED(errorMessage)
-    QTC_ASSERT(canRun(runConfiguration, mode), return 0);
-    LocalApplicationRunConfiguration *localRunConfiguration = qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
-
-    QTC_ASSERT(localRunConfiguration, return 0);
-    LocalApplicationRunControl *runControl = new LocalApplicationRunControl(localRunConfiguration, mode);
-    runControl->setCommand(localRunConfiguration->executable(), localRunConfiguration->commandLineArguments());
-    runControl->setApplicationLauncherMode(localRunConfiguration->runMode());
-    runControl->setWorkingDirectory(localRunConfiguration->workingDirectory());
+    QTC_ASSERT(runConfiguration->runnable().is<StandardRunnable>(), return 0);
+    auto runnable = runConfiguration->runnable().as<StandardRunnable>();
+    auto runControl = new LocalApplicationRunControl(runConfiguration, mode);
+    runControl->setCommand(runnable.executable, runnable.commandLineArguments);
+    runControl->setApplicationLauncherMode(runnable.runMode);
+    runControl->setWorkingDirectory(runnable.workingDirectory);
 
     return runControl;
 }
diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.h b/src/plugins/projectexplorer/localapplicationruncontrol.h
index b6fcc47da59..9d6fd3e3c8b 100644
--- a/src/plugins/projectexplorer/localapplicationruncontrol.h
+++ b/src/plugins/projectexplorer/localapplicationruncontrol.h
@@ -36,8 +36,6 @@ class LocalApplicationRunControlFactory : public IRunControlFactory
 {
     Q_OBJECT
 public:
-    LocalApplicationRunControlFactory ();
-    ~LocalApplicationRunControlFactory();
     bool canRun(RunConfiguration *runConfiguration, Core::Id mode) const;
     RunControl* create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage);
 };
diff --git a/src/plugins/projectexplorer/localenvironmentaspect.cpp b/src/plugins/projectexplorer/localenvironmentaspect.cpp
index 06f1668c65b..946313dc398 100644
--- a/src/plugins/projectexplorer/localenvironmentaspect.cpp
+++ b/src/plugins/projectexplorer/localenvironmentaspect.cpp
@@ -27,7 +27,7 @@
 
 #include "buildconfiguration.h"
 #include "environmentaspectwidget.h"
-#include "localapplicationrunconfiguration.h"
+#include "runnables.h"
 #include "kit.h"
 #include "target.h"
 
@@ -72,8 +72,8 @@ Utils::Environment LocalEnvironmentAspect::baseEnvironment() const
         env = Utils::Environment::systemEnvironment();
     }
 
-    if (const LocalApplicationRunConfiguration *rc = qobject_cast<const LocalApplicationRunConfiguration *>(runConfiguration()))
-        rc->addToBaseEnvironment(env);
+    if (m_baseEnvironmentModifier)
+        m_baseEnvironmentModifier(env);
 
     return env;
 }
@@ -84,16 +84,17 @@ void LocalEnvironmentAspect::buildEnvironmentHasChanged()
         emit environmentChanged();
 }
 
-LocalEnvironmentAspect::LocalEnvironmentAspect(RunConfiguration *parent) :
-    EnvironmentAspect(parent)
+LocalEnvironmentAspect::LocalEnvironmentAspect(RunConfiguration *parent,
+                                               const BaseEnvironmentModifier &modifier) :
+    EnvironmentAspect(parent), m_baseEnvironmentModifier(modifier)
 {
-    connect(parent->target(), SIGNAL(environmentChanged()),
-            this, SLOT(buildEnvironmentHasChanged()));
+    connect(parent->target(), &Target::environmentChanged,
+            this, &LocalEnvironmentAspect::buildEnvironmentHasChanged);
 }
 
 LocalEnvironmentAspect *LocalEnvironmentAspect::create(RunConfiguration *parent) const
 {
-    LocalEnvironmentAspect *result = new LocalEnvironmentAspect(parent);
+    auto result = new LocalEnvironmentAspect(parent, m_baseEnvironmentModifier);
     result->setUserEnvironmentChanges(userEnvironmentChanges());
     return result;
 }
diff --git a/src/plugins/projectexplorer/localenvironmentaspect.h b/src/plugins/projectexplorer/localenvironmentaspect.h
index fefb21ccb8c..6045a21a362 100644
--- a/src/plugins/projectexplorer/localenvironmentaspect.h
+++ b/src/plugins/projectexplorer/localenvironmentaspect.h
@@ -35,7 +35,8 @@ class PROJECTEXPLORER_EXPORT LocalEnvironmentAspect : public EnvironmentAspect
     Q_OBJECT
 
 public:
-    LocalEnvironmentAspect(RunConfiguration *parent);
+    typedef std::function<void(Utils::Environment &)> BaseEnvironmentModifier;
+    LocalEnvironmentAspect(RunConfiguration *parent, const BaseEnvironmentModifier &modifier);
     LocalEnvironmentAspect *create(RunConfiguration *parent) const;
 
     QList<int> possibleBaseEnvironments() const;
@@ -51,6 +52,8 @@ private:
         SystemEnvironmentBase,
         BuildEnvironmentBase
     };
+
+    BaseEnvironmentModifier m_baseEnvironmentModifier;
 };
 
 } // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index 49833ae4e62..4610d467203 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -14,7 +14,7 @@ HEADERS += projectexplorer.h \
     environmentaspectwidget.h \
     gcctoolchain.h \
     importwidget.h \
-    localapplicationrunconfiguration.h \
+    runnables.h \
     localenvironmentaspect.h \
     osparser.h \
     projectexplorer_export.h \
@@ -167,7 +167,6 @@ SOURCES += projectexplorer.cpp \
     environmentaspectwidget.cpp \
     gcctoolchain.cpp \
     importwidget.cpp \
-    localapplicationrunconfiguration.cpp \
     localenvironmentaspect.cpp \
     osparser.cpp \
     projectimporter.cpp \
diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs
index a5511ec8ddf..307a447b1b5 100644
--- a/src/plugins/projectexplorer/projectexplorer.qbs
+++ b/src/plugins/projectexplorer/projectexplorer.qbs
@@ -94,7 +94,6 @@ QtcPlugin {
             "kitoptionspage.cpp", "kitoptionspage.h",
             "ldparser.cpp", "ldparser.h",
             "linuxiccparser.cpp", "linuxiccparser.h",
-            "localapplicationrunconfiguration.cpp", "localapplicationrunconfiguration.h",
             "localapplicationruncontrol.cpp", "localapplicationruncontrol.h",
             "localenvironmentaspect.cpp", "localenvironmentaspect.h",
             "metatypedeclarations.h",
@@ -127,6 +126,7 @@ QtcPlugin {
             "projectwizardpage.cpp", "projectwizardpage.h", "projectwizardpage.ui",
             "propertiespanel.cpp", "propertiespanel.h",
             "removetaskhandler.cpp", "removetaskhandler.h",
+            "runnables.h",
             "runconfiguration.cpp", "runconfiguration.h",
             "runconfigurationaspects.cpp", "runconfigurationaspects.h",
             "runconfigurationmodel.cpp", "runconfigurationmodel.h",
diff --git a/src/plugins/projectexplorer/localapplicationrunconfiguration.cpp b/src/plugins/projectexplorer/runnables.h
similarity index 67%
rename from src/plugins/projectexplorer/localapplicationrunconfiguration.cpp
rename to src/plugins/projectexplorer/runnables.h
index 2aadfcbc8e0..12eef7595b6 100644
--- a/src/plugins/projectexplorer/localapplicationrunconfiguration.cpp
+++ b/src/plugins/projectexplorer/runnables.h
@@ -23,32 +23,28 @@
 **
 ****************************************************************************/
 
-#include "localapplicationrunconfiguration.h"
+#ifndef PROJECTEXPLORER_RUNNABLES_H
+#define PROJECTEXPLORER_RUNNABLES_H
 
-#include "buildconfiguration.h"
+#include "runconfiguration.h"
 
-#include <utils/macroexpander.h>
+#include "applicationlauncher.h"
+#include "devicesupport/idevice.h"
 
-#include <projectexplorer/target.h>
-#include <projectexplorer/project.h>
-
-#include <QDir>
+#include <utils/environment.h>
 
 namespace ProjectExplorer {
 
-LocalApplicationRunConfiguration::LocalApplicationRunConfiguration(Target *target, Core::Id id) :
-    RunConfiguration(target, id)
-{
-}
-
-LocalApplicationRunConfiguration::LocalApplicationRunConfiguration(Target *target, LocalApplicationRunConfiguration *rc) :
-    RunConfiguration(target, rc)
+class PROJECTEXPLORER_EXPORT StandardRunnable
 {
-}
-
-void LocalApplicationRunConfiguration::addToBaseEnvironment(Utils::Environment &env) const
-{
-    Q_UNUSED(env);
-}
+public:
+    QString executable;
+    QString commandLineArguments;
+    QString workingDirectory;
+    Utils::Environment environment;
+    ApplicationLauncher::Mode runMode;
+};
 
 } // namespace ProjectExplorer
+
+#endif // PROJECTEXPLORER_RUNNABLES_H
diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp
index d4fbde1c957..e1f5a5e01f6 100644
--- a/src/plugins/pythoneditor/pythoneditorplugin.cpp
+++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp
@@ -419,7 +419,7 @@ PythonRunConfiguration::PythonRunConfiguration(Target *parent, Core::Id id) :
     const QString exec = sysEnv.searchInPath(QLatin1String("python")).toString();
     m_interpreter = exec.isEmpty() ? QLatin1String("python") : exec;
 
-    addExtraAspect(new LocalEnvironmentAspect(this));
+    addExtraAspect(new LocalEnvironmentAspect(this, LocalEnvironmentAspect::BaseEnvironmentModifier()));
     addExtraAspect(new ArgumentsAspect(this, QStringLiteral("PythonEditor.RunConfiguration.Arguments")));
     addExtraAspect(new TerminalAspect(this, QStringLiteral("PythonEditor.RunConfiguration.UseTerminal")));
     setDefaultDisplayName(defaultDisplayName());
diff --git a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp
index a0b88ca5e65..3af53c933ac 100644
--- a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp
+++ b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp
@@ -61,6 +61,7 @@
 #include <QDir>
 
 using namespace ProjectExplorer;
+using namespace Utils;
 
 namespace QbsProjectManager {
 namespace Internal {
@@ -106,12 +107,12 @@ const qbs::ProductData findProduct(const qbs::ProjectData &pro, const QString &u
 // --------------------------------------------------------------------
 
 QbsRunConfiguration::QbsRunConfiguration(Target *parent, Core::Id id) :
-    LocalApplicationRunConfiguration(parent, id),
+    RunConfiguration(parent, id),
     m_uniqueProductName(uniqueProductNameFromId(id)),
     m_currentInstallStep(0),
     m_currentBuildStepList(0)
 {
-    addExtraAspect(new LocalEnvironmentAspect(this));
+    addExtraAspect(new LocalEnvironmentAspect(this, [this](Environment &env) { addToBaseEnvironment(env); }));
     addExtraAspect(new ArgumentsAspect(this, QStringLiteral("Qbs.RunConfiguration.CommandLineArguments")));
     addExtraAspect(new WorkingDirectoryAspect(this, QStringLiteral("Qbs.RunConfiguration.WorkingDirectory")));
 
@@ -123,7 +124,7 @@ QbsRunConfiguration::QbsRunConfiguration(Target *parent, Core::Id id) :
 }
 
 QbsRunConfiguration::QbsRunConfiguration(Target *parent, QbsRunConfiguration *source) :
-    LocalApplicationRunConfiguration(parent, source),
+    RunConfiguration(parent, source),
     m_uniqueProductName(source->m_uniqueProductName),
     m_currentInstallStep(0), // no need to copy this, we will get if from the DC anyway.
     m_currentBuildStepList(0) // ditto
@@ -226,6 +227,17 @@ void QbsRunConfiguration::installStepToBeRemoved(int pos)
     m_currentInstallStep = 0;
 }
 
+Runnable QbsRunConfiguration::runnable() const
+{
+    StandardRunnable r;
+    r.executable = executable();
+    r.workingDirectory = extraAspect<WorkingDirectoryAspect>()->workingDirectory().toString();
+    r.commandLineArguments = extraAspect<ArgumentsAspect>()->arguments();
+    r.runMode = extraAspect<TerminalAspect>()->runMode();
+    r.environment = extraAspect<LocalEnvironmentAspect>()->environment();
+    return r;
+}
+
 QString QbsRunConfiguration::executable() const
 {
     QbsProject *pro = static_cast<QbsProject *>(target()->project());
@@ -237,11 +249,6 @@ QString QbsRunConfiguration::executable() const
     return pro->qbsProject().targetExecutable(product, installOptions());
 }
 
-ApplicationLauncher::Mode QbsRunConfiguration::runMode() const
-{
-    return extraAspect<TerminalAspect>()->runMode();
-}
-
 bool QbsRunConfiguration::isConsoleApplication() const
 {
     QbsProject *pro = static_cast<QbsProject *>(target()->project());
@@ -249,13 +256,6 @@ bool QbsRunConfiguration::isConsoleApplication() const
     return product.properties().value(QLatin1String("consoleApplication"), false).toBool();
 }
 
-QString QbsRunConfiguration::workingDirectory() const
-{
-    const auto *wdAspect = extraAspect<WorkingDirectoryAspect>();
-    QTC_ASSERT(wdAspect, return baseWorkingDirectory());
-    return wdAspect->workingDirectory().toString();
-}
-
 QString QbsRunConfiguration::baseWorkingDirectory() const
 {
     const QString exe = executable();
@@ -264,11 +264,6 @@ QString QbsRunConfiguration::baseWorkingDirectory() const
     return QString();
 }
 
-QString QbsRunConfiguration::commandLineArguments() const
-{
-    return extraAspect<ArgumentsAspect>()->arguments();
-}
-
 void QbsRunConfiguration::addToBaseEnvironment(Utils::Environment &env) const
 {
     QbsProject *project = static_cast<QbsProject *>(target()->project());
diff --git a/src/plugins/qbsprojectmanager/qbsrunconfiguration.h b/src/plugins/qbsprojectmanager/qbsrunconfiguration.h
index c08d11eb471..7a5562df4e6 100644
--- a/src/plugins/qbsprojectmanager/qbsrunconfiguration.h
+++ b/src/plugins/qbsprojectmanager/qbsrunconfiguration.h
@@ -26,7 +26,7 @@
 #ifndef QBSRUNCONFIGURATION_H
 #define QBSRUNCONFIGURATION_H
 
-#include <projectexplorer/localapplicationrunconfiguration.h>
+#include <projectexplorer/runnables.h>
 
 #include <QStringList>
 #include <QLabel>
@@ -54,7 +54,7 @@ namespace Internal {
 class QbsInstallStep;
 class QbsRunConfigurationFactory;
 
-class QbsRunConfiguration : public ProjectExplorer::LocalApplicationRunConfiguration
+class QbsRunConfiguration : public ProjectExplorer::RunConfiguration
 {
     Q_OBJECT
 
@@ -69,14 +69,12 @@ public:
     QString disabledReason() const override;
     QWidget *createConfigurationWidget() override;
 
-    QString executable() const override;
-    ProjectExplorer::ApplicationLauncher::Mode runMode() const override;
-    QString workingDirectory() const override;
-    QString commandLineArguments() const override;
+    ProjectExplorer::Runnable runnable() const override;
 
+    QString executable() const;
     Utils::OutputFormatter *createOutputFormatter() const override;
 
-    void addToBaseEnvironment(Utils::Environment &env) const override;
+    void addToBaseEnvironment(Utils::Environment &env) const;
 
     QString uniqueProductName() const;
     bool isConsoleApplication() const;
diff --git a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp
index b2a5bb50a4a..a075482ffef 100644
--- a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp
+++ b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp
@@ -76,10 +76,10 @@ static Utils::FileName pathFromId(Core::Id id)
 //
 
 DesktopQmakeRunConfiguration::DesktopQmakeRunConfiguration(Target *parent, Core::Id id) :
-    LocalApplicationRunConfiguration(parent, id),
+    RunConfiguration(parent, id),
     m_proFilePath(pathFromId(id))
 {
-    addExtraAspect(new LocalEnvironmentAspect(this));
+    addExtraAspect(new LocalEnvironmentAspect(this, [this](Environment &env) { addToBaseEnvironment(env); }));
     addExtraAspect(new ArgumentsAspect(this, QStringLiteral("Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments")));
     addExtraAspect(new TerminalAspect(this, QStringLiteral("Qt4ProjectManager.Qt4RunConfiguration.UseTerminal")));
     addExtraAspect(new WorkingDirectoryAspect(this,
@@ -92,7 +92,7 @@ DesktopQmakeRunConfiguration::DesktopQmakeRunConfiguration(Target *parent, Core:
 }
 
 DesktopQmakeRunConfiguration::DesktopQmakeRunConfiguration(Target *parent, DesktopQmakeRunConfiguration *source) :
-    LocalApplicationRunConfiguration(parent, source),
+    RunConfiguration(parent, source),
     m_proFilePath(source->m_proFilePath),
     m_isUsingDyldImageSuffix(source->m_isUsingDyldImageSuffix),
     m_isUsingLibrarySearchPath(source->m_isUsingLibrarySearchPath),
@@ -200,7 +200,8 @@ DesktopQmakeRunConfigurationWidget::DesktopQmakeRunConfigurationWidget(DesktopQm
 
     m_useQvfbCheck = new QCheckBox(tr("Run on QVFb"), this);
     m_useQvfbCheck->setToolTip(tr("Check this option to run the application on a Qt Virtual Framebuffer."));
-    m_useQvfbCheck->setChecked(m_qmakeRunConfiguration->runMode() == ApplicationLauncher::Console);
+    m_useQvfbCheck->setChecked(m_qmakeRunConfiguration->runnable().as<StandardRunnable>().runMode
+                               == ApplicationLauncher::Console);
     m_useQvfbCheck->setVisible(false);
     auto innerBox = new QHBoxLayout();
     innerBox->addWidget(m_useQvfbCheck);
@@ -301,10 +302,21 @@ QWidget *DesktopQmakeRunConfiguration::createConfigurationWidget()
     return new DesktopQmakeRunConfigurationWidget(this);
 }
 
+Runnable DesktopQmakeRunConfiguration::runnable() const
+{
+    StandardRunnable r;
+    r.executable = executable();
+    r.commandLineArguments = extraAspect<ArgumentsAspect>()->arguments();
+    r.workingDirectory = extraAspect<WorkingDirectoryAspect>()->workingDirectory().toString();
+    r.environment = extraAspect<LocalEnvironmentAspect>()->environment();
+    r.runMode = extraAspect<TerminalAspect>()->runMode();
+    return r;
+}
+
 QVariantMap DesktopQmakeRunConfiguration::toMap() const
 {
     const QDir projectDir = QDir(target()->project()->projectDirectory().toString());
-    QVariantMap map(LocalApplicationRunConfiguration::toMap());
+    QVariantMap map(RunConfiguration::toMap());
     map.insert(QLatin1String(PRO_FILE_KEY), projectDir.relativeFilePath(m_proFilePath.toString()));
     map.insert(QLatin1String(USE_DYLD_IMAGE_SUFFIX_KEY), m_isUsingDyldImageSuffix);
     map.insert(QLatin1String(USE_LIBRARY_SEARCH_PATH), m_isUsingLibrarySearchPath);
@@ -321,7 +333,7 @@ bool DesktopQmakeRunConfiguration::fromMap(const QVariantMap &map)
     m_parseSuccess = qmakeProject()->validParse(m_proFilePath);
     m_parseInProgress = qmakeProject()->parseInProgress(m_proFilePath);
 
-    return LocalApplicationRunConfiguration::fromMap(map);
+    return RunConfiguration::fromMap(map);
 }
 
 QString DesktopQmakeRunConfiguration::executable() const
@@ -330,11 +342,6 @@ QString DesktopQmakeRunConfiguration::executable() const
     return extractWorkingDirAndExecutable(node).second;
 }
 
-ApplicationLauncher::Mode DesktopQmakeRunConfiguration::runMode() const
-{
-    return extraAspect<TerminalAspect>()->runMode();
-}
-
 bool DesktopQmakeRunConfiguration::isUsingDyldImageSuffix() const
 {
     return m_isUsingDyldImageSuffix;
@@ -361,22 +368,12 @@ void DesktopQmakeRunConfiguration::setUsingLibrarySearchPath(bool state)
     return extraAspect<LocalEnvironmentAspect>()->environmentChanged();
 }
 
-QString DesktopQmakeRunConfiguration::workingDirectory() const
-{
-    return extraAspect<WorkingDirectoryAspect>()->workingDirectory().toString();
-}
-
 QString DesktopQmakeRunConfiguration::baseWorkingDirectory() const
 {
     const QmakeProFileNode *node = qmakeProject()->rootProjectNode()->findProFileFor(m_proFilePath);
     return extractWorkingDirAndExecutable(node).first;
 }
 
-QString DesktopQmakeRunConfiguration::commandLineArguments() const
-{
-    return extraAspect<ArgumentsAspect>()->arguments();
-}
-
 void DesktopQmakeRunConfiguration::addToBaseEnvironment(Environment &env) const
 {
     if (m_isUsingDyldImageSuffix)
diff --git a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h
index e29fcc524dd..1b1ae059ee1 100644
--- a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h
+++ b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h
@@ -28,7 +28,7 @@
 
 #include <qmakeprojectmanager/qmakerunconfigurationfactory.h>
 
-#include <projectexplorer/localapplicationrunconfiguration.h>
+#include <projectexplorer/runnables.h>
 
 #include <utils/fileutils.h>
 
@@ -48,7 +48,7 @@ class QmakeProject;
 namespace Internal {
 class DesktopQmakeRunConfigurationFactory;
 
-class DesktopQmakeRunConfiguration : public ProjectExplorer::LocalApplicationRunConfiguration
+class DesktopQmakeRunConfiguration : public ProjectExplorer::RunConfiguration
 {
     Q_OBJECT
     // to change the display name and arguments and set the userenvironmentchanges
@@ -62,10 +62,8 @@ public:
     QString disabledReason() const override;
     QWidget *createConfigurationWidget() override;
 
-    QString executable() const override;
-    ProjectExplorer::ApplicationLauncher::Mode runMode() const override;
-    QString workingDirectory() const override;
-    QString commandLineArguments() const override;
+    ProjectExplorer::Runnable runnable() const override;
+    QString executable() const;
 
     bool isUsingDyldImageSuffix() const;
     void setUsingDyldImageSuffix(bool state);
@@ -79,7 +77,7 @@ public:
 
     Utils::OutputFormatter *createOutputFormatter() const override;
 
-    void addToBaseEnvironment(Utils::Environment &env) const override;
+    void addToBaseEnvironment(Utils::Environment &env) const;
 
 signals:
     void baseWorkingDirectoryChanged(const QString&);
diff --git a/src/plugins/qmlprofiler/localqmlprofilerrunner.cpp b/src/plugins/qmlprofiler/localqmlprofilerrunner.cpp
index 36c12f69011..9f307ffb6ec 100644
--- a/src/plugins/qmlprofiler/localqmlprofilerrunner.cpp
+++ b/src/plugins/qmlprofiler/localqmlprofilerrunner.cpp
@@ -28,7 +28,6 @@
 #include "qmlprofilerruncontrol.h"
 
 #include <projectexplorer/runconfiguration.h>
-#include <projectexplorer/localapplicationrunconfiguration.h>
 #include <projectexplorer/environmentaspect.h>
 #include <projectexplorer/devicesupport/idevice.h>
 #include <projectexplorer/kitinformation.h>
diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
index 638add3506e..5baac87289b 100644
--- a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
@@ -37,7 +37,7 @@
 #include <projectexplorer/target.h>
 #include <projectexplorer/environmentaspect.h>
 #include <projectexplorer/localapplicationruncontrol.h>
-#include <projectexplorer/localapplicationrunconfiguration.h>
+#include <projectexplorer/runnables.h>
 #include <qtsupport/qtsupportconstants.h>
 #include <qmldebug/qmloutputparser.h>
 
diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp b/src/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp
index 3408c470ef3..0929664d932 100644
--- a/src/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp
@@ -36,7 +36,7 @@
 
 #include <projectexplorer/environmentaspect.h>
 #include <projectexplorer/kitinformation.h>
-#include <projectexplorer/localapplicationrunconfiguration.h>
+#include <projectexplorer/runnables.h>
 #include <projectexplorer/projectexplorer.h>
 #include <projectexplorer/project.h>
 #include <projectexplorer/session.h>
@@ -52,6 +52,13 @@ using namespace ProjectExplorer;
 namespace QmlProfiler {
 namespace Internal {
 
+static bool isLocal(RunConfiguration *runConfiguration)
+{
+    Target *target = runConfiguration ? runConfiguration->target() : 0;
+    Kit *kit = target ? target->kit() : 0;
+    return DeviceTypeKitInformation::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
+}
+
 QmlProfilerRunControlFactory::QmlProfilerRunControlFactory(QObject *parent) :
     IRunControlFactory(parent)
 {
@@ -59,22 +66,19 @@ QmlProfilerRunControlFactory::QmlProfilerRunControlFactory(QObject *parent) :
 
 bool QmlProfilerRunControlFactory::canRun(RunConfiguration *runConfiguration, Core::Id mode) const
 {
-    return mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE
-            && (qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration));
+    return mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE && isLocal(runConfiguration);
 }
 
 RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage)
 {
     QTC_ASSERT(canRun(runConfiguration, mode), return 0);
-
-    Kit *kit = runConfiguration->target()->kit();
-    // FIXME: This is only used to communicate the connParams settings.
-    auto localRunConfiguration = qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
-    QTC_ASSERT(localRunConfiguration, return 0);
+    QTC_ASSERT(runConfiguration->runnable().is<StandardRunnable>(), return 0);
+    auto &rcRunnable = runConfiguration->runnable().as<StandardRunnable>();
     AnalyzerRunnable runnable;
-    runnable.debuggee = localRunConfiguration->executable();
-    runnable.debuggeeArgs = localRunConfiguration->commandLineArguments();
+    runnable.debuggee = rcRunnable.executable;
+    runnable.debuggeeArgs = rcRunnable.commandLineArguments;
 
+    Kit *kit = runConfiguration->target()->kit();
     AnalyzerConnection connection;
     const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
     if (version) {
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp
index cb8b13f0221..863f42c4d6f 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp
@@ -49,7 +49,7 @@
 #include <projectexplorer/target.h>
 #include <projectexplorer/session.h>
 #include <projectexplorer/kitinformation.h>
-#include <projectexplorer/localapplicationrunconfiguration.h>
+#include <projectexplorer/runnables.h>
 #include <texteditor/texteditor.h>
 
 #include <coreplugin/coreconstants.h>
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
index 4e58b38a19b..d2ae1a29ec9 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
@@ -52,7 +52,7 @@ namespace QmlProjectManager {
 const char M_CURRENT_FILE[] = "CurrentFile";
 
 QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *parent, Id id) :
-    LocalApplicationRunConfiguration(parent, id),
+    RunConfiguration(parent, id),
     m_scriptFile(QLatin1String(M_CURRENT_FILE)),
     m_isEnabled(false)
 {
@@ -61,9 +61,20 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *parent, Id id) :
     ctor();
 }
 
+Runnable QmlProjectRunConfiguration::runnable() const
+{
+    StandardRunnable r;
+    r.executable = executable();
+    r.commandLineArguments = commandLineArguments();
+    r.runMode = ApplicationLauncher::Gui;
+    r.workingDirectory = canonicalCapsPath(target()->project()->projectFilePath()
+                                           .toFileInfo().absolutePath());
+    return r;
+}
+
 QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *parent,
                                                        QmlProjectRunConfiguration *source) :
-    LocalApplicationRunConfiguration(parent, source),
+    RunConfiguration(parent, source),
     m_currentFileFilename(source->m_currentFileFilename),
     m_mainScriptFilename(source->m_mainScriptFilename),
     m_scriptFile(source->m_scriptFile),
@@ -114,11 +125,6 @@ QString QmlProjectRunConfiguration::executable() const
     return version->qmlviewerCommand();
 }
 
-ApplicationLauncher::Mode QmlProjectRunConfiguration::runMode() const
-{
-    return ApplicationLauncher::Gui;
-}
-
 QString QmlProjectRunConfiguration::commandLineArguments() const
 {
     // arguments in .user file
@@ -139,11 +145,6 @@ QString QmlProjectRunConfiguration::commandLineArguments() const
     return args;
 }
 
-QString QmlProjectRunConfiguration::workingDirectory() const
-{
-    return canonicalCapsPath(target()->project()->projectFilePath().toFileInfo().absolutePath());
-}
-
 /* QtDeclarative checks explicitly that the capitalization for any URL / path
    is exactly like the capitalization on disk.*/
 QString QmlProjectRunConfiguration::canonicalCapsPath(const QString &fileName)
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
index a57e5b66df4..e271d84fa61 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
@@ -28,7 +28,7 @@
 
 #include "qmlprojectmanager_global.h"
 
-#include <projectexplorer/localapplicationrunconfiguration.h>
+#include <projectexplorer/runnables.h>
 
 #include <QPointer>
 
@@ -46,7 +46,7 @@ namespace Internal {
     class QmlProjectRunConfigurationWidget;
 }
 
-class QMLPROJECTMANAGER_EXPORT QmlProjectRunConfiguration : public ProjectExplorer::LocalApplicationRunConfiguration
+class QMLPROJECTMANAGER_EXPORT QmlProjectRunConfiguration : public ProjectExplorer::RunConfiguration
 {
     Q_OBJECT
     friend class Internal::QmlProjectRunConfigurationFactory;
@@ -56,11 +56,8 @@ class QMLPROJECTMANAGER_EXPORT QmlProjectRunConfiguration : public ProjectExplor
 public:
     QmlProjectRunConfiguration(ProjectExplorer::Target *parent, Core::Id id);
 
-    QString executable() const override;
-    ProjectExplorer::ApplicationLauncher::Mode runMode() const override;
-    QString commandLineArguments() const override;
+    ProjectExplorer::Runnable runnable() const override;
 
-    QString workingDirectory() const override;
     QtSupport::BaseQtVersion *qtVersion() const;
 
     enum MainScriptSource {
@@ -96,6 +93,10 @@ protected:
 
 private:
     void ctor();
+
+    QString executable() const;
+    QString commandLineArguments() const;
+
     static bool isValidVersion(QtSupport::BaseQtVersion *version);
 
     static QString canonicalCapsPath(const QString &filePath);
diff --git a/src/plugins/qtsupport/customexecutablerunconfiguration.cpp b/src/plugins/qtsupport/customexecutablerunconfiguration.cpp
index c2f1308612e..13e06233433 100644
--- a/src/plugins/qtsupport/customexecutablerunconfiguration.cpp
+++ b/src/plugins/qtsupport/customexecutablerunconfiguration.cpp
@@ -64,21 +64,22 @@ void CustomExecutableRunConfiguration::ctor()
 }
 
 CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *parent) :
-    LocalApplicationRunConfiguration(parent, Core::Id(CUSTOM_EXECUTABLE_ID)),
-    m_workingDirectory(QLatin1String(Constants::DEFAULT_WORKING_DIR)),
+    RunConfiguration(parent, CUSTOM_EXECUTABLE_ID),
     m_dialog(0)
 {
-    addExtraAspect(new LocalEnvironmentAspect(this));
+    addExtraAspect(new LocalEnvironmentAspect(this, LocalEnvironmentAspect::BaseEnvironmentModifier()));
     addExtraAspect(new ArgumentsAspect(this, QStringLiteral("ProjectExplorer.CustomExecutableRunConfiguration.Arguments")));
     addExtraAspect(new TerminalAspect(this, QStringLiteral("ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal")));
-    if (!parent->activeBuildConfiguration())
+    if (parent->activeBuildConfiguration())
+        m_workingDirectory = QLatin1String(Constants::DEFAULT_WORKING_DIR);
+    else
         m_workingDirectory = QLatin1String(Constants::DEFAULT_WORKING_DIR_ALTERNATE);
     ctor();
 }
 
 CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *parent,
                                                                    CustomExecutableRunConfiguration *source) :
-    LocalApplicationRunConfiguration(parent, source),
+    RunConfiguration(parent, source),
     m_executable(source->m_executable),
     m_workingDirectory(source->m_workingDirectory),
     m_dialog(0)
@@ -236,11 +237,6 @@ bool CustomExecutableRunConfiguration::isConfigured() const
     return !m_executable.isEmpty();
 }
 
-ApplicationLauncher::Mode CustomExecutableRunConfiguration::runMode() const
-{
-    return extraAspect<TerminalAspect>()->runMode();
-}
-
 QString CustomExecutableRunConfiguration::workingDirectory() const
 {
     EnvironmentAspect *aspect = extraAspect<EnvironmentAspect>();
@@ -249,15 +245,20 @@ QString CustomExecutableRunConfiguration::workingDirectory() const
                 macroExpander()->expand(baseWorkingDirectory())));
 }
 
-QString CustomExecutableRunConfiguration::baseWorkingDirectory() const
+Runnable CustomExecutableRunConfiguration::runnable() const
 {
-    return m_workingDirectory;
+    StandardRunnable r;
+    r.executable = executable();
+    r.commandLineArguments = extraAspect<ArgumentsAspect>()->arguments();
+    r.workingDirectory = workingDirectory();
+    r.environment = extraAspect<LocalEnvironmentAspect>()->environment();
+    r.runMode = extraAspect<TerminalAspect>()->runMode();
+    return r;
 }
 
-
-QString CustomExecutableRunConfiguration::commandLineArguments() const
+QString CustomExecutableRunConfiguration::baseWorkingDirectory() const
 {
-    return extraAspect<ArgumentsAspect>()->arguments();
+    return m_workingDirectory;
 }
 
 QString CustomExecutableRunConfiguration::defaultDisplayName() const
@@ -270,7 +271,7 @@ QString CustomExecutableRunConfiguration::defaultDisplayName() const
 
 QVariantMap CustomExecutableRunConfiguration::toMap() const
 {
-    QVariantMap map(LocalApplicationRunConfiguration::toMap());
+    QVariantMap map(RunConfiguration::toMap());
     map.insert(QLatin1String(EXECUTABLE_KEY), m_executable);
     map.insert(QLatin1String(WORKING_DIRECTORY_KEY), m_workingDirectory);
     return map;
@@ -282,7 +283,7 @@ bool CustomExecutableRunConfiguration::fromMap(const QVariantMap &map)
     m_workingDirectory = map.value(QLatin1String(WORKING_DIRECTORY_KEY)).toString();
 
     setDefaultDisplayName(defaultDisplayName());
-    return LocalApplicationRunConfiguration::fromMap(map);
+    return RunConfiguration::fromMap(map);
 }
 
 void CustomExecutableRunConfiguration::setExecutable(const QString &executable)
diff --git a/src/plugins/qtsupport/customexecutablerunconfiguration.h b/src/plugins/qtsupport/customexecutablerunconfiguration.h
index 858027f030c..919310f2067 100644
--- a/src/plugins/qtsupport/customexecutablerunconfiguration.h
+++ b/src/plugins/qtsupport/customexecutablerunconfiguration.h
@@ -28,7 +28,7 @@
 
 #include "qtsupport_global.h"
 
-#include <projectexplorer/localapplicationrunconfiguration.h>
+#include <projectexplorer/runnables.h>
 
 #include <QVariantMap>
 
@@ -39,7 +39,7 @@ namespace Internal { class CustomExecutableConfigurationWidget; }
 
 class CustomExecutableRunConfigurationFactory;
 
-class QTSUPPORT_EXPORT CustomExecutableRunConfiguration : public ProjectExplorer::LocalApplicationRunConfiguration
+class QTSUPPORT_EXPORT CustomExecutableRunConfiguration : public ProjectExplorer::RunConfiguration
 {
     Q_OBJECT
     // the configuration widget needs to setExecutable setWorkingDirectory and setCommandLineArguments
@@ -54,16 +54,14 @@ public:
      * Returns the executable, looks in the environment for it and might even
      * ask the user if none is specified
      */
-    QString executable() const override;
+    QString executable() const;
+    QString workingDirectory() const;
+    ProjectExplorer::Runnable runnable() const override;
 
     /** Returns whether this runconfiguration ever was configured with an executable
      */
     bool isConfigured() const override;
 
-    ProjectExplorer::ApplicationLauncher::Mode runMode() const override;
-    QString workingDirectory() const override;
-    QString commandLineArguments() const override;
-
     QWidget *createConfigurationWidget() override;
 
     ProjectExplorer::Abi abi() const override;
diff --git a/src/plugins/valgrind/valgrindruncontrolfactory.cpp b/src/plugins/valgrind/valgrindruncontrolfactory.cpp
index bfa6258c4a7..812b7d5e971 100644
--- a/src/plugins/valgrind/valgrindruncontrolfactory.cpp
+++ b/src/plugins/valgrind/valgrindruncontrolfactory.cpp
@@ -41,7 +41,7 @@
 
 #include <debugger/debuggerrunconfigurationaspect.h>
 #include <projectexplorer/environmentaspect.h>
-#include <projectexplorer/localapplicationrunconfiguration.h>
+#include <projectexplorer/runnables.h>
 #include <projectexplorer/kitinformation.h>
 #include <projectexplorer/projectexplorer.h>
 #include <projectexplorer/target.h>
@@ -75,21 +75,19 @@ RunControl *ValgrindRunControlFactory::create(RunConfiguration *runConfiguration
     QTC_ASSERT(runControl, return 0);
 
     ApplicationLauncher::Mode localRunMode = ApplicationLauncher::Gui;
+    IDevice::ConstPtr device = DeviceKitInformation::device(runConfiguration->target()->kit());
     Utils::Environment environment;
     AnalyzerRunnable runnable;
     AnalyzerConnection connection;
     QString workingDirectory;
-    if (auto rc1 = qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration)) {
-        EnvironmentAspect *aspect = runConfiguration->extraAspect<EnvironmentAspect>();
-        if (aspect)
-            environment = aspect->environment();
-        workingDirectory = rc1->workingDirectory();
-        runnable.debuggee = rc1->executable();
-        runnable.debuggeeArgs = rc1->commandLineArguments();
-        const IDevice::ConstPtr device =
-                DeviceKitInformation::device(runConfiguration->target()->kit());
-        QTC_ASSERT(device, return 0);
-        QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0);
+    Runnable rcRunnable = runConfiguration->runnable();
+    if (rcRunnable.is<StandardRunnable>()
+            && device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
+        auto stdRunnable = runConfiguration->runnable().as<StandardRunnable>();
+        environment = stdRunnable.environment;
+        workingDirectory = stdRunnable.workingDirectory;
+        runnable.debuggee = stdRunnable.executable;
+        runnable.debuggeeArgs = stdRunnable.commandLineArguments;
         QTcpServer server;
         if (!server.listen(QHostAddress::LocalHost) && !server.listen(QHostAddress::LocalHostIPv6)) {
             qWarning() << "Cannot open port on host for profiling.";
@@ -97,11 +95,11 @@ RunControl *ValgrindRunControlFactory::create(RunConfiguration *runConfiguration
         }
         connection.connParams.host = server.serverAddress().toString();
         connection.connParams.port = server.serverPort();
-        localRunMode = rc1->runMode();
+        localRunMode = stdRunnable.runMode;
     } else if (auto rc2 = qobject_cast<RemoteLinux::AbstractRemoteLinuxRunConfiguration *>(runConfiguration)) {
         runnable.debuggee = rc2->remoteExecutableFilePath();
         runnable.debuggeeArgs = rc2->arguments();
-        connection.connParams = DeviceKitInformation::device(rc2->target()->kit())->sshParameters();
+        connection.connParams = device->sshParameters();
     } else {
         QTC_ASSERT(false, return 0);
     }
-- 
GitLab