diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp
index 54a88c18aafa5bf7a912b962431c827b8a05cfa8..694db1012ee4638995ea093489d451a16a5106ac 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp
@@ -31,13 +31,18 @@
 
 #include "qt4projectmanagerconstants.h"
 #include "qt4buildconfiguration.h"
+#include "qt4nodes.h"
+#include "qt4project.h"
 #include "abldparser.h"
 
 #include <projectexplorer/buildconfiguration.h>
 #include <projectexplorer/target.h>
+#include <projectexplorer/project.h>
 #include <projectexplorer/gnumakeparser.h>
+#include <projectexplorer/task.h>
 
 #include <QtCore/QDir>
+#include <QtCore/QTimer>
 
 using namespace Qt4ProjectManager::Internal;
 
@@ -49,30 +54,41 @@ namespace {
     const char * const SMART_INSTALLER_KEY("Qt4ProjectManager.S60CreatorPackageStep.SmartInstaller");
 }
 
-// #pragma mark -- S60SignBuildStep
-
 S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildConfiguration *bc) :
-    MakeStep(bc, QLatin1String(SIGN_BS_ID)),
+    BuildStep(bc, QLatin1String(SIGN_BS_ID)),
     m_signingMode(SignSelf),
-    m_createSmartInstaller(false)
+    m_createSmartInstaller(false),
+    m_outputParserChain(0),
+    m_process(0),
+    m_timer(0),
+    m_eventLoop(0),
+    m_futureInterface(0)
 {
     ctor_package();
 }
 
 S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildConfiguration *bc, S60CreatePackageStep *bs) :
-    MakeStep(bc, bs),
+    BuildStep(bc, bs),
     m_signingMode(bs->m_signingMode),
     m_customSignaturePath(bs->m_customSignaturePath),
     m_customKeyPath(bs->m_customKeyPath),
-    m_createSmartInstaller(bs->m_createSmartInstaller)
+    m_createSmartInstaller(bs->m_createSmartInstaller),
+    m_outputParserChain(0),
+    m_timer(0),
+    m_eventLoop(0),
+    m_futureInterface(0)
 {
     ctor_package();
 }
 
 S60CreatePackageStep::S60CreatePackageStep(ProjectExplorer::BuildConfiguration *bc, const QString &id) :
-    MakeStep(bc, id),
+    BuildStep(bc, id),
     m_signingMode(SignSelf),
-    m_createSmartInstaller(false)
+    m_createSmartInstaller(false),
+    m_outputParserChain(0),
+    m_timer(0),
+    m_eventLoop(0),
+    m_futureInterface(0)
 {
     ctor_package();
 }
@@ -88,7 +104,7 @@ S60CreatePackageStep::~S60CreatePackageStep()
 
 QVariantMap S60CreatePackageStep::toMap() const
 {
-    QVariantMap map(MakeStep::toMap());
+    QVariantMap map(BuildStep::toMap());
     map.insert(QLatin1String(SIGNMODE_KEY), (int)m_signingMode);
     map.insert(QLatin1String(CERTIFICATE_KEY), m_customSignaturePath);
     map.insert(QLatin1String(KEYFILE_KEY), m_customKeyPath);
@@ -102,34 +118,224 @@ bool S60CreatePackageStep::fromMap(const QVariantMap &map)
     m_customSignaturePath = map.value(QLatin1String(CERTIFICATE_KEY)).toString();
     m_customKeyPath = map.value(QLatin1String(KEYFILE_KEY)).toString();
     m_createSmartInstaller = map.value(QLatin1String(SMART_INSTALLER_KEY), false).toBool();
-    return MakeStep::fromMap(map);
+    return BuildStep::fromMap(map);
+}
+
+Qt4BuildConfiguration *S60CreatePackageStep::qt4BuildConfiguration() const
+{
+    return static_cast<Qt4BuildConfiguration *>(buildConfiguration());
 }
 
 bool S60CreatePackageStep::init()
 {
-    if (!MakeStep::init())
-        return false;
-    Qt4BuildConfiguration *bc = qt4BuildConfiguration();
-    ProjectExplorer::Environment environment = bc->environment();
-    setEnvironment(environment);
-    QStringList args;
+    Qt4Project *pro = qobject_cast<Qt4Project *>(buildConfiguration()->target()->project());
+
+    QList<Qt4ProFileNode *> nodes = pro->leafProFiles();
+
+    m_workingDirectories.clear();
+    foreach (Qt4ProFileNode *node, nodes)
+        m_workingDirectories << node->buildDir();
+
+    m_makeCmd = qt4BuildConfiguration()->makeCommand();
+    if (!QFileInfo(m_makeCmd).isAbsolute()) {
+        // Try to detect command in environment
+        const QString tmp = buildConfiguration()->environment().searchInPath(m_makeCmd);
+        if (tmp.isEmpty()) {
+            emit addOutput(tr("Could not find make command: %1 in the build environment").arg(m_makeCmd), BuildStep::ErrorOutput);
+            return false;
+        }
+        m_makeCmd = tmp;
+    }
+
+    m_environment = qt4BuildConfiguration()->environment();
+
+    m_args.clear();
     if (m_createSmartInstaller)
-        args << QLatin1String("installer_sis");
+        m_args << QLatin1String("installer_sis");
     else
-        args << QLatin1String("sis");
+        m_args << QLatin1String("sis");
     if (signingMode() == SignCustom) {
-        args << QLatin1String("QT_SIS_CERTIFICATE=") + QDir::toNativeSeparators(customSignaturePath())
-             << QLatin1String("QT_SIS_KEY=") + QDir::toNativeSeparators(customKeyPath());
+        m_args << QLatin1String("QT_SIS_CERTIFICATE=") + QDir::toNativeSeparators(customSignaturePath())
+               << QLatin1String("QT_SIS_KEY=") + QDir::toNativeSeparators(customKeyPath());
+    }
+
+    delete m_outputParserChain;
+    m_outputParserChain = new ProjectExplorer::GnuMakeParser;
+    m_outputParserChain->appendOutputParser(new Qt4ProjectManager::AbldParser);
+    connect(m_outputParserChain, SIGNAL(addOutput(QString, ProjectExplorer::BuildStep::OutputFormat)),
+            this, SLOT(outputAdded(QString, ProjectExplorer::BuildStep::OutputFormat)));
+    connect(m_outputParserChain, SIGNAL(addTask(ProjectExplorer::Task)),
+            this, SLOT(taskAdded(ProjectExplorer::Task)));
+
+    return true;
+}
+
+void S60CreatePackageStep::run(QFutureInterface<bool> &fi)
+{
+    m_futureInterface = &fi;
+
+    if (m_workingDirectories.isEmpty()) {
+        fi.reportResult(true);
+        return;
+    }
+
+    // Setup everything...
+    m_process = new QProcess();
+    m_process->setEnvironment(m_environment.toStringList());
+
+    connect(m_process, SIGNAL(readyReadStandardOutput()),
+            this, SLOT(processReadyReadStdOutput()),
+            Qt::DirectConnection);
+    connect(m_process, SIGNAL(readyReadStandardError()),
+            this, SLOT(processReadyReadStdError()),
+            Qt::DirectConnection);
+
+    connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
+            this, SLOT(slotProcessFinished(int, QProcess::ExitStatus)),
+            Qt::DirectConnection);
+
+    m_timer = new QTimer();
+    connect(m_timer, SIGNAL(timeout()), this, SLOT(checkForCancel()), Qt::DirectConnection);
+    m_timer->start(500);
+    m_eventLoop = new QEventLoop;
+
+    bool returnValue = false;
+    if (startProcess())
+        returnValue = m_eventLoop->exec();
+
+    // Finished
+    m_timer->stop();
+    delete m_timer;
+    m_timer = 0;
+
+    delete m_process;
+    m_process = 0;
+    delete m_eventLoop;
+    m_eventLoop = 0;
+    fi.reportResult(returnValue);
+    m_futureInterface = 0;
+
+    return;
+}
+
+void S60CreatePackageStep::slotProcessFinished(int, QProcess::ExitStatus)
+{
+    QString line = QString::fromLocal8Bit(m_process->readAllStandardError());
+    if (!line.isEmpty())
+        stdError(line);
+
+    line = QString::fromLocal8Bit(m_process->readAllStandardOutput());
+    if (!line.isEmpty())
+        stdOutput(line);
+
+    bool returnValue = false;
+    if (m_process->exitStatus() == QProcess::NormalExit && m_process->exitCode() == 0) {
+        emit addOutput(tr("The process \"%1\" exited normally.")
+                       .arg(QDir::toNativeSeparators(m_makeCmd)),
+                       BuildStep::MessageOutput);
+        returnValue = true;
+    } else if (m_process->exitStatus() == QProcess::NormalExit) {
+        emit addOutput(tr("The process \"%1\" exited with code %2.")
+                       .arg(QDir::toNativeSeparators(m_makeCmd), QString::number(m_process->exitCode())),
+                       BuildStep::ErrorMessageOutput);
+    } else {
+        emit addOutput(tr("The process \"%1\" crashed.").arg(QDir::toNativeSeparators(m_makeCmd)), BuildStep::ErrorMessageOutput);
+    }
+
+    if (m_workingDirectories.isEmpty() || !returnValue) {
+        m_eventLoop->exit(returnValue);
+    } else {
+        // Success, do next
+        if (!startProcess())
+            m_eventLoop->exit(returnValue);
     }
-    setArguments(args); // overwrite any stuff done in make step
+}
+
+bool S60CreatePackageStep::startProcess()
+{
+    QString workingDirectory = m_workingDirectories.takeFirst();
+    QDir wd(workingDirectory);
+    if (!wd.exists())
+        wd.mkpath(wd.absolutePath());
 
-    ProjectExplorer::GnuMakeParser *parser = new ProjectExplorer::GnuMakeParser;
-    parser->appendOutputParser(new Qt4ProjectManager::AbldParser);
-    setOutputParser(parser);
+    m_process->setWorkingDirectory(workingDirectory);
 
+    // Go for it!
+    m_process->start(m_makeCmd, m_args);
+    if (!m_process->waitForStarted()) {
+        emit addOutput(tr("Could not start process \"%1\" in %2")
+                       .arg(QDir::toNativeSeparators(m_makeCmd),
+                            workingDirectory),
+                       BuildStep::ErrorMessageOutput);
+        return false;
+    }
+    emit addOutput(tr("Starting: \"%1\" %2 in %3\n")
+                   .arg(QDir::toNativeSeparators(m_makeCmd),
+                        m_args.join(" "),
+                        workingDirectory),
+                   BuildStep::MessageOutput);
     return true;
 }
 
+void S60CreatePackageStep::processReadyReadStdOutput()
+{
+    m_process->setReadChannel(QProcess::StandardOutput);
+    while (m_process->canReadLine()) {
+        QString line = QString::fromLocal8Bit(m_process->readLine());
+        stdOutput(line);
+    }
+}
+
+void S60CreatePackageStep::stdOutput(const QString &line)
+{
+    if (m_outputParserChain)
+        m_outputParserChain->stdOutput(line);
+    emit addOutput(line, BuildStep::NormalOutput);
+}
+
+void S60CreatePackageStep::processReadyReadStdError()
+{
+    m_process->setReadChannel(QProcess::StandardError);
+    while (m_process->canReadLine()) {
+        QString line = QString::fromLocal8Bit(m_process->readLine());
+        stdError(line);
+    }
+}
+
+void S60CreatePackageStep::stdError(const QString &line)
+{
+    if (m_outputParserChain)
+        m_outputParserChain->stdError(line);
+    emit addOutput(line, BuildStep::ErrorOutput);
+}
+
+void S60CreatePackageStep::checkForCancel()
+{
+    if (m_futureInterface->isCanceled() && m_timer->isActive()) {
+        m_timer->stop();
+        m_process->terminate();
+        m_process->waitForFinished(5000);
+        m_process->kill();
+    }
+}
+
+void S60CreatePackageStep::taskAdded(const ProjectExplorer::Task &task)
+{
+    ProjectExplorer::Task editable(task);
+    QString filePath = QDir::cleanPath(task.file.trimmed());
+    if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) {
+        // TODO which kind of tasks do we get from package building?
+        // No absoulte path
+    }
+    emit addTask(editable);
+}
+
+void S60CreatePackageStep::outputAdded(const QString &string, ProjectExplorer::BuildStep::OutputFormat format)
+{
+    emit addOutput(string, format);
+}
+
+
 bool S60CreatePackageStep::immutable() const
 {
     return false;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h
index fd74500b9b60550886cd74379df2823b0d934e9e..e4a03985adc5d2239f988947a7e12a145b690214 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.h
@@ -59,7 +59,8 @@ public:
     ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildConfiguration *parent, ProjectExplorer::BuildStep::Type type, ProjectExplorer::BuildStep *product);
 };
 
-class S60CreatePackageStep : public MakeStep {
+class S60CreatePackageStep : public ProjectExplorer::BuildStep
+{
     Q_OBJECT
     friend class S60CreatePackageStepFactory;
 public:
@@ -72,6 +73,7 @@ public:
     virtual ~S60CreatePackageStep();
 
     virtual bool init();
+    virtual void run(QFutureInterface<bool> &fi);
     virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
     virtual bool immutable() const;
 
@@ -91,13 +93,38 @@ protected:
     S60CreatePackageStep(ProjectExplorer::BuildConfiguration *bc, const QString &id);
     bool fromMap(const QVariantMap &map);
 
+    Qt4BuildConfiguration *qt4BuildConfiguration() const;
+
+private slots:
+    void slotProcessFinished(int, QProcess::ExitStatus);
+    void processReadyReadStdOutput();
+    void processReadyReadStdError();
+    void taskAdded(const ProjectExplorer::Task &task);
+    void outputAdded(const QString &string, ProjectExplorer::BuildStep::OutputFormat format);
+    void checkForCancel();
+
 private:
+    void stdOutput(const QString &line);
+    void stdError(const QString &line);
+    bool startProcess();
+    QStringList m_workingDirectories;
+
+    QString m_makeCmd;
+    ProjectExplorer::Environment m_environment;
+    QStringList m_args;
+
     void ctor_package();
 
     SigningMode m_signingMode;
     QString m_customSignaturePath;
     QString m_customKeyPath;
     bool m_createSmartInstaller;
+    ProjectExplorer::IOutputParser *m_outputParserChain;
+
+    QProcess *m_process;
+    QTimer *m_timer;
+    QEventLoop *m_eventLoop;
+    QFutureInterface<bool> *m_futureInterface;
 };
 
 class S60CreatePackageStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp
index 129f52f7ccd6b335fe3d6f9a47bac63457d5ebcb..d1a9df646c61cf035fdbaf07fa64f7bdb2cf2d0c 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp
@@ -126,8 +126,9 @@ bool S60DeployStep::init()
     }
     m_serialPortName = runConfiguration->serialPortName();
     m_serialPortFriendlyName = SymbianUtils::SymbianDeviceManager::instance()->friendlyNameForPort(m_serialPortName);
-    m_packageFileNameWithTarget = runConfiguration->packageFileNameWithTargetInfo();
-    m_signedPackage = runConfiguration->signedPackage();
+    m_packageFileNamesWithTarget = runConfiguration->packageFileNamesWithTargetInfo();
+    m_signedPackages = runConfiguration->signedPackages();
+
     m_installationDrive = runConfiguration->installationDrive();
     m_silentInstall = runConfiguration->silentInstall();
 
@@ -174,31 +175,31 @@ void S60DeployStep::appendMessage(const QString &error, bool isError)
 
 bool S60DeployStep::processPackageName(QString &errorMessage)
 {
-    QFileInfo packageInfo(m_signedPackage);
-    {
+    for (int i = 0; i < m_signedPackages.count(); ++i) {
+        QFileInfo packageInfo(m_signedPackages.at(i));
         // support for 4.6.1 and pre, where make sis creates 'targetname_armX_udeb.sis' instead of 'targetname.sis'
-        QFileInfo packageWithTargetInfo(m_packageFileNameWithTarget);
+        QFileInfo packageWithTargetInfo(m_packageFileNamesWithTarget.at(i));
         // does the 4.6.1 version exist?
         if (packageWithTargetInfo.exists() && packageWithTargetInfo.isFile()) {
             // is the 4.6.1 version newer? (to guard against behavior change Qt Creator 1.3 --> 2.0)
             if (!packageInfo.exists() || packageInfo.lastModified() < packageWithTargetInfo.lastModified()) { //TODO change the QtCore
                 // the 'targetname_armX_udeb.sis' crap exists and is new, rename it
                 appendMessage(tr("Renaming new package '%1' to '%2'")
-                              .arg(QDir::toNativeSeparators(m_packageFileNameWithTarget),
-                                   QDir::toNativeSeparators(m_signedPackage)), false);
-                return renameFile(m_packageFileNameWithTarget, m_signedPackage, &errorMessage);
+                              .arg(QDir::toNativeSeparators(m_packageFileNamesWithTarget.at(i)),
+                                   QDir::toNativeSeparators(m_signedPackages.at(i))), false);
+                return renameFile(m_packageFileNamesWithTarget.at(i), m_signedPackages.at(i), &errorMessage);
             } else {
                 // the 'targetname_armX_udeb.sis' crap exists but is old, remove it
                 appendMessage(tr("Removing old package '%1'")
-                              .arg(QDir::toNativeSeparators(m_packageFileNameWithTarget)),
+                              .arg(QDir::toNativeSeparators(m_packageFileNamesWithTarget.at(i))),
                               false);
-                ensureDeleteFile(m_packageFileNameWithTarget, &errorMessage);
+                ensureDeleteFile(m_packageFileNamesWithTarget.at(i), &errorMessage);
             }
         }
-    }
-    if (!packageInfo.exists() || !packageInfo.isFile()) {
-        errorMessage = tr("Package file not found");
-        return false;
+        if (!packageInfo.exists() || !packageInfo.isFile()) {
+            errorMessage = tr("'%1': Package file not found").arg(m_signedPackages.at(i));
+            return false;
+        }
     }
     return true;
 }
@@ -217,7 +218,7 @@ void S60DeployStep::start()
     if (processPackageName(errorMessage)) {
         startDeployment();
     } else {
-        errorMessage = tr("Failed to find package '%1': %2").arg(m_signedPackage, errorMessage);
+        errorMessage = tr("Failed to find package %1").arg(errorMessage);
         appendMessage(errorMessage, true);
         stop();
         emit finished();
@@ -253,16 +254,19 @@ void S60DeployStep::startDeployment()
 
     setupConnections();
 
-    const QString copyDst = QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(QFileInfo(m_signedPackage).fileName());
+    QStringList copyDst;
+    foreach (const QString &signedPackage, m_signedPackages)
+        copyDst << QString::fromLatin1("%1:\\Data\\%1").arg(m_installationDrive).arg(QFileInfo(signedPackage).fileName());
 
-    m_launcher->setCopyFileName(m_signedPackage, copyDst);
-    m_launcher->setInstallFileName(copyDst);
+    m_launcher->setCopyFileNames(m_signedPackages, copyDst);
+    m_launcher->setInstallFileNames(copyDst);
     m_launcher->setInstallationDrive(m_installationDrive);
     m_launcher->setInstallationMode(m_silentInstall?trk::Launcher::InstallationModeSilentAndUser:
                                                     trk::Launcher::InstallationModeUser);
     m_launcher->addStartupActions(trk::Launcher::ActionCopyInstall);
 
-    appendMessage(tr("Package: %1\nDeploying application to '%2'...").arg(m_signedPackage, m_serialPortFriendlyName), false);
+    // TODO readd information about packages? msgListFile(m_signedPackage)
+    appendMessage(tr("Deploying application to '%2'...").arg(m_serialPortFriendlyName), false);
 
     QString errorMessage;
     if (!m_launcher->startServer(&errorMessage)) {
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h
index 2023270b5c63f2f93d2363a70b5e217913cc5f13..e3c324669dc7c78686d73d61f8841a1375a70761 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h
@@ -129,8 +129,8 @@ signals:
 private:
     QString m_serialPortName;
     QString m_serialPortFriendlyName;
-    QString m_packageFileNameWithTarget; // Support for 4.6.1
-    QString m_signedPackage;
+    QStringList m_packageFileNamesWithTarget; // Support for 4.6.1
+    QStringList m_signedPackages;
 
     QTimer *m_timer;
 
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
index 4c66d059c7f5b12db3404b24230b924f1d21a9ac..8bb36a1982385ee23c00591e6fbce2aef0f61f32 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
@@ -286,16 +286,22 @@ static inline QString fixBaseNameTarget(const QString &in)
     return in;
 }
 
-QString S60DeviceRunConfiguration::packageFileNameWithTargetInfo() const
-{
-    TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
-    if (!ti.valid)
-        return QString();
-    QString baseFileName = ti.buildDir + QLatin1Char('/') + ti.target;
-    baseFileName += QLatin1Char('_')
-                    + (isDebug() ? QLatin1String("debug") : QLatin1String("release"))
-                    + QLatin1Char('-') + symbianPlatform() + QLatin1String(".sis");
-    return baseFileName;
+QStringList S60DeviceRunConfiguration::packageFileNamesWithTargetInfo() const
+{
+    QList<Qt4ProFileNode *> leafs = qt4Target()->qt4Project()->leafProFiles();
+
+    QStringList result;
+    foreach (Qt4ProFileNode *qt4ProFileNode, leafs) {
+        TargetInformation ti = qt4ProFileNode->targetInformation();
+        if (!ti.valid)
+            continue;
+        QString baseFileName = ti.buildDir + QLatin1Char('/') + ti.target;
+        baseFileName += QLatin1Char('_')
+                + (isDebug() ? QLatin1String("debug") : QLatin1String("release"))
+                + QLatin1Char('-') + symbianPlatform() + QLatin1String(".sis");
+        result << baseFileName;
+    }
+    return result;
 }
 
 QString S60DeviceRunConfiguration::symbianPlatform() const
@@ -323,7 +329,19 @@ QString S60DeviceRunConfiguration::symbianTarget() const
     return isDebug() ? QLatin1String("udeb") : QLatin1String("urel");
 }
 
-QString S60DeviceRunConfiguration::packageTemplateFileName() const
+QStringList S60DeviceRunConfiguration::packageTemplateFileNames() const
+{
+    QList<Qt4ProFileNode *> list = qt4Target()->qt4Project()->leafProFiles();
+    QStringList result;
+    foreach (Qt4ProFileNode *node, list) {
+        TargetInformation ti = node->targetInformation();
+        if (ti.valid)
+            result << ti.buildDir + QLatin1Char('/') + ti.target + QLatin1String("_template.pkg");
+    }
+    return result;
+}
+
+QString S60DeviceRunConfiguration::appPackageTemplateFileName() const
 {
     TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
     if (!ti.valid)
@@ -331,6 +349,7 @@ QString S60DeviceRunConfiguration::packageTemplateFileName() const
     return ti.buildDir + QLatin1Char('/') + ti.target + QLatin1String("_template.pkg");
 }
 
+
 /* Grep a package file for the '.exe' file. Curently for use on Linux only
  * as the '.pkg'-files on Windows do not contain drive letters, which is not
  * handled here. \code
@@ -373,7 +392,7 @@ QString S60DeviceRunConfiguration::localExecutableFileName() const
     switch (toolChainType()) {
     case ToolChain::GCCE_GNUPOC:
     case ToolChain::RVCT_ARMV5_GNUPOC:
-        localExecutable = executableFromPackageUnix(packageTemplateFileName());
+        localExecutable = executableFromPackageUnix(appPackageTemplateFileName());
         break;
     default: {
             const QtVersion *qtv = qtVersion();
@@ -403,7 +422,21 @@ bool S60DeviceRunConfiguration::runSmartInstaller() const
     return false;
 }
 
-QString S60DeviceRunConfiguration::signedPackage() const
+QStringList S60DeviceRunConfiguration::signedPackages() const
+{
+    QList<Qt4ProFileNode *> list = qt4Target()->qt4Project()->leafProFiles();
+    QStringList result;
+    foreach (Qt4ProFileNode *node, list) {
+        TargetInformation ti = node->targetInformation();
+        if (ti.valid)
+            result << ti.buildDir + QLatin1Char('/') + ti.target
+                      + (runSmartInstaller() ? QLatin1String("_installer") : QLatin1String(""))
+                      + QLatin1String(".sis");
+    }
+    return result;
+}
+
+QString S60DeviceRunConfiguration::appSignedPackage() const
 {
     TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(m_proFilePath);
     if (!ti.valid)
@@ -640,7 +673,6 @@ void S60DeviceRunControlBase::startDeployment()
 
         if (!m_commandLineArguments.isEmpty())
             m_launcher->setCommandLineArgs(m_commandLineArguments);
-			
         const QString runFileName = QString::fromLatin1("%1:\\sys\\bin\\%2.exe").arg(m_installationDrive).arg(m_targetName);
         initLauncher(runFileName, m_launcher);
         const trk::PromptStartCommunicationResult src =
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
index d17716f9574971c85c2f40d7cb19accabb8f98a6..b2c7a4883a2f0c1027341f4900bf83e2e6320802 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
@@ -82,15 +82,14 @@ public:
     char installationDrive() const;
     void setInstallationDrive(char drive);
 
+    QStringList packageFileNamesWithTargetInfo() const;
+    QStringList packageTemplateFileNames() const;
+    QString appPackageTemplateFileName() const;
     QString targetName() const;
-    QString packageFileNameWithTargetInfo() const;
-    QString symbianPlatform() const;
-    QString symbianTarget() const;
-    bool isDebug() const;
-    QString packageTemplateFileName() const;
 
     QString localExecutableFileName() const;
-    QString signedPackage() const;
+    QStringList signedPackages() const;
+    QString appSignedPackage() const;
     const QtVersion *qtVersion() const;
 
     QStringList commandLineArguments() const;
@@ -107,6 +106,7 @@ signals:
     void targetInformationChanged();
     void serialPortNameChanged();
 
+
 private slots:
     void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro);
     void updateActiveBuildConfiguration(ProjectExplorer::BuildConfiguration *buildConfiguration);
@@ -116,6 +116,9 @@ protected:
     virtual bool fromMap(const QVariantMap &map);
 
 private:
+    QString symbianPlatform() const;
+    QString symbianTarget() const;
+    bool isDebug() const;
     ProjectExplorer::ToolChain::ToolChainType toolChainType(ProjectExplorer::BuildConfiguration *configuration) const;
     void ctor();
 
@@ -197,7 +200,6 @@ private:
     QString m_serialPortFriendlyName;
     QString m_targetName;
     QStringList m_commandLineArguments;
-    QString m_workingDirectory;
     QString m_executableFileName;
     QString m_qtDir;
     QString m_qtBinPath;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
index d180b23498771ec58407ee4784f6b8c0647229e2..cb3a4c08c2e43d78f3b821c83c70caa5c72f41b6 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
@@ -247,7 +247,7 @@ void S60DeviceRunConfigurationWidget::argumentsEdited(const QString &text)
 
 void S60DeviceRunConfigurationWidget::updateTargetInformation()
 {
-    m_sisFileLabel->setText(QDir::toNativeSeparators(m_runConfiguration->signedPackage()));
+    m_sisFileLabel->setText(QDir::toNativeSeparators(m_runConfiguration->appPackageTemplateFileName()));
 }
 
 void S60DeviceRunConfigurationWidget::setInstallationDrive(int index)
diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp
index 3e42ca965e81921c75a74f809e2d2ba1bbcf676f..202431549185afbebb468d6db477573725b6948a 100644
--- a/src/plugins/qt4projectmanager/qt4project.cpp
+++ b/src/plugins/qt4projectmanager/qt4project.cpp
@@ -977,6 +977,19 @@ QList<BuildConfigWidget*> Qt4Project::subConfigWidgets()
     return subWidgets;
 }
 
+void Qt4Project::collectLeafProFiles(QList<Qt4ProFileNode *> &list, Qt4ProFileNode *node)
+{
+    if (node->projectType() != Internal::SubDirsTemplate) {
+        list.append(node);
+    }
+    foreach (ProjectNode *n, node->subProjectNodes()) {
+        Qt4ProFileNode *qt4ProFileNode = qobject_cast<Qt4ProFileNode *>(n);
+        if (qt4ProFileNode)
+            collectLeafProFiles(list, qt4ProFileNode);
+    }
+}
+
+
 void Qt4Project::collectApplicationProFiles(QList<Qt4ProFileNode *> &list, Qt4ProFileNode *node)
 {
     if (node->projectType() == Internal::ApplicationTemplate
@@ -1035,6 +1048,15 @@ void Qt4Project::createApplicationProjects()
     }
 }
 
+QList<Qt4ProFileNode *> Qt4Project::leafProFiles() const
+{
+    QList<Qt4ProFileNode *> list;
+    if (!rootProjectNode())
+        return list;
+    collectLeafProFiles(list, rootProjectNode());
+    return list;
+}
+
 QList<Qt4ProFileNode *> Qt4Project::applicationProFiles() const
 {
     QList<Qt4ProFileNode *> list;
diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h
index 7cd90165059975be4fa59722d84e7e1967acd1fa..2d805c21cb6e3cc5d91de624af2694bead3a1e27 100644
--- a/src/plugins/qt4projectmanager/qt4project.h
+++ b/src/plugins/qt4projectmanager/qt4project.h
@@ -136,6 +136,7 @@ public:
     ProjectExplorer::BuildConfigWidget *createConfigWidget();
     QList<ProjectExplorer::BuildConfigWidget*> subConfigWidgets();
 
+    QList<Internal::Qt4ProFileNode *> leafProFiles() const;
     QList<Internal::Qt4ProFileNode *> applicationProFiles() const;
     bool hasApplicationProFile(const QString &path) const;
     QStringList applicationProFilePathes(const QString &prepend = QString()) const;
@@ -191,6 +192,7 @@ private:
     void updateCodeModel();
     void updateFileList();
 
+    static void collectLeafProFiles(QList<Internal::Qt4ProFileNode *> &list, Internal::Qt4ProFileNode *node);
     static void collectApplicationProFiles(QList<Internal::Qt4ProFileNode *> &list, Internal::Qt4ProFileNode *node);
     static void findProFile(const QString& fileName, Internal::Qt4ProFileNode *root, QList<Internal::Qt4ProFileNode *> &list);
     static bool hasSubNode(Internal::Qt4PriFileNode *root, const QString &path);
diff --git a/src/shared/symbianutils/launcher.cpp b/src/shared/symbianutils/launcher.cpp
index e6b790f45af0bbc9bfeb7741353315333645026f..4f8eaf7ad28875a776edf4840e649c2deb5309a6 100644
--- a/src/shared/symbianutils/launcher.cpp
+++ b/src/shared/symbianutils/launcher.cpp
@@ -74,15 +74,24 @@ void CrashReportState::clear()
 }
 
 struct LauncherPrivate {
-    struct CopyState {
-        QString sourceFileName;
-        QString destinationFileName;
+    struct TransferState {
+        int currentFileName;
         uint copyFileHandle;
         QScopedPointer<QByteArray> data;
         qint64 position;
         QScopedPointer<QFile> localFile;
     };
 
+    struct CopyState : public TransferState {
+        QStringList sourceFileNames;
+        QStringList destinationFileNames;
+    };
+
+    struct DownloadState : public TransferState {
+        QString sourceFileName;
+        QString destinationFileName;
+    };
+
     explicit LauncherPrivate(const TrkDevicePtr &d);
 
     TrkDevicePtr m_device;
@@ -94,10 +103,11 @@ struct LauncherPrivate {
     Session m_session; // global-ish data (process id, target information)
 
     CopyState m_copyState;
-    CopyState m_downloadState;
+    DownloadState m_downloadState;
     QString m_fileName;
     QStringList m_commandLineArgs;
-    QString m_installFileName;
+    QStringList m_installFileNames;
+    int m_currentInstallFileName;
     int m_verbose;
     Launcher::Actions m_startupActions;
     bool m_closeDevice;
@@ -188,10 +198,11 @@ void Launcher::setFileName(const QString &name)
     d->m_fileName = name;
 }
 
-void Launcher::setCopyFileName(const QString &srcName, const QString &dstName)
+void Launcher::setCopyFileNames(const QStringList &srcNames, const QStringList &dstNames)
 {
-    d->m_copyState.sourceFileName = srcName;
-    d->m_copyState.destinationFileName = dstName;
+    d->m_copyState.sourceFileNames = srcNames;
+    d->m_copyState.destinationFileNames = dstNames;
+    d->m_copyState.currentFileName = 0;
 }
 
 void Launcher::setDownloadFileName(const QString &srcName, const QString &dstName)
@@ -200,9 +211,10 @@ void Launcher::setDownloadFileName(const QString &srcName, const QString &dstNam
     d->m_downloadState.destinationFileName = dstName;
 }
 
-void Launcher::setInstallFileName(const QString &name)
+void Launcher::setInstallFileNames(const QStringList &names)
 {
-    d->m_installFileName = name;
+    d->m_installFileNames = names;
+    d->m_currentInstallFileName = 0;
 }
 
 void Launcher::setCommandLineArgs(const QStringList &args)
@@ -255,28 +267,29 @@ bool Launcher::startServer(QString *errorMessage)
             str << " Executable=" << d->m_fileName;
         if (!d->m_commandLineArgs.isEmpty())
             str << " Arguments= " << d->m_commandLineArgs.join(QString(QLatin1Char(' ')));
-        if (!d->m_copyState.sourceFileName.isEmpty())
-            str << " Package/Source=" << d->m_copyState.sourceFileName;
-        if (!d->m_copyState.destinationFileName.isEmpty())
-            str << " Remote Package/Destination=" << d->m_copyState.destinationFileName;
+        for (int i = 0; i < d->m_copyState.sourceFileNames.size(); ++i) {
+            str << " Package/Source=" << d->m_copyState.sourceFileNames.at(i);
+            str << " Remote Package/Destination=" << d->m_copyState.destinationFileNames.at(i);
+        }
         if (!d->m_downloadState.sourceFileName.isEmpty())
             str << " Source=" << d->m_downloadState.sourceFileName;
         if (!d->m_downloadState.destinationFileName.isEmpty())
             str << " Destination=" << d->m_downloadState.destinationFileName;
-        if (!d->m_installFileName.isEmpty())
-            str << " Install file=" << d->m_installFileName;
+        if (!d->m_installFileNames.isEmpty())
+            foreach (const QString &installFileName, d->m_installFileNames)
+                str << " Install file=" << installFileName;
         logMessage(msg);
     }
     if (d->m_startupActions & ActionCopy) {
-        if (d->m_copyState.sourceFileName.isEmpty()) {
+        if (d->m_copyState.sourceFileNames.isEmpty()) {
             qWarning("No local filename given for copying package.");
             return false;
-        } else if (d->m_copyState.destinationFileName.isEmpty()) {
+        } else if (d->m_copyState.destinationFileNames.isEmpty()) {
             qWarning("No remote filename given for copying package.");
             return false;
         }
     }
-    if (d->m_startupActions & ActionInstall && d->m_installFileName.isEmpty()) {
+    if (d->m_startupActions & ActionInstall && d->m_installFileNames.isEmpty()) {
         qWarning("No package name given for installing.");
         return false;
     }
@@ -573,15 +586,15 @@ static inline QString msgCannotOpenLocalFile(const QString &fileName, const QStr
 void Launcher::handleFileCreation(const TrkResult &result)
 {
     if (result.errorCode() || result.data.size() < 6) {
-        const QString msg = msgCannotOpenRemoteFile(d->m_copyState.destinationFileName, result.errorString());
+        const QString msg = msgCannotOpenRemoteFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), result.errorString());
         logMessage(msg);
-        emit canNotCreateFile(d->m_copyState.destinationFileName, msg);
+        emit canNotCreateFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), msg);
         disconnectTrk();
         return;
     }
     const char *data = result.data.data();
     d->m_copyState.copyFileHandle = extractInt(data + 2);
-    const QString localFileName = d->m_copyState.sourceFileName;
+    const QString localFileName = d->m_copyState.sourceFileNames.at(d->m_copyState.currentFileName);
     QFile file(localFileName);
     d->m_copyState.position = 0;
     if (!file.open(QIODevice::ReadOnly)) {
@@ -657,7 +670,7 @@ void Launcher::handleCopy(const TrkResult &result)
 {
     if (result.errorCode() || result.data.size() < 4) {
         closeRemoteFile(true);
-        emit canNotWriteFile(d->m_copyState.destinationFileName, result.errorString());
+        emit canNotWriteFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), result.errorString());
         disconnectTrk();
     } else {
         continueCopying(extractShort(result.data.data() + 2));
@@ -693,7 +706,7 @@ void Launcher::closeRemoteFile(bool failed)
     d->m_device->sendTrkMessage(TrkCloseFile,
                                failed ? TrkCallback() : TrkCallback(this, &Launcher::handleFileCopied),
                                ba);
-    d->m_copyState.data.reset();
+    d->m_copyState.data.reset(0);
     d->m_copyState.copyFileHandle = 0;
     d->m_copyState.position = 0;
 }
@@ -701,15 +714,21 @@ void Launcher::closeRemoteFile(bool failed)
 void Launcher::handleFileCopied(const TrkResult &result)
 {
     if (result.errorCode())
-        emit canNotCloseFile(d->m_copyState.destinationFileName, result.errorString());
-    if (d->m_startupActions & ActionInstall)
+        emit canNotCloseFile(d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName), result.errorString());
+
+    ++d->m_copyState.currentFileName;
+
+    if (d->m_startupActions & ActionInstall && d->m_copyState.currentFileName < d->m_copyState.sourceFileNames.size()) {
+        copyFileToRemote();
+    } else if (d->m_startupActions & ActionInstall) {
         installRemotePackage();
-    else if (d->m_startupActions & ActionRun)
+    } else if (d->m_startupActions & ActionRun) {
         startInferiorIfNeeded();
-    else if (d->m_startupActions & ActionDownload)
+    } else if (d->m_startupActions & ActionDownload) {
         copyFileFromRemote();
-    else
+    } else {
         disconnectTrk();
+    }
 }
 
 void Launcher::handleCpuType(const TrkResult &result)
@@ -856,7 +875,7 @@ void Launcher::copyFileToRemote()
     emit copyingStarted();
     QByteArray ba;
     ba.append(char(10)); //kDSFileOpenWrite | kDSFileOpenBinary
-    appendString(&ba, d->m_copyState.destinationFileName.toLocal8Bit(), TargetByteOrder, false);
+    appendString(&ba, d->m_copyState.destinationFileNames.at(d->m_copyState.currentFileName).toLocal8Bit(), TargetByteOrder, false);
     d->m_device->sendTrkMessage(TrkOpenFile, TrkCallback(this, &Launcher::handleFileCreation), ba);
 }
 
@@ -875,7 +894,7 @@ void Launcher::installRemotePackageSilently()
     d->m_currentInstallationStep = InstallationModeSilent;
     QByteArray ba;
     ba.append((char)QChar::toUpper((ushort)d->m_installationDrive));
-    appendString(&ba, d->m_installFileName.toLocal8Bit(), TargetByteOrder, false);
+    appendString(&ba, d->m_installFileNames.at(d->m_currentInstallFileName).toLocal8Bit(), TargetByteOrder, false);
     d->m_device->sendTrkMessage(TrkInstallFile, TrkCallback(this, &Launcher::handleInstallPackageFinished), ba);
 }
 
@@ -884,7 +903,7 @@ void Launcher::installRemotePackageByUser()
     emit installingStarted();
     d->m_currentInstallationStep = InstallationModeUser;
     QByteArray ba;
-    appendString(&ba, d->m_installFileName.toLocal8Bit(), TargetByteOrder, false);
+    appendString(&ba, d->m_installFileNames.at(d->m_currentInstallFileName).toLocal8Bit(), TargetByteOrder, false);
     d->m_device->sendTrkMessage(TrkInstallFile2, TrkCallback(this, &Launcher::handleInstallPackageFinished), ba);
 }
 
@@ -911,13 +930,19 @@ void Launcher::handleInstallPackageFinished(const TrkResult &result)
             installRemotePackageByUser();
             return;
         }
-        emit canNotInstall(d->m_installFileName, result.errorString());
+        emit canNotInstall(d->m_installFileNames.at(d->m_currentInstallFileName), result.errorString());
         disconnectTrk();
         return;
-    } else {
-        emit installingFinished();
     }
-    if (d->m_startupActions & ActionRun) {
+
+    ++d->m_currentInstallFileName;
+
+    if (d->m_currentInstallFileName == d->m_installFileNames.size())
+        emit installingFinished();
+
+    if (d->m_startupActions & ActionInstall && d->m_currentInstallFileName < d->m_installFileNames.size()) {
+        installRemotePackage();
+    } else if (d->m_startupActions & ActionRun) {
         startInferiorIfNeeded();
     } else if (d->m_startupActions & ActionDownload) {
         copyFileFromRemote();
@@ -973,6 +998,7 @@ void Launcher::startInferiorIfNeeded()
         logMessage("Process already 'started'");
         return;
     }
+
     d->m_device->sendTrkMessage(TrkCreateItem, TrkCallback(this, &Launcher::handleCreateProcess),
                                 startProcessMessage(d->m_fileName, d->m_commandLineArgs)); // Create Item
 }
diff --git a/src/shared/symbianutils/launcher.h b/src/shared/symbianutils/launcher.h
index c2270f1402fcadea1ff0acc2f1cc4a5042eeb10c..1a822f357bde93de903b4388d7333b7d1f16d330 100644
--- a/src/shared/symbianutils/launcher.h
+++ b/src/shared/symbianutils/launcher.h
@@ -89,9 +89,9 @@ public:
     void setTrkServerName(const QString &name);
     QString trkServerName() const;
     void setFileName(const QString &name);
-    void setCopyFileName(const QString &srcName, const QString &dstName);
+    void setCopyFileNames(const QStringList &srcName, const QStringList &dstName);
     void setDownloadFileName(const QString &srcName, const QString &dstName);
-    void setInstallFileName(const QString &name);
+    void setInstallFileNames(const QStringList &names);
     void setCommandLineArgs(const QStringList &args);
     bool startServer(QString *errorMessage);
     void setInstallationMode(InstallationMode installation);