diff --git a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d83d48b5667f4d5a3df72f9b4a2a66daf0e3e8af
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qbsinstallstep.h"
+
+#include "qbsbuildconfiguration.h"
+#include "qbsproject.h"
+#include "qbsprojectmanagerconstants.h"
+
+#include "ui_qbsinstallstepconfigwidget.h"
+
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/deployconfiguration.h>
+#include <projectexplorer/kit.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/target.h>
+#include <utils/qtcassert.h>
+
+#include <QFileInfo>
+
+static const char QBS_INSTALL_ROOT[] = "Qbs.InstallRoot";
+static const char QBS_REMOVE_FIRST[] = "Qbs.RemoveFirst";
+static const char QBS_DRY_RUN[] = "Qbs.DryRun";
+static const char QBS_KEEP_GOING[] = "Qbs.DryKeepGoing";
+
+// --------------------------------------------------------------------
+// Constants:
+// --------------------------------------------------------------------
+
+namespace QbsProjectManager {
+namespace Internal {
+
+// --------------------------------------------------------------------
+// QbsInstallStep:
+// --------------------------------------------------------------------
+
+QbsInstallStep::QbsInstallStep(ProjectExplorer::BuildStepList *bsl) :
+    ProjectExplorer::BuildStep(bsl, Core::Id(Constants::QBS_INSTALLSTEP_ID)),
+    m_job(0), m_showCompilerOutput(true), m_parser(0)
+{
+    setDisplayName(tr("Qbs Install"));
+}
+
+QbsInstallStep::QbsInstallStep(ProjectExplorer::BuildStepList *bsl, const QbsInstallStep *other) :
+    ProjectExplorer::BuildStep(bsl, Core::Id(Constants::QBS_INSTALLSTEP_ID)),
+    m_qbsInstallOptions(other->m_qbsInstallOptions), m_job(0),
+    m_showCompilerOutput(other->m_showCompilerOutput), m_parser(0)
+{ }
+
+QbsInstallStep::~QbsInstallStep()
+{
+    cancel();
+    if (m_job)
+        m_job->deleteLater();
+    m_job = 0;
+}
+
+bool QbsInstallStep::init()
+{
+    QTC_ASSERT(!static_cast<QbsProject *>(project())->isParsing() && !m_job, return false);
+    return true;
+}
+
+void QbsInstallStep::run(QFutureInterface<bool> &fi)
+{
+    m_fi = &fi;
+
+    QbsProject *pro = static_cast<QbsProject *>(project());
+    m_job = pro->install(m_qbsInstallOptions);
+
+    if (!m_job) {
+        m_fi->reportResult(false);
+        return;
+    }
+
+    m_progressBase = 0;
+
+    connect(m_job, SIGNAL(finished(bool,qbs::AbstractJob*)), this, SLOT(installDone(bool)));
+    connect(m_job, SIGNAL(taskStarted(QString,int,qbs::AbstractJob*)),
+            this, SLOT(handleTaskStarted(QString,int)));
+    connect(m_job, SIGNAL(taskProgress(int,qbs::AbstractJob*)),
+            this, SLOT(handleProgress(int)));
+}
+
+ProjectExplorer::BuildStepConfigWidget *QbsInstallStep::createConfigWidget()
+{
+    return new QbsInstallStepConfigWidget(this);
+}
+
+bool QbsInstallStep::runInGuiThread() const
+{
+    return true;
+}
+
+void QbsInstallStep::cancel()
+{
+    if (m_job)
+        m_job->cancel();
+}
+
+QString QbsInstallStep::installRoot() const
+{
+    if (!m_qbsInstallOptions.installRoot.isEmpty())
+        return m_qbsInstallOptions.installRoot;
+
+    return qbs::InstallOptions::defaultInstallRoot();
+}
+
+QString QbsInstallStep::absoluteInstallRoot() const
+{
+    const qbs::ProjectData *data = static_cast<QbsProject *>(project())->qbsProjectData();
+    QString path = installRoot();
+    if (data)
+        path = QDir(data->buildDirectory()).absoluteFilePath(path);
+    return path;
+}
+
+bool QbsInstallStep::removeFirst() const
+{
+    return m_qbsInstallOptions.removeFirst;
+}
+
+bool QbsInstallStep::dryRun() const
+{
+    return m_qbsInstallOptions.dryRun;
+}
+
+bool QbsInstallStep::keepGoing() const
+{
+    return m_qbsInstallOptions.keepGoing;
+}
+
+bool QbsInstallStep::fromMap(const QVariantMap &map)
+{
+    if (!ProjectExplorer::BuildStep::fromMap(map))
+        return false;
+
+    setInstallRoot(map.value(QLatin1String(QBS_INSTALL_ROOT)).toString());
+    m_qbsInstallOptions.removeFirst = map.value(QLatin1String(QBS_REMOVE_FIRST), false).toBool();
+    m_qbsInstallOptions.dryRun = map.value(QLatin1String(QBS_DRY_RUN), false).toBool();
+    m_qbsInstallOptions.keepGoing = map.value(QLatin1String(QBS_KEEP_GOING), false).toBool();
+
+    return true;
+}
+
+QVariantMap QbsInstallStep::toMap() const
+{
+    QVariantMap map = ProjectExplorer::BuildStep::toMap();
+    map.insert(QLatin1String(QBS_INSTALL_ROOT), m_qbsInstallOptions.installRoot);
+    map.insert(QLatin1String(QBS_REMOVE_FIRST), m_qbsInstallOptions.removeFirst);
+    map.insert(QLatin1String(QBS_DRY_RUN), m_qbsInstallOptions.dryRun);
+    map.insert(QLatin1String(QBS_KEEP_GOING), m_qbsInstallOptions.keepGoing);
+
+    return map;
+}
+
+void QbsInstallStep::installDone(bool success)
+{
+    // Report errors:
+    foreach (const qbs::ErrorData &data, m_job->error().entries()) {
+        createTaskAndOutput(ProjectExplorer::Task::Error, data.description(),
+                            data.codeLocation().fileName, data.codeLocation().line);
+    }
+
+    QTC_ASSERT(m_fi, return);
+    m_fi->reportResult(success);
+    m_fi = 0; // do not delete, it is not ours
+    m_job->deleteLater();
+    m_job = 0;
+
+    emit finished();
+}
+
+void QbsInstallStep::handleTaskStarted(const QString &desciption, int max)
+{
+    Q_UNUSED(desciption);
+    QTC_ASSERT(m_fi, return);
+    m_progressBase = m_fi->progressValue();
+    m_fi->setProgressRange(0, m_progressBase + max);
+}
+
+void QbsInstallStep::handleProgress(int value)
+{
+    QTC_ASSERT(m_fi, return);
+    m_fi->setProgressValue(m_progressBase + value);
+}
+
+void QbsInstallStep::createTaskAndOutput(ProjectExplorer::Task::TaskType type,
+                                         const QString &message, const QString &file, int line)
+{
+    emit addTask(ProjectExplorer::Task(type, message,
+                                       Utils::FileName::fromString(file), line,
+                                       ProjectExplorer::Constants::TASK_CATEGORY_COMPILE));
+    emit addOutput(message, NormalOutput);
+}
+
+void QbsInstallStep::setInstallRoot(const QString &ir)
+{
+    if (m_qbsInstallOptions.installRoot == ir)
+        return;
+    m_qbsInstallOptions.installRoot = ir;
+    emit changed();
+}
+
+void QbsInstallStep::setRemoveFirst(bool rf)
+{
+    if (m_qbsInstallOptions.removeFirst == rf)
+        return;
+    m_qbsInstallOptions.removeFirst = rf;
+    emit changed();
+}
+
+void QbsInstallStep::setDryRun(bool dr)
+{
+    if (m_qbsInstallOptions.dryRun == dr)
+        return;
+    m_qbsInstallOptions.dryRun = dr;
+    emit changed();
+}
+
+void QbsInstallStep::setKeepGoing(bool kg)
+{
+    if (m_qbsInstallOptions.keepGoing == kg)
+        return;
+    m_qbsInstallOptions.keepGoing = kg;
+    emit changed();
+}
+
+// --------------------------------------------------------------------
+// QbsInstallStepConfigWidget:
+// --------------------------------------------------------------------
+
+QbsInstallStepConfigWidget::QbsInstallStepConfigWidget(QbsInstallStep *step) :
+    m_step(step), m_ignoreChange(false)
+{
+    connect(m_step, SIGNAL(displayNameChanged()), this, SLOT(updateState()));
+    connect(m_step, SIGNAL(changed()), this, SLOT(updateState()));
+
+    setContentsMargins(0, 0, 0, 0);
+
+    QbsProject *project = static_cast<QbsProject *>(m_step->project());
+
+    m_ui = new Ui::QbsInstallStepConfigWidget;
+    m_ui->setupUi(this);
+
+    m_ui->installRootChooser->setPromptDialogTitle(tr("Qbs Install Prefix"));
+    m_ui->installRootChooser->setExpectedKind(Utils::PathChooser::Directory);
+
+    connect(m_ui->installRootChooser, SIGNAL(changed(QString)), this, SLOT(changeInstallRoot()));
+    connect(m_ui->removeFirstCheckBox, SIGNAL(toggled(bool)), this, SLOT(changeRemoveFirst(bool)));
+    connect(m_ui->dryRunCheckBox, SIGNAL(toggled(bool)), this, SLOT(changeDryRun(bool)));
+    connect(m_ui->keepGoingCheckBox, SIGNAL(toggled(bool)), this, SLOT(changeKeepGoing(bool)));
+
+    connect(project, SIGNAL(projectParsingDone(bool)), this, SLOT(updateState()));
+
+    updateState();
+}
+
+QString QbsInstallStepConfigWidget::summaryText() const
+{
+    return m_summary;
+}
+
+QString QbsInstallStepConfigWidget::displayName() const
+{
+    return m_step->displayName();
+}
+
+void QbsInstallStepConfigWidget::updateState()
+{
+    if (!m_ignoreChange) {
+        m_ui->installRootChooser->setPath(m_step->installRoot());
+        m_ui->removeFirstCheckBox->setChecked(m_step->removeFirst());
+        m_ui->dryRunCheckBox->setChecked(m_step->dryRun());
+        m_ui->keepGoingCheckBox->setChecked(m_step->keepGoing());
+    }
+
+    const qbs::ProjectData *data = static_cast<QbsProject *>(m_step->project())->qbsProjectData();
+    if (data)
+        m_ui->installRootChooser->setBaseDirectory(data->buildDirectory());
+
+    QString command = QLatin1String("qbs install ");
+    if (m_step->dryRun())
+        command += QLatin1String("--dry-run ");
+    if (m_step->keepGoing())
+        command += QLatin1String("--keep-going ");
+    if (m_step->removeFirst())
+        command += QLatin1String("--remove-first ");
+    command += QString::fromLatin1("--install-root \"%1\"").arg(m_step->absoluteInstallRoot());
+
+    QString summary = tr("<b>Qbs:</b> %1").arg(command);
+    if (m_summary != summary) {
+        m_summary = summary;
+        emit updateSummary();
+    }
+}
+
+void QbsInstallStepConfigWidget::changeInstallRoot()
+{
+    const QString path = m_ui->installRootChooser->path();
+    if (m_step->installRoot() == path)
+        return;
+
+    m_ignoreChange = true;
+    m_step->setInstallRoot(path);
+    m_ignoreChange = false;
+}
+
+void QbsInstallStepConfigWidget::changeRemoveFirst(bool rf)
+{
+    m_step->setRemoveFirst(rf);
+}
+
+void QbsInstallStepConfigWidget::changeDryRun(bool dr)
+{
+    m_step->setDryRun(dr);
+}
+
+void QbsInstallStepConfigWidget::changeKeepGoing(bool kg)
+{
+    m_step->setKeepGoing(kg);
+}
+
+// --------------------------------------------------------------------
+// QbsInstallStepFactory:
+// --------------------------------------------------------------------
+
+QbsInstallStepFactory::QbsInstallStepFactory(QObject *parent) :
+    ProjectExplorer::IBuildStepFactory(parent)
+{ }
+
+QList<Core::Id> QbsInstallStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
+{
+    if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_DEPLOY
+            && qobject_cast<ProjectExplorer::DeployConfiguration *>(parent->parent()))
+        return QList<Core::Id>() << Core::Id(Constants::QBS_INSTALLSTEP_ID);
+    return QList<Core::Id>();
+}
+
+QString QbsInstallStepFactory::displayNameForId(Core::Id id) const
+{
+    if (id == Core::Id(Constants::QBS_INSTALLSTEP_ID))
+        return tr("Qbs Install");
+    return QString();
+}
+
+bool QbsInstallStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, Core::Id id) const
+{
+    if (parent->id() != Core::Id(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY)
+            || !qobject_cast<ProjectExplorer::DeployConfiguration *>(parent->parent()))
+        return false;
+    return id == Core::Id(Constants::QBS_INSTALLSTEP_ID);
+}
+
+ProjectExplorer::BuildStep *QbsInstallStepFactory::create(ProjectExplorer::BuildStepList *parent,
+                                                          Core::Id id)
+{
+    if (!canCreate(parent, id))
+        return 0;
+    return new QbsInstallStep(parent);
+}
+
+bool QbsInstallStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const
+{
+    return canCreate(parent, ProjectExplorer::idFromMap(map));
+}
+
+ProjectExplorer::BuildStep *QbsInstallStepFactory::restore(ProjectExplorer::BuildStepList *parent,
+                                                           const QVariantMap &map)
+{
+    if (!canRestore(parent, map))
+        return 0;
+    QbsInstallStep *bs = new QbsInstallStep(parent);
+    if (!bs->fromMap(map)) {
+        delete bs;
+        return 0;
+    }
+    return bs;
+}
+
+bool QbsInstallStepFactory::canClone(ProjectExplorer::BuildStepList *parent,
+                                     ProjectExplorer::BuildStep *product) const
+{
+    return canCreate(parent, product->id());
+}
+
+ProjectExplorer::BuildStep *QbsInstallStepFactory::clone(ProjectExplorer::BuildStepList *parent,
+                                                         ProjectExplorer::BuildStep *product)
+{
+    if (!canClone(parent, product))
+        return 0;
+    return new QbsInstallStep(parent, static_cast<QbsInstallStep *>(product));
+}
+
+} // namespace Internal
+} // namespace QbsProjectManager
diff --git a/src/plugins/qbsprojectmanager/qbsinstallstep.h b/src/plugins/qbsprojectmanager/qbsinstallstep.h
new file mode 100644
index 0000000000000000000000000000000000000000..520d255ea506dcd2e8a518685b5cf83c9a47c73c
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsinstallstep.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBSINSTALLSTEP_H
+#define QBSINSTALLSTEP_H
+
+#include "qbsbuildconfiguration.h"
+
+#include <projectexplorer/buildstep.h>
+#include <projectexplorer/task.h>
+
+#include <qbs.h>
+
+namespace QbsProjectManager {
+namespace Internal {
+
+class QbsInstallStepConfigWidget;
+
+class QbsInstallStep : public ProjectExplorer::BuildStep
+{
+    Q_OBJECT
+
+public:
+    QbsInstallStep(ProjectExplorer::BuildStepList *bsl);
+    QbsInstallStep(ProjectExplorer::BuildStepList *bsl, const QbsInstallStep *other);
+    ~QbsInstallStep();
+
+    bool init();
+
+    void run(QFutureInterface<bool> &fi);
+
+    ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
+
+    bool runInGuiThread() const;
+    void cancel();
+
+    bool fromMap(const QVariantMap &map);
+    QVariantMap toMap() const;
+
+    QString installRoot() const;
+    QString absoluteInstallRoot() const;
+    bool removeFirst() const;
+    bool dryRun() const;
+    bool keepGoing() const;
+
+signals:
+    void changed();
+
+private slots:
+    void installDone(bool success);
+    void handleTaskStarted(const QString &desciption, int max);
+    void handleProgress(int value);
+
+private:
+    void createTaskAndOutput(ProjectExplorer::Task::TaskType type,
+                             const QString &message, const QString &file, int line);
+
+    void setInstallRoot(const QString &ir);
+    void setRemoveFirst(bool rf);
+    void setDryRun(bool dr);
+    void setKeepGoing(bool kg);
+
+    qbs::InstallOptions m_qbsInstallOptions;
+
+    QFutureInterface<bool> *m_fi;
+    qbs::InstallJob *m_job;
+    int m_progressBase;
+    bool m_showCompilerOutput;
+    ProjectExplorer::IOutputParser *m_parser;
+
+    friend class QbsInstallStepConfigWidget;
+};
+
+namespace Ui { class QbsInstallStepConfigWidget; }
+
+class QbsInstallStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget
+{
+    Q_OBJECT
+public:
+    QbsInstallStepConfigWidget(QbsInstallStep *step);
+    QString summaryText() const;
+    QString displayName() const;
+
+private slots:
+    void updateState();
+
+    void changeInstallRoot();
+    void changeRemoveFirst(bool rf);
+    void changeDryRun(bool dr);
+    void changeKeepGoing(bool kg);
+
+private:
+    Ui::QbsInstallStepConfigWidget *m_ui;
+
+    QbsInstallStep *m_step;
+    QString m_summary;
+    bool m_ignoreChange;
+};
+
+
+class QbsInstallStepFactory : public ProjectExplorer::IBuildStepFactory
+{
+    Q_OBJECT
+
+public:
+    explicit QbsInstallStepFactory(QObject *parent = 0);
+
+    // used to show the list of possible additons to a target, returns a list of types
+    QList<Core::Id> availableCreationIds(ProjectExplorer::BuildStepList *parent) const;
+    // used to translate the types to names to display to the user
+    QString displayNameForId(Core::Id id) const;
+
+    bool canCreate(ProjectExplorer::BuildStepList *parent, Core::Id id) const;
+    ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, Core::Id id);
+    // used to recreate the runConfigurations when restoring settings
+    bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const;
+    ProjectExplorer::BuildStep *restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map);
+    bool canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const;
+    ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product);
+};
+
+
+} // namespace Internal
+} // namespace QbsProjectManager
+
+#endif // QBSINSTALLSTEP_H
diff --git a/src/plugins/qbsprojectmanager/qbsinstallstepconfigwidget.ui b/src/plugins/qbsprojectmanager/qbsinstallstepconfigwidget.ui
new file mode 100644
index 0000000000000000000000000000000000000000..4336caf9cec22c5393d77c52ad84c26392526208
--- /dev/null
+++ b/src/plugins/qbsprojectmanager/qbsinstallstepconfigwidget.ui
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QbsProjectManager::Internal::QbsInstallStepConfigWidget</class>
+ <widget class="QWidget" name="QbsProjectManager::Internal::QbsInstallStepConfigWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>371</width>
+    <height>60</height>
+   </rect>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <property name="horizontalSpacing">
+    <number>6</number>
+   </property>
+   <property name="verticalSpacing">
+    <number>18</number>
+   </property>
+   <item row="0" column="0">
+    <widget class="QLabel" name="installRootLabel">
+     <property name="text">
+      <string>Install Root:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1" colspan="2">
+    <widget class="Utils::PathChooser" name="installRootChooser">
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>0</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QCheckBox" name="removeFirstCheckBox">
+     <property name="text">
+      <string>Remove First</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QCheckBox" name="dryRunCheckBox">
+     <property name="text">
+      <string>Dry run</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="2">
+    <widget class="QCheckBox" name="keepGoingCheckBox">
+     <property name="text">
+      <string>Keep Going</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>Utils::PathChooser</class>
+   <extends>QLineEdit</extends>
+   <header location="global">utils/pathchooser.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp
index ef52efd13525d7bc7252a5d67c0a06ac38c70b4f..3c324a4109aa3c2790b5e139ed2c79d322ca057a 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.cpp
+++ b/src/plugins/qbsprojectmanager/qbsproject.cpp
@@ -195,6 +195,13 @@ qbs::CleanJob *QbsProject::clean(const qbs::CleanOptions &opts)
     return qbsProject()->cleanAllProducts(opts);
 }
 
+qbs::InstallJob *QbsProject::install(const qbs::InstallOptions &opts)
+{
+    if (!qbsProject())
+        return 0;
+    return qbsProject()->installAllProducts(opts);
+}
+
 QString QbsProject::profileForTarget(const ProjectExplorer::Target *t) const
 {
     return m_manager->profileForKit(t->kit());
diff --git a/src/plugins/qbsprojectmanager/qbsproject.h b/src/plugins/qbsprojectmanager/qbsproject.h
index 80b7fd4128ae68515a8e97ac711f39225d8eef02..5e1ec70e886db5fe2f0a187721599356a50c51b3 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.h
+++ b/src/plugins/qbsprojectmanager/qbsproject.h
@@ -81,6 +81,7 @@ public:
 
     qbs::BuildJob *build(const qbs::BuildOptions &opts);
     qbs::CleanJob *clean(const qbs::CleanOptions &opts);
+    qbs::InstallJob *install(const qbs::InstallOptions &opts);
 
     static ProjectExplorer::FileType fileTypeFor(const QSet<QString> &tags);
 
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.pro b/src/plugins/qbsprojectmanager/qbsprojectmanager.pro
index e6c4b383ab8bfeff16960652ac9fda613bf04813..d228910150eb9652637ccccab968b2fb07f32ad4 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanager.pro
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.pro
@@ -18,6 +18,7 @@ HEADERS = \
     qbsbuildconfigurationwidget.h \
     qbsbuildstep.h \
     qbscleanstep.h \
+    qbsinstallstep.h \
     qbslogsink.h \
     qbsnodes.h \
     qbsparser.h \
@@ -34,6 +35,7 @@ SOURCES = \
     qbsbuildconfigurationwidget.cpp \
     qbsbuildstep.cpp \
     qbscleanstep.cpp \
+    qbsinstallstep.cpp \
     qbslogsink.cpp \
     qbsnodes.cpp \
     qbsparser.cpp \
@@ -46,4 +48,5 @@ SOURCES = \
 FORMS = \
     qbsbuildstepconfigwidget.ui \
     qbscleanstepconfigwidget.ui \
+    qbsinstallstepconfigwidget.ui \
     qbsstepconfigwidget.ui
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
index 17ddb68285ac443d61c4d30a8db1133e3735156f..56016b1c458c9f41888ebe79fd16a108c7b3e5de 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
@@ -59,6 +59,9 @@ QtcPlugin {
         "qbscleanstep.cpp",
         "qbscleanstep.h",
         "qbscleanstepconfigwidget.ui",
+        "qbsinstallstep.cpp",
+        "qbsinstallstep.h",
+        "qbsinstallstepconfigwidget.ui",
         "qbslogsink.cpp",
         "qbslogsink.h",
         "qbsnodes.cpp",
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h b/src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h
index d011bc4ad2d494bcef05414d42431f2227235901..5c29eb5c25136e3c2f3951806961bbfbe1a6433c 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanagerconstants.h
@@ -52,6 +52,7 @@ const char ACTION_BUILD_FILE_QBS_CONTEXT[] = "Qbs.BuildFileCtx";
 // Ids:
 const char QBS_BUILDSTEP_ID[] = "Qbs.BuildStep";
 const char QBS_CLEANSTEP_ID[] = "Qbs.CleanStep";
+const char QBS_INSTALLSTEP_ID[] = "Qbs.InstallStep";
 
 // QBS strings:
 static const char QBS_VARIANT_DEBUG[] = "debug";
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp
index c352b99d6730727d07c2e7f3e37c19f9ad4369dc..481392169cccdf869e551421ceab025ca9b954b7 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp
@@ -32,6 +32,7 @@
 #include "qbsbuildconfiguration.h"
 #include "qbsbuildstep.h"
 #include "qbscleanstep.h"
+#include "qbsinstallstep.h"
 #include "qbsproject.h"
 #include "qbsprojectmanager.h"
 #include "qbsprojectmanagerconstants.h"
@@ -81,6 +82,7 @@ bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *
     addAutoReleasedObject(new QbsBuildConfigurationFactory);
     addAutoReleasedObject(new QbsBuildStepFactory);
     addAutoReleasedObject(new QbsCleanStepFactory);
+    addAutoReleasedObject(new QbsInstallStepFactory);
 
     //menus
     // Build Menu: