forked from qt-creator/qt-creator
ProjectExplorer: Introduce generic application runner.
This class aims to be a flexible worker class for SSH-based run controls. It supersedes AbstractRemoteLinuxApplicationRunner as well as all of its derived classes, while having no RemoteLinux dependencies itself. Change-Id: If24f03a32126b36fc3d0b253a1615ad0af5f2b46 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -11,7 +11,6 @@ HEADERS += \
|
||||
debianmanager.h \
|
||||
maemoconstants.h \
|
||||
maemorunconfigurationwidget.h \
|
||||
maemoruncontrol.h \
|
||||
maemorunfactories.h \
|
||||
maemosettingspages.h \
|
||||
maemopackagecreationstep.h \
|
||||
@@ -20,8 +19,6 @@ HEADERS += \
|
||||
maemoqemumanager.h \
|
||||
maemodeploystepfactory.h \
|
||||
maemoglobal.h \
|
||||
maemosshrunner.h \
|
||||
maemodebugsupport.h \
|
||||
maemoremotemountsmodel.h \
|
||||
maemomountspecification.h \
|
||||
maemoremotemounter.h \
|
||||
@@ -52,13 +49,13 @@ HEADERS += \
|
||||
maddedevicetester.h \
|
||||
maddedeviceconfigurationfactory.h \
|
||||
maddedevice.h \
|
||||
rpmmanager.h
|
||||
rpmmanager.h \
|
||||
maemoapplicationrunnerhelperactions.h
|
||||
|
||||
SOURCES += \
|
||||
maddeplugin.cpp \
|
||||
debianmanager.cpp \
|
||||
maemorunconfigurationwidget.cpp \
|
||||
maemoruncontrol.cpp \
|
||||
maemorunfactories.cpp \
|
||||
maemosettingspages.cpp \
|
||||
maemopackagecreationstep.cpp \
|
||||
@@ -67,8 +64,6 @@ SOURCES += \
|
||||
maemoqemumanager.cpp \
|
||||
maemodeploystepfactory.cpp \
|
||||
maemoglobal.cpp \
|
||||
maemosshrunner.cpp \
|
||||
maemodebugsupport.cpp \
|
||||
maemoremotemountsmodel.cpp \
|
||||
maemomountspecification.cpp \
|
||||
maemoremotemounter.cpp \
|
||||
@@ -98,7 +93,8 @@ SOURCES += \
|
||||
maddedevicetester.cpp \
|
||||
maemorunconfiguration.cpp \
|
||||
maddedevice.cpp \
|
||||
rpmmanager.cpp
|
||||
rpmmanager.cpp \
|
||||
maemoapplicationrunnerhelperactions.cpp
|
||||
|
||||
FORMS += \
|
||||
maemopackagecreationwidget.ui \
|
||||
|
@@ -31,8 +31,6 @@ QtcPlugin {
|
||||
"maddeuploadandinstallpackagesteps.cpp",
|
||||
"maddeuploadandinstallpackagesteps.h",
|
||||
"maemoconstants.h",
|
||||
"maemodebugsupport.cpp",
|
||||
"maemodebugsupport.h",
|
||||
"maemodeploybymountsteps.cpp",
|
||||
"maemodeploybymountsteps.h",
|
||||
"maemodeployconfigurationwidget.cpp",
|
||||
@@ -108,14 +106,10 @@ QtcPlugin {
|
||||
"maemorunconfiguration.h",
|
||||
"maemorunconfigurationwidget.cpp",
|
||||
"maemorunconfigurationwidget.h",
|
||||
"maemoruncontrol.cpp",
|
||||
"maemoruncontrol.h",
|
||||
"maemorunfactories.cpp",
|
||||
"maemorunfactories.h",
|
||||
"maemosettingspages.cpp",
|
||||
"maemosettingspages.h",
|
||||
"maemosshrunner.cpp",
|
||||
"maemosshrunner.h",
|
||||
"qt-maemo.qrc",
|
||||
"qt4maemodeployconfiguration.cpp",
|
||||
"qt4maemodeployconfiguration.h",
|
||||
@@ -124,6 +118,8 @@ QtcPlugin {
|
||||
"debianmanager.h",
|
||||
"debianmanager.cpp",
|
||||
"rpmmanager.h",
|
||||
"rpmmanager.cpp"
|
||||
"rpmmanager.cpp",
|
||||
"maemoapplicationrunnerhelperactions.h",
|
||||
"maemoapplicationrunnerhelperactions.cpp"
|
||||
]
|
||||
}
|
||||
|
148
src/plugins/madde/maemoapplicationrunnerhelperactions.cpp
Normal file
148
src/plugins/madde/maemoapplicationrunnerhelperactions.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
#include "maemoapplicationrunnerhelperactions.h"
|
||||
|
||||
#include "maemomountspecification.h"
|
||||
#include "maemoremotemounter.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Madde {
|
||||
namespace Internal {
|
||||
|
||||
MaemoPreRunAction::MaemoPreRunAction(const IDevice::ConstPtr &device, const FileName &maddeRoot,
|
||||
const QList<MaemoMountSpecification> &mountSpecs, QObject *parent)
|
||||
: DeviceApplicationHelperAction(parent), m_mounter(new MaemoRemoteMounter(this))
|
||||
{
|
||||
m_mounter->setParameters(device, maddeRoot);
|
||||
foreach (const MaemoMountSpecification &m, mountSpecs)
|
||||
m_mounter->addMountSpecification(m, false);
|
||||
}
|
||||
|
||||
void MaemoPreRunAction::handleMounted()
|
||||
{
|
||||
QTC_ASSERT(m_isRunning, return);
|
||||
|
||||
setFinished(true);
|
||||
}
|
||||
|
||||
void MaemoPreRunAction::handleError(const QString &message)
|
||||
{
|
||||
if (!m_isRunning)
|
||||
return;
|
||||
|
||||
emit reportError(message);
|
||||
setFinished(false);
|
||||
}
|
||||
|
||||
void MaemoPreRunAction::start()
|
||||
{
|
||||
QTC_ASSERT(!m_isRunning, return);
|
||||
|
||||
connect(m_mounter, SIGNAL(debugOutput(QString)), SIGNAL(reportProgress(QString)));
|
||||
connect(m_mounter, SIGNAL(reportProgress(QString)), SIGNAL(reportProgress(QString)));
|
||||
connect(m_mounter, SIGNAL(mounted()), SLOT(handleMounted()));
|
||||
connect(m_mounter, SIGNAL(error(QString)), SLOT(handleError(QString)));
|
||||
m_isRunning = true;
|
||||
m_mounter->mount();
|
||||
}
|
||||
|
||||
void MaemoPreRunAction::stop()
|
||||
{
|
||||
QTC_ASSERT(m_isRunning, return);
|
||||
|
||||
m_mounter->stop();
|
||||
setFinished(false);
|
||||
}
|
||||
|
||||
void MaemoPreRunAction::setFinished(bool success)
|
||||
{
|
||||
QTC_ASSERT(m_isRunning, return);
|
||||
|
||||
m_mounter->disconnect(this);
|
||||
m_isRunning = false;
|
||||
emit finished(success);
|
||||
}
|
||||
|
||||
MaemoPostRunAction::MaemoPostRunAction(MaemoRemoteMounter *mounter, QObject *parent)
|
||||
: DeviceApplicationHelperAction(parent), m_mounter(mounter)
|
||||
{
|
||||
}
|
||||
|
||||
void MaemoPostRunAction::handleUnmounted()
|
||||
{
|
||||
QTC_ASSERT(m_isRunning, return);
|
||||
|
||||
setFinished(true);
|
||||
}
|
||||
|
||||
void MaemoPostRunAction::handleError(const QString &message)
|
||||
{
|
||||
if (!m_isRunning)
|
||||
return;
|
||||
|
||||
emit reportError(message);
|
||||
setFinished(false);
|
||||
}
|
||||
|
||||
void MaemoPostRunAction::start()
|
||||
{
|
||||
QTC_ASSERT(!m_isRunning, return);
|
||||
|
||||
connect(m_mounter, SIGNAL(debugOutput(QString)), SIGNAL(reportProgress(QString)));
|
||||
connect(m_mounter, SIGNAL(reportProgress(QString)), SIGNAL(reportProgress(QString)));
|
||||
connect(m_mounter, SIGNAL(unmounted()), SLOT(handleUnmounted()));
|
||||
connect(m_mounter, SIGNAL(error(QString)), SLOT(handleError(QString)));
|
||||
m_isRunning = true;
|
||||
m_mounter->unmount();
|
||||
}
|
||||
|
||||
void MaemoPostRunAction::stop()
|
||||
{
|
||||
QTC_ASSERT(m_isRunning, return);
|
||||
|
||||
m_mounter->stop();
|
||||
setFinished(false);
|
||||
}
|
||||
|
||||
void MaemoPostRunAction::setFinished(bool success)
|
||||
{
|
||||
QTC_ASSERT(m_isRunning, return);
|
||||
|
||||
m_mounter->disconnect(this);
|
||||
m_isRunning = false;
|
||||
emit finished(success);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Madde
|
@@ -6,6 +6,7 @@
|
||||
**
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
@@ -26,54 +27,65 @@
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
#ifndef MAEMOAPPLICATIONRUNNERHELPERACTIONS_H
|
||||
#define MAEMOAPPLICATIONRUNNERHELPERACTIONS_H
|
||||
|
||||
#ifndef MAEMOSSHRUNNER_H
|
||||
#define MAEMOSSHRUNNER_H
|
||||
#include <projectexplorer/devicesupport/deviceapplicationrunner.h>
|
||||
|
||||
#include "maemomountspecification.h"
|
||||
#include <QList>
|
||||
|
||||
#include <remotelinux/remotelinuxapplicationrunner.h>
|
||||
namespace Utils { class FileName; }
|
||||
|
||||
namespace Madde {
|
||||
namespace Internal {
|
||||
class MaemoMountSpecification;
|
||||
class MaemoRemoteMounter;
|
||||
class MaemoRunConfiguration;
|
||||
|
||||
class MaemoSshRunner : public RemoteLinux::AbstractRemoteLinuxApplicationRunner
|
||||
class MaemoPreRunAction : public ProjectExplorer::DeviceApplicationHelperAction
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MaemoSshRunner(QObject *parent, MaemoRunConfiguration *runConfig);
|
||||
MaemoPreRunAction(const ProjectExplorer::IDevice::ConstPtr &device,
|
||||
const Utils::FileName &maddeRoot, const QList<MaemoMountSpecification> &mountSpecs,
|
||||
QObject *parent = 0);
|
||||
|
||||
signals:
|
||||
void mountDebugOutput(const QString &output);
|
||||
MaemoRemoteMounter *mounter() const { return m_mounter; }
|
||||
|
||||
private slots:
|
||||
void handleMounted();
|
||||
void handleUnmounted();
|
||||
void handleMounterError(const QString &errorMsg);
|
||||
void handleError(const QString &message);
|
||||
|
||||
private:
|
||||
enum MountState { InactiveMountState, InitialUnmounting, Mounting, Mounted, PostRunUnmounting };
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
bool canRun(QString &whyNot) const;
|
||||
void doDeviceSetup();
|
||||
void doAdditionalInitialCleanup();
|
||||
void doAdditionalInitializations();
|
||||
void doPostRunCleanup();
|
||||
void doAdditionalConnectionErrorHandling();
|
||||
|
||||
void mount();
|
||||
void unmount();
|
||||
void setFinished(bool success);
|
||||
|
||||
MaemoRemoteMounter * const m_mounter;
|
||||
QList<MaemoMountSpecification> m_mountSpecs;
|
||||
MountState m_mountState;
|
||||
int m_qtId;
|
||||
bool m_isRunning;
|
||||
};
|
||||
|
||||
class MaemoPostRunAction : public ProjectExplorer::DeviceApplicationHelperAction
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MaemoPostRunAction(MaemoRemoteMounter *mounter, QObject *parent = 0);
|
||||
|
||||
private slots:
|
||||
void handleUnmounted();
|
||||
void handleError(const QString &message);
|
||||
|
||||
private:
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void setFinished(bool success);
|
||||
|
||||
MaemoRemoteMounter * const m_mounter;
|
||||
bool m_isRunning;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Madde
|
||||
|
||||
#endif // MAEMOSSHRUNNER_H
|
||||
#endif // MAEMOAPPLICATIONRUNNERHELPERACTIONS_H
|
@@ -1,54 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
#include "maemodebugsupport.h"
|
||||
|
||||
#include "maemorunconfiguration.h"
|
||||
#include "maemosshrunner.h"
|
||||
|
||||
#include <remotelinux/linuxdeviceconfiguration.h>
|
||||
|
||||
using namespace RemoteLinux;
|
||||
|
||||
namespace Madde {
|
||||
namespace Internal {
|
||||
|
||||
MaemoDebugSupport::MaemoDebugSupport(MaemoRunConfiguration *runConfig, Debugger::DebuggerEngine *engine)
|
||||
: AbstractRemoteLinuxDebugSupport(runConfig, engine),
|
||||
m_runner(new MaemoSshRunner(this, runConfig))
|
||||
{
|
||||
}
|
||||
|
||||
MaemoDebugSupport::~MaemoDebugSupport()
|
||||
{
|
||||
}
|
||||
|
||||
AbstractRemoteLinuxApplicationRunner *MaemoDebugSupport::runner() const { return m_runner; }
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Madde
|
@@ -1,56 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MAEMODEBUGSUPPORT_H
|
||||
#define MAEMODEBUGSUPPORT_H
|
||||
|
||||
#include <remotelinux/remotelinuxdebugsupport.h>
|
||||
|
||||
namespace Madde {
|
||||
namespace Internal {
|
||||
class MaemoRunConfiguration;
|
||||
class MaemoSshRunner;
|
||||
|
||||
class MaemoDebugSupport : public RemoteLinux::AbstractRemoteLinuxDebugSupport
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MaemoDebugSupport(MaemoRunConfiguration *runConfig, Debugger::DebuggerEngine *engine);
|
||||
~MaemoDebugSupport();
|
||||
|
||||
private:
|
||||
RemoteLinux::AbstractRemoteLinuxApplicationRunner *runner() const;
|
||||
|
||||
MaemoSshRunner * const m_runner;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Madde
|
||||
|
||||
#endif // MAEMODEBUGSUPPORT_H
|
@@ -59,7 +59,7 @@ public:
|
||||
~MaemoRemoteMounter();
|
||||
|
||||
void setParameters(const ProjectExplorer::IDevice::ConstPtr &devConf,
|
||||
const Utils::FileName &fileName);
|
||||
const Utils::FileName &maddeRoot);
|
||||
void addMountSpecification(const MaemoMountSpecification &mountSpec,
|
||||
bool mountAsRoot);
|
||||
bool hasValidMountSpecifications() const;
|
||||
|
@@ -135,32 +135,6 @@ Utils::PortList MaemoRunConfiguration::freePorts() const
|
||||
return MaemoGlobal::freePorts(target()->profile());
|
||||
}
|
||||
|
||||
QString MaemoRunConfiguration::localDirToMountForRemoteGdb() const
|
||||
{
|
||||
const QString projectDir
|
||||
= QDir::fromNativeSeparators(QDir::cleanPath(activeBuildConfiguration()
|
||||
->target()->project()->projectDirectory()));
|
||||
const QString execDir
|
||||
= QDir::fromNativeSeparators(QFileInfo(localExecutableFilePath()).path());
|
||||
const int length = qMin(projectDir.length(), execDir.length());
|
||||
int lastSeparatorPos = 0;
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (projectDir.at(i) != execDir.at(i))
|
||||
return projectDir.left(lastSeparatorPos);
|
||||
if (projectDir.at(i) == QLatin1Char('/'))
|
||||
lastSeparatorPos = i;
|
||||
}
|
||||
return projectDir.length() == execDir.length()
|
||||
? projectDir : projectDir.left(lastSeparatorPos);
|
||||
}
|
||||
|
||||
QString MaemoRunConfiguration::remoteProjectSourcesMountPoint() const
|
||||
{
|
||||
return MaemoGlobal::homeDirOnDevice(DeviceProfileInformation::device(target()->profile())->sshParameters().userName)
|
||||
+ QLatin1String("/gdbSourcesDir_")
|
||||
+ QFileInfo(localExecutableFilePath()).fileName();
|
||||
}
|
||||
|
||||
bool MaemoRunConfiguration::hasEnoughFreePorts(RunMode mode) const
|
||||
{
|
||||
const int freePortCount = freePorts().count();
|
||||
|
@@ -53,8 +53,6 @@ public:
|
||||
|
||||
Internal::MaemoRemoteMountsModel *remoteMounts() const { return m_remoteMounts; }
|
||||
bool hasEnoughFreePorts(ProjectExplorer::RunMode mode) const;
|
||||
QString localDirToMountForRemoteGdb() const;
|
||||
QString remoteProjectSourcesMountPoint() const;
|
||||
|
||||
signals:
|
||||
void remoteMountsChanged();
|
||||
|
@@ -1,66 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "maemoruncontrol.h"
|
||||
|
||||
#include "maemoglobal.h"
|
||||
#include "maemorunconfiguration.h"
|
||||
#include "maemosshrunner.h"
|
||||
|
||||
namespace Madde {
|
||||
namespace Internal {
|
||||
|
||||
using namespace RemoteLinux;
|
||||
using ProjectExplorer::RunConfiguration;
|
||||
|
||||
MaemoRunControl::MaemoRunControl(RunConfiguration *rc)
|
||||
: AbstractRemoteLinuxRunControl(rc)
|
||||
, m_runner(new MaemoSshRunner(this, qobject_cast<MaemoRunConfiguration *>(rc)))
|
||||
{
|
||||
}
|
||||
|
||||
MaemoRunControl::~MaemoRunControl()
|
||||
{
|
||||
}
|
||||
|
||||
void MaemoRunControl::start()
|
||||
{
|
||||
AbstractRemoteLinuxRunControl::start();
|
||||
connect(m_runner, SIGNAL(mountDebugOutput(QString)), SLOT(handleMountDebugOutput(QString)));
|
||||
}
|
||||
|
||||
void MaemoRunControl::handleMountDebugOutput(const QString &output)
|
||||
{
|
||||
appendMessage(output, Utils::StdErrFormatSameLine);
|
||||
}
|
||||
|
||||
AbstractRemoteLinuxApplicationRunner *MaemoRunControl::runner() const { return m_runner; }
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Madde
|
@@ -1,64 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MAEMORUNCONTROL_H
|
||||
#define MAEMORUNCONTROL_H
|
||||
|
||||
#include <remotelinux/remotelinuxruncontrol.h>
|
||||
|
||||
namespace RemoteLinux {
|
||||
class RemoteLinuxRunConfiguration;
|
||||
}
|
||||
|
||||
namespace Madde {
|
||||
namespace Internal {
|
||||
class MaemoSshRunner;
|
||||
|
||||
class MaemoRunControl : public RemoteLinux::AbstractRemoteLinuxRunControl
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MaemoRunControl(ProjectExplorer::RunConfiguration *runConfig);
|
||||
virtual ~MaemoRunControl();
|
||||
|
||||
void start();
|
||||
|
||||
private slots:
|
||||
void handleMountDebugOutput(const QString &output);
|
||||
|
||||
private:
|
||||
virtual RemoteLinux::AbstractRemoteLinuxApplicationRunner *runner() const;
|
||||
|
||||
MaemoSshRunner * const m_runner;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Madde
|
||||
|
||||
#endif // MAEMORUNCONTROL_H
|
@@ -28,11 +28,11 @@
|
||||
**************************************************************************/
|
||||
#include "maemorunfactories.h"
|
||||
|
||||
#include "maemoapplicationrunnerhelperactions.h"
|
||||
#include "maemoconstants.h"
|
||||
#include "maemodebugsupport.h"
|
||||
#include "maemoglobal.h"
|
||||
#include "maemoremotemountsmodel.h"
|
||||
#include "maemorunconfiguration.h"
|
||||
#include "maemoruncontrol.h"
|
||||
|
||||
#include <debugger/debuggerconstants.h>
|
||||
#include <debugger/debuggerstartparameters.h>
|
||||
@@ -44,6 +44,8 @@
|
||||
#include <qt4projectmanager/qt4nodes.h>
|
||||
#include <qt4projectmanager/qt4project.h>
|
||||
#include <qtsupport/customexecutablerunconfiguration.h>
|
||||
#include <remotelinux/remotelinuxdebugsupport.h>
|
||||
#include <remotelinux/remotelinuxruncontrol.h>
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
@@ -169,7 +171,6 @@ QList<RunConfiguration *> MaemoRunConfigurationFactory::runConfigurationsForNode
|
||||
return result;
|
||||
}
|
||||
|
||||
// #pragma mark -- MaemoRunControlFactory
|
||||
|
||||
MaemoRunControlFactory::MaemoRunControlFactory(QObject *parent)
|
||||
: IRunControlFactory(parent)
|
||||
@@ -197,14 +198,21 @@ RunControl* MaemoRunControlFactory::create(RunConfiguration *runConfig, RunMode
|
||||
Q_ASSERT(rc);
|
||||
|
||||
if (mode == NormalRunMode)
|
||||
return new MaemoRunControl(rc);
|
||||
return new RemoteLinuxRunControl(rc);
|
||||
|
||||
const DebuggerStartParameters params
|
||||
= AbstractRemoteLinuxDebugSupport::startParameters(rc);
|
||||
const DebuggerStartParameters params = LinuxDeviceDebugSupport::startParameters(rc);
|
||||
DebuggerRunControl * const runControl = DebuggerPlugin::createDebugger(params, rc);
|
||||
if (!runControl)
|
||||
return 0;
|
||||
MaemoDebugSupport *debugSupport = new MaemoDebugSupport(rc, runControl->engine());
|
||||
LinuxDeviceDebugSupport * const debugSupport
|
||||
= new LinuxDeviceDebugSupport(rc, runControl->engine());
|
||||
const Profile * const profile = runConfig->target()->profile();
|
||||
MaemoPreRunAction * const preRunAction = new MaemoPreRunAction(
|
||||
DeviceProfileInformation::device(profile), MaemoGlobal::maddeRoot(profile),
|
||||
rc->remoteMounts()->mountSpecs(), rc);
|
||||
MaemoPostRunAction * const postRunAction = new MaemoPostRunAction(preRunAction->mounter(), rc);
|
||||
debugSupport->setApplicationRunnerPreRunAction(preRunAction);
|
||||
debugSupport->setApplicationRunnerPostRunAction(postRunAction);
|
||||
connect(runControl, SIGNAL(finished()), debugSupport, SLOT(handleDebuggingFinished()));
|
||||
return runControl;
|
||||
}
|
||||
|
@@ -1,215 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
#include "maemosshrunner.h"
|
||||
|
||||
#include "maemoglobal.h"
|
||||
#include "maemoqemumanager.h"
|
||||
#include "maemoremotemounter.h"
|
||||
#include "maemoremotemountsmodel.h"
|
||||
#include "maemorunconfiguration.h"
|
||||
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <qtsupport/qtprofileinformation.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <ssh/sshconnection.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace QSsh;
|
||||
using namespace RemoteLinux;
|
||||
|
||||
namespace Madde {
|
||||
namespace Internal {
|
||||
|
||||
MaemoSshRunner::MaemoSshRunner(QObject *parent, MaemoRunConfiguration *runConfig)
|
||||
: AbstractRemoteLinuxApplicationRunner(runConfig, parent),
|
||||
m_mounter(new MaemoRemoteMounter(this)),
|
||||
m_mountSpecs(runConfig->remoteMounts()->mountSpecs()),
|
||||
m_mountState(InactiveMountState)
|
||||
{
|
||||
const BuildConfiguration * const bc = runConfig->target()->activeBuildConfiguration();
|
||||
Profile *profile = bc ? bc->target()->profile() : 0;
|
||||
m_qtId = QtSupport::QtProfileInformation::qtVersionId(profile);
|
||||
m_mounter->setParameters(devConfig(), MaemoGlobal::maddeRoot(profile));
|
||||
connect(m_mounter, SIGNAL(mounted()), this, SLOT(handleMounted()));
|
||||
connect(m_mounter, SIGNAL(unmounted()), this, SLOT(handleUnmounted()));
|
||||
connect(m_mounter, SIGNAL(error(QString)), this,
|
||||
SLOT(handleMounterError(QString)));
|
||||
connect(m_mounter, SIGNAL(reportProgress(QString)), this,
|
||||
SIGNAL(reportProgress(QString)));
|
||||
connect(m_mounter, SIGNAL(debugOutput(QString)), this,
|
||||
SIGNAL(mountDebugOutput(QString)));
|
||||
}
|
||||
|
||||
bool MaemoSshRunner::canRun(QString &whyNot) const
|
||||
{
|
||||
if (!AbstractRemoteLinuxApplicationRunner::canRun(whyNot))
|
||||
return false;
|
||||
|
||||
if (devConfig()->machineType() == IDevice::Emulator
|
||||
&& !MaemoQemuManager::instance().qemuIsRunning()) {
|
||||
MaemoQemuRuntime rt;
|
||||
if (MaemoQemuManager::instance().runtimeForQtVersion(m_qtId, &rt)) {
|
||||
MaemoQemuManager::instance().startRuntime();
|
||||
whyNot = tr("Qemu was not running. It has now been started up for you, but it will "
|
||||
"take a bit of time until it is ready. Please try again then.");
|
||||
} else {
|
||||
whyNot = tr("You want to run on Qemu, but it is not enabled for this Qt version.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MaemoSshRunner::doDeviceSetup()
|
||||
{
|
||||
QTC_ASSERT(m_mountState == InactiveMountState, return);
|
||||
|
||||
handleDeviceSetupDone(true);
|
||||
}
|
||||
|
||||
void MaemoSshRunner::doAdditionalInitialCleanup()
|
||||
{
|
||||
QTC_ASSERT(m_mountState == InactiveMountState, return);
|
||||
|
||||
m_mounter->resetMountSpecifications();
|
||||
for (int i = 0; i < m_mountSpecs.count(); ++i)
|
||||
m_mounter->addMountSpecification(m_mountSpecs.at(i), false);
|
||||
m_mountState = InitialUnmounting;
|
||||
unmount();
|
||||
}
|
||||
|
||||
void MaemoSshRunner::doAdditionalInitializations()
|
||||
{
|
||||
mount();
|
||||
}
|
||||
|
||||
void MaemoSshRunner::doPostRunCleanup()
|
||||
{
|
||||
QTC_ASSERT(m_mountState == Mounted, return);
|
||||
|
||||
m_mountState = PostRunUnmounting;
|
||||
unmount();
|
||||
}
|
||||
|
||||
void MaemoSshRunner::handleUnmounted()
|
||||
{
|
||||
QTC_ASSERT(m_mountState == InitialUnmounting || m_mountState == PostRunUnmounting, return);
|
||||
|
||||
switch (m_mountState) {
|
||||
case InitialUnmounting:
|
||||
m_mountState = InactiveMountState;
|
||||
handleInitialCleanupDone(true);
|
||||
break;
|
||||
case PostRunUnmounting:
|
||||
m_mountState = InactiveMountState;
|
||||
handlePostRunCleanupDone();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_mountState = InactiveMountState;
|
||||
}
|
||||
|
||||
void MaemoSshRunner::doAdditionalConnectionErrorHandling()
|
||||
{
|
||||
m_mountState = InactiveMountState;
|
||||
}
|
||||
|
||||
void MaemoSshRunner::handleMounted()
|
||||
{
|
||||
QTC_ASSERT(m_mountState == Mounting, return);
|
||||
|
||||
if (m_mountState == Mounting) {
|
||||
m_mountState = Mounted;
|
||||
handleInitializationsDone(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MaemoSshRunner::handleMounterError(const QString &errorMsg)
|
||||
{
|
||||
QTC_ASSERT(m_mountState == InitialUnmounting || m_mountState == Mounting
|
||||
|| m_mountState == PostRunUnmounting, return);
|
||||
|
||||
const MountState oldMountState = m_mountState;
|
||||
m_mountState = InactiveMountState;
|
||||
emit error(errorMsg);
|
||||
switch (oldMountState) {
|
||||
case InitialUnmounting:
|
||||
handleInitialCleanupDone(false);
|
||||
break;
|
||||
case Mounting:
|
||||
handleInitializationsDone(false);
|
||||
break;
|
||||
case PostRunUnmounting:
|
||||
handlePostRunCleanupDone();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MaemoSshRunner::mount()
|
||||
{
|
||||
m_mountState = Mounting;
|
||||
if (m_mounter->hasValidMountSpecifications()) {
|
||||
emit reportProgress(tr("Mounting host directories..."));
|
||||
m_mounter->mount();
|
||||
} else {
|
||||
handleMounted();
|
||||
}
|
||||
}
|
||||
|
||||
void MaemoSshRunner::unmount()
|
||||
{
|
||||
QTC_ASSERT(m_mountState == InitialUnmounting || m_mountState == PostRunUnmounting, return);
|
||||
|
||||
if (m_mounter->hasValidMountSpecifications()) {
|
||||
QString message;
|
||||
switch (m_mountState) {
|
||||
case InitialUnmounting:
|
||||
message = tr("Potentially unmounting left-over host directory mounts...");
|
||||
break;
|
||||
case PostRunUnmounting:
|
||||
message = tr("Unmounting host directories...");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
emit reportProgress(message);
|
||||
m_mounter->unmount();
|
||||
} else {
|
||||
handleUnmounted();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Madde
|
||||
|
@@ -0,0 +1,339 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
#include "deviceapplicationrunner.h"
|
||||
|
||||
#include <ssh/sshconnection.h>
|
||||
#include <ssh/sshconnectionmanager.h>
|
||||
#include <ssh/sshremoteprocess.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
using namespace QSsh;
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
namespace {
|
||||
enum State { Inactive, Connecting, PreRun, Run, PostRun };
|
||||
} // anonymous namespace
|
||||
|
||||
class DeviceApplicationRunner::DeviceApplicationRunnerPrivate
|
||||
{
|
||||
public:
|
||||
SshConnection *connection;
|
||||
DeviceApplicationHelperAction *preRunAction;
|
||||
DeviceApplicationHelperAction *postRunAction;
|
||||
IDevice::ConstPtr device;
|
||||
SshRemoteProcess::Ptr remoteApp;
|
||||
QTimer stopTimer;
|
||||
QByteArray commandLine;
|
||||
State state;
|
||||
bool stopRequested;
|
||||
bool success;
|
||||
};
|
||||
|
||||
|
||||
DeviceApplicationHelperAction::DeviceApplicationHelperAction(QObject *parent) : QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceApplicationHelperAction::~DeviceApplicationHelperAction()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DeviceApplicationRunner::DeviceApplicationRunner(QObject *parent) :
|
||||
QObject(parent), d(new DeviceApplicationRunnerPrivate)
|
||||
{
|
||||
d->preRunAction = 0;
|
||||
d->postRunAction = 0;
|
||||
d->connection = 0;
|
||||
d->state = Inactive;
|
||||
|
||||
d->stopTimer.setSingleShot(true);
|
||||
connect(&d->stopTimer, SIGNAL(timeout()), SLOT(handleStopTimeout()));
|
||||
}
|
||||
|
||||
DeviceApplicationRunner::~DeviceApplicationRunner()
|
||||
{
|
||||
setFinished();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::start(const IDevice::ConstPtr &device,
|
||||
const QByteArray &commandLine)
|
||||
{
|
||||
QTC_ASSERT(d->state == Inactive, return);
|
||||
|
||||
d->device = device;
|
||||
d->commandLine = commandLine;
|
||||
d->stopRequested = false;
|
||||
d->success = true;
|
||||
|
||||
connectToServer();
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::stop(const QByteArray &stopCommand)
|
||||
{
|
||||
QTC_ASSERT(d->state != Inactive, return);
|
||||
|
||||
if (d->stopRequested)
|
||||
return;
|
||||
d->stopRequested = true;
|
||||
d->success = false;
|
||||
emit reportProgress(tr("User requested stop. Shutting down..."));
|
||||
switch (d->state) {
|
||||
case Connecting:
|
||||
setFinished();
|
||||
break;
|
||||
case PreRun:
|
||||
d->preRunAction->stop();
|
||||
break;
|
||||
case Run:
|
||||
d->stopTimer.start(10000);
|
||||
d->connection->createRemoteProcess(stopCommand)->start();
|
||||
break;
|
||||
case PostRun:
|
||||
d->postRunAction->stop();
|
||||
break;
|
||||
case Inactive:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::setPreRunAction(DeviceApplicationHelperAction *action)
|
||||
{
|
||||
addAction(d->preRunAction, action);
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::setPostRunAction(DeviceApplicationHelperAction *action)
|
||||
{
|
||||
addAction(d->postRunAction, action);
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::connectToServer()
|
||||
{
|
||||
QTC_CHECK(!d->connection);
|
||||
|
||||
d->state = Connecting;
|
||||
|
||||
if (!d->device) {
|
||||
emit reportError(tr("Cannot run: No device."));
|
||||
setFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
d->connection = SshConnectionManager::instance().acquireConnection(d->device->sshParameters());
|
||||
connect(d->connection, SIGNAL(error(QSsh::SshError)), SLOT(handleConnectionFailure()));
|
||||
if (d->connection->state() == SshConnection::Connected) {
|
||||
handleConnected();
|
||||
} else {
|
||||
emit reportProgress(tr("Connecting to device..."));
|
||||
connect(d->connection, SIGNAL(connected()), SLOT(handleConnected()));
|
||||
if (d->connection->state() == QSsh::SshConnection::Unconnected)
|
||||
d->connection->connectToHost();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::executePreRunAction()
|
||||
{
|
||||
QTC_ASSERT(d->state == Connecting, return);
|
||||
|
||||
d->state = PreRun;
|
||||
if (d->preRunAction)
|
||||
d->preRunAction->start();
|
||||
else
|
||||
runApplication();
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::executePostRunAction()
|
||||
{
|
||||
QTC_ASSERT(d->state == PreRun || d->state == Run, return);
|
||||
|
||||
d->state = PostRun;
|
||||
if (d->postRunAction)
|
||||
d->postRunAction->start();
|
||||
else
|
||||
setFinished();
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::setFinished()
|
||||
{
|
||||
if (d->state == Inactive)
|
||||
return;
|
||||
|
||||
if (d->remoteApp) {
|
||||
d->remoteApp->disconnect(this);
|
||||
d->remoteApp->close();
|
||||
d->remoteApp.clear();
|
||||
}
|
||||
if (d->connection) {
|
||||
d->connection->disconnect(this);
|
||||
SshConnectionManager::instance().releaseConnection(d->connection);
|
||||
d->connection = 0;
|
||||
}
|
||||
|
||||
d->state = Inactive;
|
||||
emit finished(d->success);
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::handleConnected()
|
||||
{
|
||||
QTC_ASSERT(d->state == Connecting, return);
|
||||
|
||||
if (d->stopRequested) {
|
||||
setFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
executePreRunAction();
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::handleConnectionFailure()
|
||||
{
|
||||
QTC_ASSERT(d->state != Inactive, return);
|
||||
|
||||
emit reportError(tr("SSH connection failed: %1").arg(d->connection->errorString()));
|
||||
d->success = false;
|
||||
switch (d->state) {
|
||||
case Inactive:
|
||||
break; // Can't happen.
|
||||
case Connecting:
|
||||
setFinished();
|
||||
break;
|
||||
case PreRun:
|
||||
d->preRunAction->stop();
|
||||
break;
|
||||
case Run:
|
||||
d->stopTimer.stop();
|
||||
d->remoteApp->disconnect(this);
|
||||
executePostRunAction();
|
||||
break;
|
||||
case PostRun:
|
||||
d->postRunAction->stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::handleHelperActionFinished(bool success)
|
||||
{
|
||||
switch (d->state) {
|
||||
case Inactive:
|
||||
break;
|
||||
case PreRun:
|
||||
if (success && d->success) {
|
||||
runApplication();
|
||||
} else if (success && !d->success) {
|
||||
executePostRunAction();
|
||||
} else {
|
||||
d->success = false;
|
||||
setFinished();
|
||||
}
|
||||
break;
|
||||
case PostRun:
|
||||
if (!success)
|
||||
d->success = false;
|
||||
setFinished();
|
||||
break;
|
||||
default:
|
||||
QTC_CHECK(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::addAction(DeviceApplicationHelperAction *&target,
|
||||
DeviceApplicationHelperAction *source)
|
||||
{
|
||||
QTC_ASSERT(d->state == Inactive, return);
|
||||
|
||||
if (target)
|
||||
disconnect(target, 0, this, 0);
|
||||
target = source;
|
||||
if (target) {
|
||||
connect(target, SIGNAL(finished(bool)), SLOT(handleHelperActionFinished(bool)));
|
||||
connect(target, SIGNAL(reportProgress(QString)), SIGNAL(reportProgress(QString)));
|
||||
connect(target, SIGNAL(reportError(QString)), SIGNAL(reportError(QString)));
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::handleStopTimeout()
|
||||
{
|
||||
QTC_ASSERT(d->stopRequested && d->state == Run, return);
|
||||
|
||||
emit reportError(tr("Application did not finish in time, aborting."));
|
||||
d->success = false;
|
||||
setFinished();
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::handleApplicationFinished(int exitStatus)
|
||||
{
|
||||
QTC_ASSERT(d->state == Run, return);
|
||||
|
||||
d->stopTimer.stop();
|
||||
if (exitStatus == SshRemoteProcess::CrashExit) {
|
||||
emit reportError(tr("Remote application crashed: %1").arg(d->remoteApp->errorString()));
|
||||
d->success = false;
|
||||
} else {
|
||||
const int exitCode = d->remoteApp->exitCode();
|
||||
if (exitCode != 0) {
|
||||
emit reportError(tr("Remote application finished with exit code %1.").arg(exitCode));
|
||||
d->success = false;
|
||||
} else {
|
||||
emit reportProgress(tr("Remote application finished with exit code 0."));
|
||||
}
|
||||
}
|
||||
executePostRunAction();
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::handleRemoteStdout()
|
||||
{
|
||||
QTC_ASSERT(d->state == Run, return);
|
||||
emit remoteStdout(d->remoteApp->readAllStandardOutput());
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::handleRemoteStderr()
|
||||
{
|
||||
QTC_ASSERT(d->state == Run, return);
|
||||
emit remoteStderr(d->remoteApp->readAllStandardError());
|
||||
}
|
||||
|
||||
void DeviceApplicationRunner::runApplication()
|
||||
{
|
||||
QTC_ASSERT(d->state == PreRun, return);
|
||||
|
||||
d->state = Run;
|
||||
d->remoteApp = d->connection->createRemoteProcess(d->commandLine);
|
||||
connect(d->remoteApp.data(), SIGNAL(started()), SIGNAL(remoteProcessStarted()));
|
||||
connect(d->remoteApp.data(), SIGNAL(readyReadStandardOutput()), SLOT(handleRemoteStdout()));
|
||||
connect(d->remoteApp.data(), SIGNAL(readyReadStandardError()), SLOT(handleRemoteStderr()));
|
||||
connect(d->remoteApp.data(), SIGNAL(closed(int)), SLOT(handleApplicationFinished(int)));
|
||||
d->remoteApp->start();
|
||||
}
|
||||
|
||||
} // namespace ProjectExplorer
|
@@ -0,0 +1,104 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
#ifndef ONDEVICEAPPLICATIONRUNNER_H
|
||||
#define ONDEVICEAPPLICATIONRUNNER_H
|
||||
|
||||
#include "idevice.h"
|
||||
|
||||
#include "../projectexplorer_export.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
class PROJECTEXPLORER_EXPORT DeviceApplicationHelperAction : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
~DeviceApplicationHelperAction();
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
signals:
|
||||
void reportProgress(const QString &progressOutput);
|
||||
void reportError(const QString &errorOutput);
|
||||
void finished(bool success);
|
||||
|
||||
protected:
|
||||
DeviceApplicationHelperAction(QObject *parent = 0);
|
||||
};
|
||||
|
||||
class PROJECTEXPLORER_EXPORT DeviceApplicationRunner : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeviceApplicationRunner(QObject *parent = 0);
|
||||
virtual ~DeviceApplicationRunner();
|
||||
|
||||
void start(const IDevice::ConstPtr &device, const QByteArray &commandLine);
|
||||
void stop(const QByteArray &stopCommand);
|
||||
|
||||
// Use these if you need to do something before and after the application is run, respectively.
|
||||
// Typically, the post-run action reverts the effects of the pre-run action.
|
||||
// If you only have a pre-run action, you probably want a deploy step instead.
|
||||
void setPreRunAction(DeviceApplicationHelperAction *action);
|
||||
void setPostRunAction(DeviceApplicationHelperAction *action);
|
||||
|
||||
signals:
|
||||
void remoteStdout(const QByteArray &output);
|
||||
void remoteStderr(const QByteArray &output);
|
||||
void reportProgress(const QString &progressOutput);
|
||||
void reportError(const QString &errorOutput);
|
||||
void remoteProcessStarted();
|
||||
void finished(bool success);
|
||||
|
||||
private slots:
|
||||
void handleConnected();
|
||||
void handleConnectionFailure();
|
||||
void handleHelperActionFinished(bool success);
|
||||
void handleStopTimeout();
|
||||
void handleApplicationFinished(int exitStatus);
|
||||
void handleRemoteStdout();
|
||||
void handleRemoteStderr();
|
||||
|
||||
private:
|
||||
void addAction(DeviceApplicationHelperAction *&target, DeviceApplicationHelperAction *source);
|
||||
void connectToServer();
|
||||
void executePreRunAction();
|
||||
void executePostRunAction();
|
||||
void runApplication();
|
||||
void setFinished();
|
||||
|
||||
class DeviceApplicationRunnerPrivate;
|
||||
DeviceApplicationRunnerPrivate * const d;
|
||||
};
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
|
||||
#endif // ONDEVICEAPPLICATIONRUNNER_H
|
@@ -125,7 +125,8 @@ HEADERS += projectexplorer.h \
|
||||
devicesupport/deviceprocessesdialog.h \
|
||||
devicesupport/devicesettingswidget.h \
|
||||
devicesupport/devicesettingspage.h \
|
||||
devicesupport/deviceusedportsgatherer.h
|
||||
devicesupport/deviceusedportsgatherer.h \
|
||||
devicesupport/deviceapplicationrunner.h
|
||||
|
||||
SOURCES += projectexplorer.cpp \
|
||||
abi.cpp \
|
||||
@@ -227,7 +228,8 @@ SOURCES += projectexplorer.cpp \
|
||||
devicesupport/deviceprocessesdialog.cpp \
|
||||
devicesupport/devicesettingswidget.cpp \
|
||||
devicesupport/devicesettingspage.cpp \
|
||||
devicesupport/deviceusedportsgatherer.cpp
|
||||
devicesupport/deviceusedportsgatherer.cpp \
|
||||
devicesupport/deviceapplicationrunner.cpp
|
||||
|
||||
FORMS += processstep.ui \
|
||||
editorsettingspropertiespage.ui \
|
||||
|
@@ -308,7 +308,9 @@ QtcPlugin {
|
||||
"devicesupport/deviceusedportsgatherer.h",
|
||||
"devicesupport/idevicewidget.h",
|
||||
"devicesupport/idevicefactory.cpp",
|
||||
"devicesupport/idevicefactory.h"
|
||||
"devicesupport/idevicefactory.h",
|
||||
"devicesupport/deviceapplicationrunner.cpp",
|
||||
"devicesupport/deviceapplicationrunner.h"
|
||||
]
|
||||
|
||||
Group {
|
||||
|
@@ -45,6 +45,7 @@
|
||||
#include <qt4projectmanager/qt-s60/s60devicedebugruncontrol.h>
|
||||
#include <qt4projectmanager/qt-s60/s60devicerunconfiguration.h>
|
||||
#include <qmldebug/qmloutputparser.h>
|
||||
#include <remotelinux/remotelinuxrunconfiguration.h>
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QMessageBox>
|
||||
@@ -370,6 +371,7 @@ void QmlProfilerEngine::profilerStateChanged()
|
||||
case QmlProfilerStateManager::Idle : {
|
||||
// When all the profiling is done, delete the profiler runner
|
||||
// (a new one will be created at start)
|
||||
d->m_noDebugOutputTimer.stop();
|
||||
if (d->m_runner) {
|
||||
delete d->m_runner;
|
||||
d->m_runner = 0;
|
||||
|
@@ -27,15 +27,18 @@
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "remotelinuxqmlprofilerrunner.h"
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <projectexplorer/devicesupport/deviceapplicationrunner.h>
|
||||
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
|
||||
#include <projectexplorer/profileinformation.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <remotelinux/remotelinuxapplicationrunner.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <remotelinux/remotelinuxrunconfiguration.h>
|
||||
#include <remotelinux/remotelinuxutils.h>
|
||||
#include <utils/portlist.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace ExtensionSystem;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace QmlProfiler::Internal;
|
||||
using namespace RemoteLinux;
|
||||
@@ -43,55 +46,43 @@ using namespace RemoteLinux;
|
||||
RemoteLinuxQmlProfilerRunner::RemoteLinuxQmlProfilerRunner(
|
||||
RemoteLinuxRunConfiguration *runConfiguration, QObject *parent)
|
||||
: AbstractQmlProfilerRunner(parent)
|
||||
, m_portsGatherer(new DeviceUsedPortsGatherer(this))
|
||||
, m_runner(new DeviceApplicationRunner(this))
|
||||
, m_device(DeviceProfileInformation::device(runConfiguration->target()->profile()))
|
||||
, m_remoteExecutable(runConfiguration->remoteExecutableFilePath())
|
||||
, m_arguments(runConfiguration->arguments())
|
||||
, m_commandPrefix(runConfiguration->commandPrefix())
|
||||
, m_port(0)
|
||||
, m_runControl(0)
|
||||
{
|
||||
// find run control factory
|
||||
IRunControlFactory *runControlFactory = 0;
|
||||
QList<IRunControlFactory*> runControlFactories
|
||||
= PluginManager::getObjects<IRunControlFactory>();
|
||||
|
||||
foreach (IRunControlFactory *factory, runControlFactories) {
|
||||
if (factory->canRun(runConfiguration, NormalRunMode)) {
|
||||
runControlFactory = factory;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QTC_ASSERT(runControlFactory, return);
|
||||
|
||||
// create run control
|
||||
RunControl *runControl = runControlFactory->create(runConfiguration, NormalRunMode);
|
||||
|
||||
m_runControl = qobject_cast<AbstractRemoteLinuxRunControl*>(runControl);
|
||||
QTC_ASSERT(m_runControl, return);
|
||||
|
||||
connect(runner(), SIGNAL(readyForExecution()), this, SLOT(getPorts()));
|
||||
connect(runner(), SIGNAL(error(QString)), this, SLOT(handleError(QString)));
|
||||
connect(runner(), SIGNAL(remoteErrorOutput(QByteArray)), this, SLOT(handleStdErr(QByteArray)));
|
||||
connect(runner(), SIGNAL(remoteOutput(QByteArray)), this, SLOT(handleStdOut(QByteArray)));
|
||||
|
||||
connect(runner(), SIGNAL(remoteProcessStarted()), this, SLOT(handleRemoteProcessStarted()));
|
||||
connect(runner(), SIGNAL(remoteProcessFinished(qint64)),
|
||||
this, SLOT(handleRemoteProcessFinished(qint64)));
|
||||
connect(runner(), SIGNAL(reportProgress(QString)), this, SLOT(handleProgressReport(QString)));
|
||||
connect(m_runner, SIGNAL(reportError(QString)), this, SLOT(handleError(QString)));
|
||||
connect(m_runner, SIGNAL(remoteStderr(QByteArray)), this, SLOT(handleStdErr(QByteArray)));
|
||||
connect(m_runner, SIGNAL(remoteStdout(QByteArray)), this, SLOT(handleStdOut(QByteArray)));
|
||||
connect(m_runner, SIGNAL(finished(bool)), SLOT(handleRemoteProcessFinished(bool)));
|
||||
connect(m_runner, SIGNAL(reportProgress(QString)), this, SLOT(handleProgressReport(QString)));
|
||||
connect(m_portsGatherer, SIGNAL(error(QString)), SLOT(handlePortsGathererError(QString)));
|
||||
connect(m_portsGatherer, SIGNAL(portListReady()), SLOT(handlePortListReady()));
|
||||
}
|
||||
|
||||
RemoteLinuxQmlProfilerRunner::~RemoteLinuxQmlProfilerRunner()
|
||||
{
|
||||
delete m_runControl;
|
||||
stop();
|
||||
}
|
||||
|
||||
void RemoteLinuxQmlProfilerRunner::start()
|
||||
{
|
||||
QTC_ASSERT(runner(), return);
|
||||
runner()->start();
|
||||
QTC_ASSERT(m_port == 0, return);
|
||||
|
||||
m_portsGatherer->start(m_device);
|
||||
emit started();
|
||||
}
|
||||
|
||||
void RemoteLinuxQmlProfilerRunner::stop()
|
||||
{
|
||||
QTC_ASSERT(runner(), return);
|
||||
runner()->stop();
|
||||
if (m_port == 0)
|
||||
m_portsGatherer->stop();
|
||||
else
|
||||
m_runner->stop(RemoteLinuxUtils::killApplicationCommandLine(m_remoteExecutable).toUtf8());
|
||||
m_port = 0;
|
||||
}
|
||||
|
||||
quint16 RemoteLinuxQmlProfilerRunner::debugPort() const
|
||||
@@ -99,26 +90,37 @@ quint16 RemoteLinuxQmlProfilerRunner::debugPort() const
|
||||
return m_port;
|
||||
}
|
||||
|
||||
void RemoteLinuxQmlProfilerRunner::handlePortsGathererError(const QString &message)
|
||||
{
|
||||
emit appendMessage(tr("Gathering ports failed: %1").arg(message), Utils::ErrorMessageFormat);
|
||||
m_port = 0;
|
||||
emit stopped();
|
||||
}
|
||||
|
||||
void RemoteLinuxQmlProfilerRunner::handlePortListReady()
|
||||
{
|
||||
getPorts();
|
||||
}
|
||||
|
||||
void RemoteLinuxQmlProfilerRunner::getPorts()
|
||||
{
|
||||
QTC_ASSERT(runner(), return);
|
||||
m_port = runner()->freePorts()->getNext();
|
||||
if (m_port == 0) {
|
||||
Utils::PortList portList = m_device->freePorts();
|
||||
m_port = m_portsGatherer->getNextFreePort(&portList);
|
||||
|
||||
if (m_port == -1) {
|
||||
emit appendMessage(tr("Not enough free ports on device for analyzing.\n"),
|
||||
Utils::ErrorMessageFormat);
|
||||
runner()->stop();
|
||||
m_port = 0;
|
||||
emit stopped();
|
||||
} else {
|
||||
emit appendMessage(tr("Starting remote process ...\n"), Utils::NormalMessageFormat);
|
||||
|
||||
QString arguments = runner()->arguments();
|
||||
QString arguments = m_arguments;
|
||||
if (!arguments.isEmpty())
|
||||
arguments.append(QLatin1Char(' '));
|
||||
arguments.append(QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(m_port));
|
||||
|
||||
runner()->startExecution(QString::fromLatin1("%1 %2 %3")
|
||||
.arg(runner()->commandPrefix())
|
||||
.arg(runner()->remoteExecutable())
|
||||
.arg(arguments).toUtf8());
|
||||
const QString commandLine = QString::fromLatin1("%1 %2 %3")
|
||||
.arg(m_commandPrefix, m_remoteExecutable, arguments);
|
||||
m_runner->start(m_device, commandLine.toUtf8());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,18 +139,11 @@ void RemoteLinuxQmlProfilerRunner::handleStdOut(const QByteArray &msg)
|
||||
emit appendMessage(QString::fromUtf8(msg), Utils::StdOutFormat);
|
||||
}
|
||||
|
||||
void RemoteLinuxQmlProfilerRunner::handleRemoteProcessStarted()
|
||||
void RemoteLinuxQmlProfilerRunner::handleRemoteProcessFinished(bool success)
|
||||
{
|
||||
emit started();
|
||||
}
|
||||
|
||||
void RemoteLinuxQmlProfilerRunner::handleRemoteProcessFinished(qint64 exitCode)
|
||||
{
|
||||
if (exitCode != AbstractRemoteLinuxApplicationRunner::InvalidExitCode) {
|
||||
appendMessage(tr("Finished running remote process. Exit code was %1.\n")
|
||||
.arg(exitCode), Utils::NormalMessageFormat);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
appendMessage(tr("Failure running remote process."), Utils::NormalMessageFormat);
|
||||
m_port = 0;
|
||||
emit stopped();
|
||||
}
|
||||
|
||||
@@ -156,11 +151,3 @@ void RemoteLinuxQmlProfilerRunner::handleProgressReport(const QString &progressS
|
||||
{
|
||||
appendMessage(progressString + QLatin1Char('\n'), Utils::NormalMessageFormat);
|
||||
}
|
||||
|
||||
AbstractRemoteLinuxApplicationRunner *RemoteLinuxQmlProfilerRunner::runner() const
|
||||
{
|
||||
if (!m_runControl)
|
||||
return 0;
|
||||
return m_runControl->runner();
|
||||
}
|
||||
|
||||
|
@@ -32,8 +32,16 @@
|
||||
#define REMOTELINUXQMLPROFILERRUNNER_H
|
||||
|
||||
#include "abstractqmlprofilerrunner.h"
|
||||
#include <remotelinux/remotelinuxrunconfiguration.h>
|
||||
#include <remotelinux/remotelinuxruncontrol.h>
|
||||
|
||||
#include <projectexplorer/devicesupport/idevice.h>
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class DeviceApplicationRunner;
|
||||
class DeviceUsedPortsGatherer;
|
||||
}
|
||||
namespace RemoteLinux { class RemoteLinuxRunConfiguration; }
|
||||
|
||||
namespace QmlProfiler {
|
||||
namespace Internal {
|
||||
@@ -54,19 +62,24 @@ public:
|
||||
virtual quint16 debugPort() const;
|
||||
|
||||
private slots:
|
||||
void getPorts();
|
||||
void handleError(const QString &msg);
|
||||
void handleStdErr(const QByteArray &msg);
|
||||
void handleStdOut(const QByteArray &msg);
|
||||
void handleRemoteProcessStarted();
|
||||
void handleRemoteProcessFinished(qint64);
|
||||
void handleRemoteProcessFinished(bool success);
|
||||
void handleProgressReport(const QString &progressString);
|
||||
void handlePortsGathererError(const QString &message);
|
||||
void handlePortListReady();
|
||||
|
||||
private:
|
||||
RemoteLinux::AbstractRemoteLinuxApplicationRunner *runner() const;
|
||||
void getPorts();
|
||||
|
||||
quint16 m_port;
|
||||
RemoteLinux::AbstractRemoteLinuxRunControl *m_runControl;
|
||||
ProjectExplorer::DeviceUsedPortsGatherer * const m_portsGatherer;
|
||||
ProjectExplorer::DeviceApplicationRunner * const m_runner;
|
||||
const ProjectExplorer::IDevice::ConstPtr m_device;
|
||||
const QString m_remoteExecutable;
|
||||
const QString m_arguments;
|
||||
const QString m_commandPrefix;
|
||||
int m_port;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -41,7 +41,6 @@ SOURCES += qnxplugin.cpp \
|
||||
qnxrunconfiguration.cpp \
|
||||
qnxruncontrolfactory.cpp \
|
||||
qnxdebugsupport.cpp \
|
||||
qnxapplicationrunner.cpp \
|
||||
qnxdeploystepfactory.cpp \
|
||||
qnxdeployconfigurationfactory.cpp \
|
||||
qnxrunconfigurationfactory.cpp \
|
||||
@@ -91,7 +90,6 @@ HEADERS += qnxplugin.h\
|
||||
qnxrunconfiguration.h \
|
||||
qnxruncontrolfactory.h \
|
||||
qnxdebugsupport.h \
|
||||
qnxapplicationrunner.h \
|
||||
qnxdeploystepfactory.h \
|
||||
qnxdeployconfigurationfactory.h \
|
||||
qnxrunconfigurationfactory.h \
|
||||
|
@@ -1,85 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (C) 2011 - 2012 Research In Motion
|
||||
**
|
||||
** Contact: Research In Motion (blackberry-qt@qnx.com)
|
||||
** Contact: KDAB (info@kdab.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "qnxapplicationrunner.h"
|
||||
#include "qnxrunconfiguration.h"
|
||||
#include "qnxconstants.h"
|
||||
|
||||
using namespace Qnx;
|
||||
using namespace Qnx::Internal;
|
||||
|
||||
QnxApplicationRunner::QnxApplicationRunner(QnxRunConfiguration *runConfig, QObject *parent)
|
||||
: RemoteLinux::AbstractRemoteLinuxApplicationRunner(runConfig, parent)
|
||||
, m_debugMode(false)
|
||||
{
|
||||
usedPortsGatherer()->setCommand(QLatin1String(Constants::QNX_PORT_GATHERER_COMMAND));
|
||||
}
|
||||
|
||||
void QnxApplicationRunner::setDebugMode(bool debugMode)
|
||||
{
|
||||
m_debugMode = debugMode;
|
||||
}
|
||||
|
||||
void QnxApplicationRunner::doDeviceSetup()
|
||||
{
|
||||
handleDeviceSetupDone(true);
|
||||
}
|
||||
|
||||
void QnxApplicationRunner::doAdditionalInitialCleanup()
|
||||
{
|
||||
handleInitialCleanupDone(true);
|
||||
}
|
||||
|
||||
void QnxApplicationRunner::doAdditionalInitializations()
|
||||
{
|
||||
handleInitializationsDone(true);
|
||||
}
|
||||
|
||||
void QnxApplicationRunner::doPostRunCleanup()
|
||||
{
|
||||
handlePostRunCleanupDone();
|
||||
}
|
||||
|
||||
void QnxApplicationRunner::doAdditionalConnectionErrorHandling()
|
||||
{
|
||||
}
|
||||
|
||||
QString QnxApplicationRunner::killApplicationCommandLine() const
|
||||
{
|
||||
QString executable = m_debugMode ? QLatin1String(Constants::QNX_DEBUG_EXECUTABLE) : remoteExecutable();
|
||||
executable.replace(QLatin1String("/"), QLatin1String("\\/"));
|
||||
return QString::fromLatin1("for PID in $(ps -f -o pid,comm | grep %1 | awk '/%1/ {print $1}'); "
|
||||
"do "
|
||||
"kill $PID; sleep 1; kill -9 $PID; "
|
||||
"done").arg(executable);
|
||||
}
|
@@ -1,69 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (C) 2011 - 2012 Research In Motion
|
||||
**
|
||||
** Contact: Research In Motion (blackberry-qt@qnx.com)
|
||||
** Contact: KDAB (info@kdab.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at info@qt.nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef QNX_INTERNAL_QNXAPPLICATIONRUNNER_H
|
||||
#define QNX_INTERNAL_QNXAPPLICATIONRUNNER_H
|
||||
|
||||
#include <remotelinux/remotelinuxapplicationrunner.h>
|
||||
|
||||
namespace Qnx {
|
||||
namespace Internal {
|
||||
|
||||
class QnxRunConfiguration;
|
||||
|
||||
class QnxApplicationRunner : public RemoteLinux::AbstractRemoteLinuxApplicationRunner
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QnxApplicationRunner(QnxRunConfiguration *runConfig,
|
||||
QObject *parent = 0);
|
||||
|
||||
void setDebugMode(bool debugMode);
|
||||
|
||||
protected:
|
||||
void doDeviceSetup();
|
||||
void doAdditionalInitialCleanup();
|
||||
void doAdditionalInitializations();
|
||||
void doPostRunCleanup();
|
||||
void doAdditionalConnectionErrorHandling();
|
||||
|
||||
private:
|
||||
QString killApplicationCommandLine() const;
|
||||
|
||||
bool m_debugMode;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qnx
|
||||
|
||||
#endif // QNX_INTERNAL_QNXAPPLICATIONRUNNER_H
|
@@ -32,22 +32,46 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "qnxdebugsupport.h"
|
||||
#include "qnxapplicationrunner.h"
|
||||
#include "qnxconstants.h"
|
||||
#include "qnxrunconfiguration.h"
|
||||
#include "qnxutils.h"
|
||||
|
||||
#include <debugger/debuggerengine.h>
|
||||
#include <projectexplorer/devicesupport/deviceapplicationrunner.h>
|
||||
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
|
||||
#include <projectexplorer/profileinformation.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <utils/portlist.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace RemoteLinux;
|
||||
|
||||
using namespace Qnx;
|
||||
using namespace Qnx::Internal;
|
||||
|
||||
QnxDebugSupport::QnxDebugSupport(QnxRunConfiguration *runConfig, Debugger::DebuggerEngine *engine)
|
||||
: QObject(engine)
|
||||
, m_executable(QLatin1String(Constants::QNX_DEBUG_EXECUTABLE))
|
||||
, m_commandPrefix(runConfig->commandPrefix())
|
||||
, m_arguments(runConfig->arguments())
|
||||
, m_device(DeviceProfileInformation::device(runConfig->target()->profile()))
|
||||
, m_engine(engine)
|
||||
, m_port(-1)
|
||||
, m_state(Inactive)
|
||||
{
|
||||
m_runner = new QnxApplicationRunner(runConfig, this);
|
||||
m_runner->setDebugMode(true);
|
||||
m_runner = new DeviceApplicationRunner(this);
|
||||
m_portsGatherer = new DeviceUsedPortsGatherer(this);
|
||||
m_portsGatherer->setCommand(QLatin1String(Constants::QNX_PORT_GATHERER_COMMAND));
|
||||
|
||||
connect(m_portsGatherer, SIGNAL(error(QString)), SLOT(handleError(QString)));
|
||||
connect(m_portsGatherer, SIGNAL(portListReady()), SLOT(handlePortListReady()));
|
||||
|
||||
connect(m_runner, SIGNAL(reportError(QString)), SLOT(handleError(QString)));
|
||||
connect(m_runner, SIGNAL(remoteProcessStarted()), this, SLOT(handleRemoteProcessStarted()));
|
||||
connect(m_runner, SIGNAL(finished(bool)), SLOT(handleRemoteProcessFinished(qint64)));
|
||||
connect(m_runner, SIGNAL(reportProgress(QString)), this, SLOT(handleProgressReport(QString)));
|
||||
connect(m_runner, SIGNAL(remoteStdout(QByteArray)), this, SLOT(handleRemoteOutput(QByteArray)));
|
||||
|
||||
connect(m_engine, SIGNAL(requestRemoteSetup()), this, SLOT(handleAdapterSetupRequested()));
|
||||
}
|
||||
@@ -56,18 +80,16 @@ void QnxDebugSupport::handleAdapterSetupRequested()
|
||||
{
|
||||
QTC_ASSERT(m_state == Inactive, return);
|
||||
|
||||
m_state = StartingRunner;
|
||||
m_state = GatheringPorts;
|
||||
if (m_engine)
|
||||
m_engine->showMessage(tr("Preparing remote side...\n"), Debugger::AppStuff);
|
||||
m_portsGatherer->start(m_device);
|
||||
}
|
||||
|
||||
connect(m_runner, SIGNAL(error(QString)), this, SLOT(handleSshError(QString)));
|
||||
connect(m_runner, SIGNAL(readyForExecution()), this, SLOT(startExecution()));
|
||||
connect(m_runner, SIGNAL(remoteProcessStarted()), this, SLOT(handleRemoteProcessStarted()));
|
||||
connect(m_runner, SIGNAL(remoteProcessFinished(qint64)), this, SLOT(handleRemoteProcessFinished(qint64)));
|
||||
connect(m_runner, SIGNAL(reportProgress(QString)), this, SLOT(handleProgressReport(QString)));
|
||||
connect(m_runner, SIGNAL(remoteOutput(QByteArray)), this, SLOT(handleRemoteOutput(QByteArray)));
|
||||
|
||||
m_runner->start();
|
||||
void QnxDebugSupport::handlePortListReady()
|
||||
{
|
||||
QTC_ASSERT(m_state == GatheringPorts, return);
|
||||
startExecution();
|
||||
}
|
||||
|
||||
void QnxDebugSupport::startExecution()
|
||||
@@ -75,13 +97,13 @@ void QnxDebugSupport::startExecution()
|
||||
if (m_state == Inactive)
|
||||
return;
|
||||
|
||||
QTC_ASSERT(m_state == StartingRunner, return);
|
||||
|
||||
m_state = StartingRemoteProcess;
|
||||
m_port = m_runner->usedPortsGatherer()->getNextFreePort(m_runner->freePorts());
|
||||
Utils::PortList portList = m_device->freePorts();
|
||||
m_port = m_portsGatherer->getNextFreePort(&portList);
|
||||
|
||||
const QString remoteCommandLine = QString::fromLatin1("%1 %2 %3").arg(m_runner->commandPrefix()).arg(QLatin1String(Constants::QNX_DEBUG_EXECUTABLE)).arg(m_port);
|
||||
m_runner->startExecution(remoteCommandLine.toUtf8());
|
||||
const QString remoteCommandLine = QString::fromLatin1("%1 %2 %3")
|
||||
.arg(m_commandPrefix, m_executable).arg(m_port);
|
||||
m_runner->start(m_device, remoteCommandLine.toUtf8());
|
||||
}
|
||||
|
||||
void QnxDebugSupport::handleRemoteProcessStarted()
|
||||
@@ -90,17 +112,17 @@ void QnxDebugSupport::handleRemoteProcessStarted()
|
||||
m_engine->notifyEngineRemoteSetupDone(m_port, -1);
|
||||
}
|
||||
|
||||
void QnxDebugSupport::handleRemoteProcessFinished(qint64 exitCode)
|
||||
void QnxDebugSupport::handleRemoteProcessFinished(bool success)
|
||||
{
|
||||
if (m_engine || m_state == Inactive)
|
||||
return;
|
||||
|
||||
if (m_state == Debugging) {
|
||||
if (exitCode != 0)
|
||||
if (!success)
|
||||
m_engine->notifyInferiorIll();
|
||||
|
||||
} else {
|
||||
const QString errorMsg = tr("The %1 process closed unexpectedly.").arg(QLatin1String(Constants::QNX_DEBUG_EXECUTABLE));
|
||||
const QString errorMsg = tr("The %1 process closed unexpectedly.").arg(m_executable);
|
||||
m_engine->notifyEngineRemoteSetupFailed(errorMsg);
|
||||
}
|
||||
}
|
||||
@@ -113,7 +135,7 @@ void QnxDebugSupport::handleDebuggingFinished()
|
||||
void QnxDebugSupport::setFinished()
|
||||
{
|
||||
m_state = Inactive;
|
||||
m_runner->stop();
|
||||
m_runner->stop(QnxUtils::applicationKillCommand(m_executable).toUtf8());
|
||||
}
|
||||
|
||||
void QnxDebugSupport::handleProgressReport(const QString &progressOutput)
|
||||
@@ -130,7 +152,7 @@ void QnxDebugSupport::handleRemoteOutput(const QByteArray &output)
|
||||
m_engine->showMessage(QString::fromUtf8(output), Debugger::AppOutput);
|
||||
}
|
||||
|
||||
void QnxDebugSupport::handleSshError(const QString &error)
|
||||
void QnxDebugSupport::handleError(const QString &error)
|
||||
{
|
||||
if (m_state == Debugging) {
|
||||
if (m_engine) {
|
||||
|
@@ -34,16 +34,20 @@
|
||||
#ifndef QNX_INTERNAL_QNXDEBUGSUPPORT_H
|
||||
#define QNX_INTERNAL_QNXDEBUGSUPPORT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <projectexplorer/devicesupport/idevice.h>
|
||||
|
||||
namespace Debugger {
|
||||
class DebuggerEngine;
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
namespace Debugger { class DebuggerEngine; }
|
||||
namespace ProjectExplorer {
|
||||
class DeviceApplicationRunner;
|
||||
class DeviceUsedPortsGatherer;
|
||||
}
|
||||
|
||||
namespace Qnx {
|
||||
namespace Internal {
|
||||
|
||||
class QnxApplicationRunner;
|
||||
class QnxRunConfiguration;
|
||||
|
||||
class QnxDebugSupport : public QObject
|
||||
@@ -59,25 +63,30 @@ public slots:
|
||||
private slots:
|
||||
void handleAdapterSetupRequested();
|
||||
|
||||
void startExecution();
|
||||
void handleRemoteProcessStarted();
|
||||
void handleRemoteProcessFinished(qint64 exitCode);
|
||||
void handleRemoteProcessFinished(bool success);
|
||||
void handleProgressReport(const QString &progressOutput);
|
||||
void handleRemoteOutput(const QByteArray &output);
|
||||
void handleSshError(const QString &error);
|
||||
void handleError(const QString &error);
|
||||
void handlePortListReady();
|
||||
|
||||
private:
|
||||
void startExecution();
|
||||
void setFinished();
|
||||
|
||||
enum State {
|
||||
Inactive,
|
||||
StartingRunner,
|
||||
GatheringPorts,
|
||||
StartingRemoteProcess,
|
||||
Debugging
|
||||
};
|
||||
|
||||
QnxApplicationRunner *m_runner;
|
||||
|
||||
const QString m_executable;
|
||||
const QString m_commandPrefix;
|
||||
const QString m_arguments;
|
||||
ProjectExplorer::IDevice::ConstPtr m_device;
|
||||
ProjectExplorer::DeviceApplicationRunner *m_runner;
|
||||
ProjectExplorer::DeviceUsedPortsGatherer * m_portsGatherer;
|
||||
Debugger::DebuggerEngine *m_engine;
|
||||
int m_port;
|
||||
|
||||
|
@@ -32,21 +32,22 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "qnxruncontrol.h"
|
||||
#include "qnxapplicationrunner.h"
|
||||
#include "qnxrunconfiguration.h"
|
||||
#include "qnxutils.h"
|
||||
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
#include <remotelinux/remotelinuxrunconfiguration.h>
|
||||
|
||||
using namespace Qnx;
|
||||
using namespace Qnx::Internal;
|
||||
using namespace RemoteLinux;
|
||||
|
||||
QnxRunControl::QnxRunControl(ProjectExplorer::RunConfiguration *runConfig)
|
||||
: RemoteLinux::AbstractRemoteLinuxRunControl(runConfig)
|
||||
, m_runner(new QnxApplicationRunner(qobject_cast<QnxRunConfiguration *>(runConfig), this))
|
||||
: RemoteLinuxRunControl(runConfig)
|
||||
{
|
||||
}
|
||||
|
||||
RemoteLinux::AbstractRemoteLinuxApplicationRunner *QnxRunControl::runner() const
|
||||
{
|
||||
return m_runner;
|
||||
const RemoteLinuxRunConfiguration * const rc
|
||||
= qobject_cast<RemoteLinuxRunConfiguration *>(runConfig);
|
||||
QString executable = rc->remoteExecutableFilePath();
|
||||
executable.replace(QLatin1String("/"), QLatin1String("\\/"));
|
||||
overrideStopCommandLine(QnxUtils::applicationKillCommand(executable).toUtf8());
|
||||
}
|
||||
|
@@ -39,18 +39,11 @@
|
||||
namespace Qnx {
|
||||
namespace Internal {
|
||||
|
||||
class QnxApplicationRunner;
|
||||
|
||||
class QnxRunControl : public RemoteLinux::AbstractRemoteLinuxRunControl
|
||||
class QnxRunControl : public RemoteLinux::RemoteLinuxRunControl
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QnxRunControl(ProjectExplorer::RunConfiguration *runConfig);
|
||||
|
||||
RemoteLinux::AbstractRemoteLinuxApplicationRunner *runner() const;
|
||||
|
||||
private:
|
||||
QnxApplicationRunner * const m_runner;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -75,3 +75,11 @@ QStringList QnxUtils::searchPaths(QnxAbstractQtVersion *qtVersion)
|
||||
|
||||
return searchPaths;
|
||||
}
|
||||
|
||||
QString QnxUtils::applicationKillCommand(const QString &applicationFilePath)
|
||||
{
|
||||
return QString::fromLatin1("for PID in $(ps -f -o pid,comm | grep %1 | awk '/%1/ {print $1}'); "
|
||||
"do "
|
||||
"kill $PID; sleep 1; kill -9 $PID; "
|
||||
"done").arg(applicationFilePath);
|
||||
}
|
||||
|
@@ -49,6 +49,7 @@ public:
|
||||
static QString addQuotes(const QString &string);
|
||||
static Qnx::QnxArchitecture cpudirToArch(const QString &cpuDir);
|
||||
static QStringList searchPaths(QnxAbstractQtVersion *qtVersion);
|
||||
static QString applicationKillCommand(const QString &applicationFilePath);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -17,7 +17,6 @@ HEADERS += \
|
||||
genericlinuxdeviceconfigurationfactory.h \
|
||||
remotelinuxrunconfigurationwidget.h \
|
||||
remotelinuxrunconfigurationfactory.h \
|
||||
remotelinuxapplicationrunner.h \
|
||||
remotelinuxruncontrol.h \
|
||||
remotelinuxruncontrolfactory.h \
|
||||
remotelinuxdebugsupport.h \
|
||||
@@ -65,7 +64,6 @@ SOURCES += \
|
||||
genericlinuxdeviceconfigurationfactory.cpp \
|
||||
remotelinuxrunconfigurationwidget.cpp \
|
||||
remotelinuxrunconfigurationfactory.cpp \
|
||||
remotelinuxapplicationrunner.cpp \
|
||||
remotelinuxruncontrol.cpp \
|
||||
remotelinuxruncontrolfactory.cpp \
|
||||
remotelinuxdebugsupport.cpp \
|
||||
|
@@ -64,8 +64,6 @@ QtcPlugin {
|
||||
"remotelinux.qrc",
|
||||
"remotelinux_constants.h",
|
||||
"remotelinux_export.h",
|
||||
"remotelinuxapplicationrunner.cpp",
|
||||
"remotelinuxapplicationrunner.h",
|
||||
"remotelinuxcustomcommanddeploymentstep.h",
|
||||
"remotelinuxcustomcommanddeployservice.cpp",
|
||||
"remotelinuxcustomcommanddeployservice.h",
|
||||
|
@@ -1,508 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "remotelinuxapplicationrunner.h"
|
||||
|
||||
#include "linuxdeviceconfiguration.h"
|
||||
#include "remotelinuxrunconfiguration.h"
|
||||
|
||||
#include <projectexplorer/target.h>
|
||||
#include <projectexplorer/profileinformation.h>
|
||||
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
|
||||
|
||||
#include <utils/portlist.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <ssh/sshconnection.h>
|
||||
#include <ssh/sshconnectionmanager.h>
|
||||
#include <ssh/sshremoteprocess.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace QSsh;
|
||||
using namespace Utils;
|
||||
|
||||
namespace RemoteLinux {
|
||||
namespace Internal {
|
||||
namespace {
|
||||
|
||||
enum State {
|
||||
Inactive, SettingUpDevice, Connecting, PreRunCleaning, AdditionalPreRunCleaning,
|
||||
GatheringPorts, AdditionalInitializing, ReadyForExecution, ProcessStarting, ProcessStarted,
|
||||
PostRunCleaning
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
class AbstractRemoteLinuxApplicationRunnerPrivate
|
||||
{
|
||||
public:
|
||||
AbstractRemoteLinuxApplicationRunnerPrivate(const RemoteLinuxRunConfiguration *runConfig)
|
||||
: devConfig(DeviceProfileInformation::device(runConfig->target()->profile())),
|
||||
remoteExecutable(runConfig->remoteExecutableFilePath()),
|
||||
appArguments(runConfig->arguments()),
|
||||
commandPrefix(runConfig->commandPrefix()),
|
||||
initialFreePorts(devConfig->freePorts()),
|
||||
connection(0),
|
||||
stopRequested(false),
|
||||
state(Inactive)
|
||||
{ }
|
||||
|
||||
DeviceUsedPortsGatherer portsGatherer;
|
||||
IDevice::ConstPtr devConfig;
|
||||
const QString remoteExecutable;
|
||||
const QString appArguments;
|
||||
const QString commandPrefix;
|
||||
const PortList initialFreePorts;
|
||||
|
||||
QSsh::SshConnection *connection;
|
||||
QSsh::SshRemoteProcess::Ptr runner;
|
||||
QSsh::SshRemoteProcess::Ptr cleaner;
|
||||
|
||||
PortList freePorts;
|
||||
int exitStatus;
|
||||
bool stopRequested;
|
||||
State state;
|
||||
|
||||
};
|
||||
} // namespace Internal
|
||||
|
||||
|
||||
using namespace Internal;
|
||||
|
||||
AbstractRemoteLinuxApplicationRunner::AbstractRemoteLinuxApplicationRunner(RemoteLinuxRunConfiguration *runConfig,
|
||||
QObject *parent)
|
||||
: QObject(parent), d(new AbstractRemoteLinuxApplicationRunnerPrivate(runConfig))
|
||||
{
|
||||
connect(&d->portsGatherer, SIGNAL(error(QString)), SLOT(handlePortsGathererError(QString)));
|
||||
connect(&d->portsGatherer, SIGNAL(portListReady()), SLOT(handleUsedPortsAvailable()));
|
||||
}
|
||||
|
||||
AbstractRemoteLinuxApplicationRunner::~AbstractRemoteLinuxApplicationRunner()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
SshConnection *AbstractRemoteLinuxApplicationRunner::connection() const
|
||||
{
|
||||
return d->connection;
|
||||
}
|
||||
|
||||
IDevice::ConstPtr AbstractRemoteLinuxApplicationRunner::devConfig() const
|
||||
{
|
||||
return d->devConfig;
|
||||
}
|
||||
|
||||
DeviceUsedPortsGatherer *AbstractRemoteLinuxApplicationRunner::usedPortsGatherer() const
|
||||
{
|
||||
return &d->portsGatherer;
|
||||
}
|
||||
|
||||
PortList *AbstractRemoteLinuxApplicationRunner::freePorts()
|
||||
{
|
||||
return &d->freePorts;
|
||||
}
|
||||
|
||||
QString AbstractRemoteLinuxApplicationRunner::remoteExecutable() const
|
||||
{
|
||||
return d->remoteExecutable;
|
||||
}
|
||||
|
||||
QString AbstractRemoteLinuxApplicationRunner::arguments() const
|
||||
{
|
||||
return d->appArguments;
|
||||
}
|
||||
|
||||
QString AbstractRemoteLinuxApplicationRunner::commandPrefix() const
|
||||
{
|
||||
return d->commandPrefix;
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::start()
|
||||
{
|
||||
QTC_ASSERT(!d->stopRequested && d->state == Inactive, return);
|
||||
|
||||
QString errorMsg;
|
||||
if (!canRun(errorMsg)) {
|
||||
emitError(tr("Cannot run: %1").arg(errorMsg), true);
|
||||
return;
|
||||
}
|
||||
|
||||
d->state = SettingUpDevice;
|
||||
doDeviceSetup();
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::stop()
|
||||
{
|
||||
if (d->stopRequested)
|
||||
return;
|
||||
|
||||
switch (d->state) {
|
||||
case Connecting:
|
||||
setInactive();
|
||||
emit remoteProcessFinished(InvalidExitCode);
|
||||
break;
|
||||
case GatheringPorts:
|
||||
d->portsGatherer.stop();
|
||||
setInactive();
|
||||
emit remoteProcessFinished(InvalidExitCode);
|
||||
break;
|
||||
case SettingUpDevice:
|
||||
case PreRunCleaning:
|
||||
case AdditionalPreRunCleaning:
|
||||
case AdditionalInitializing:
|
||||
case ProcessStarting:
|
||||
case PostRunCleaning:
|
||||
d->stopRequested = true; // TODO: We might need stopPreRunCleaning() etc. for the subclasses
|
||||
break;
|
||||
case ReadyForExecution:
|
||||
d->stopRequested = true;
|
||||
d->state = PostRunCleaning;
|
||||
doPostRunCleanup();
|
||||
break;
|
||||
case ProcessStarted:
|
||||
d->stopRequested = true;
|
||||
cleanup();
|
||||
break;
|
||||
case Inactive:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handleConnected()
|
||||
{
|
||||
QTC_ASSERT(d->state == Connecting, return);
|
||||
|
||||
if (d->stopRequested) {
|
||||
emit remoteProcessFinished(InvalidExitCode);
|
||||
setInactive();
|
||||
} else {
|
||||
d->state = PreRunCleaning;
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handleConnectionFailure()
|
||||
{
|
||||
QTC_ASSERT(d->state != Inactive, return);
|
||||
|
||||
if (d->state != Connecting || d->state != PreRunCleaning)
|
||||
doAdditionalConnectionErrorHandling();
|
||||
|
||||
const QString errorMsg = d->state == Connecting
|
||||
? tr("Could not connect to host: %1") : tr("Connection error: %1");
|
||||
emitError(errorMsg.arg(d->connection->errorString()));
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::cleanup()
|
||||
{
|
||||
QTC_ASSERT(d->state == PreRunCleaning
|
||||
|| (d->state == ProcessStarted && d->stopRequested), return);
|
||||
|
||||
emit reportProgress(tr("Killing remote process(es)..."));
|
||||
d->cleaner = d->connection->createRemoteProcess(killApplicationCommandLine().toUtf8());
|
||||
connect(d->cleaner.data(), SIGNAL(closed(int)), SLOT(handleCleanupFinished(int)));
|
||||
d->cleaner->start();
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handleCleanupFinished(int exitStatus)
|
||||
{
|
||||
Q_ASSERT(exitStatus == SshRemoteProcess::FailedToStart
|
||||
|| exitStatus == SshRemoteProcess::CrashExit
|
||||
|| exitStatus == SshRemoteProcess::NormalExit);
|
||||
|
||||
QTC_ASSERT(d->state == PreRunCleaning
|
||||
|| (d->state == ProcessStarted && d->stopRequested) || d->state == Inactive, return);
|
||||
|
||||
if (d->state == Inactive)
|
||||
return;
|
||||
if (d->stopRequested && d->state == PreRunCleaning) {
|
||||
setInactive();
|
||||
emit remoteProcessFinished(InvalidExitCode);
|
||||
return;
|
||||
}
|
||||
if (d->stopRequested) {
|
||||
d->state = PostRunCleaning;
|
||||
doPostRunCleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
if (exitStatus != SshRemoteProcess::NormalExit) {
|
||||
emitError(tr("Initial cleanup failed: %1").arg(d->cleaner->errorString()));
|
||||
emit remoteProcessFinished(InvalidExitCode);
|
||||
return;
|
||||
}
|
||||
|
||||
d->state = AdditionalPreRunCleaning;
|
||||
doAdditionalInitialCleanup();
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::startExecution(const QByteArray &remoteCall)
|
||||
{
|
||||
QTC_ASSERT(d->state == ReadyForExecution, return);
|
||||
|
||||
if (d->stopRequested)
|
||||
return;
|
||||
|
||||
d->runner = d->connection->createRemoteProcess(remoteCall);
|
||||
connect(d->runner.data(), SIGNAL(started()), SLOT(handleRemoteProcessStarted()));
|
||||
connect(d->runner.data(), SIGNAL(closed(int)), SLOT(handleRemoteProcessFinished(int)));
|
||||
connect(d->runner.data(), SIGNAL(readyReadStandardOutput()), SLOT(handleRemoteStdout()));
|
||||
connect(d->runner.data(), SIGNAL(readyReadStandardError()), SLOT(handleRemoteStderr()));
|
||||
d->state = ProcessStarting;
|
||||
d->runner->start();
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handleRemoteProcessStarted()
|
||||
{
|
||||
QTC_ASSERT(d->state == ProcessStarting, return);
|
||||
|
||||
d->state = ProcessStarted;
|
||||
if (d->stopRequested) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
emit reportProgress(tr("Remote process started."));
|
||||
emit remoteProcessStarted();
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handleRemoteProcessFinished(int exitStatus)
|
||||
{
|
||||
Q_ASSERT(exitStatus == SshRemoteProcess::FailedToStart
|
||||
|| exitStatus == SshRemoteProcess::CrashExit
|
||||
|| exitStatus == SshRemoteProcess::NormalExit);
|
||||
QTC_ASSERT(d->state == ProcessStarted || d->state == Inactive, return);
|
||||
|
||||
d->exitStatus = exitStatus;
|
||||
if (!d->stopRequested && d->state != Inactive) {
|
||||
d->state = PostRunCleaning;
|
||||
doPostRunCleanup();
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::setInactive()
|
||||
{
|
||||
d->portsGatherer.stop();
|
||||
if (d->connection) {
|
||||
disconnect(d->connection, 0, this, 0);
|
||||
SshConnectionManager::instance().releaseConnection(d->connection);
|
||||
d->connection = 0;
|
||||
}
|
||||
if (d->cleaner)
|
||||
disconnect(d->cleaner.data(), 0, this, 0);
|
||||
d->stopRequested = false;
|
||||
d->state = Inactive;
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::emitError(const QString &errorMsg, bool force)
|
||||
{
|
||||
if (d->state != Inactive) {
|
||||
setInactive();
|
||||
emit error(errorMsg);
|
||||
} else if (force) {
|
||||
emit error(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handlePortsGathererError(const QString &errorMsg)
|
||||
{
|
||||
if (d->state != Inactive) {
|
||||
if (connection()->errorState() != SshNoError) {
|
||||
emitError(errorMsg);
|
||||
} else {
|
||||
emit reportProgress(tr("Gathering ports failed: %1\nContinuing anyway.").arg(errorMsg));
|
||||
handleUsedPortsAvailable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handleUsedPortsAvailable()
|
||||
{
|
||||
QTC_ASSERT(d->state == GatheringPorts, return);
|
||||
|
||||
if (d->stopRequested) {
|
||||
setInactive();
|
||||
emit remoteProcessFinished(InvalidExitCode);
|
||||
return;
|
||||
}
|
||||
|
||||
d->state = AdditionalInitializing;
|
||||
doAdditionalInitializations();
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handleRemoteStdout()
|
||||
{
|
||||
emit remoteOutput(d->runner->readAllStandardOutput());
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handleRemoteStderr()
|
||||
{
|
||||
emit remoteErrorOutput(d->runner->readAllStandardError());
|
||||
}
|
||||
|
||||
bool AbstractRemoteLinuxApplicationRunner::canRun(QString &whyNot) const
|
||||
{
|
||||
if (d->remoteExecutable.isEmpty()) {
|
||||
whyNot = tr("No remote executable set.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!d->devConfig) {
|
||||
whyNot = tr("No device configuration set.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handleDeviceSetupDone(bool success)
|
||||
{
|
||||
QTC_ASSERT(d->state == SettingUpDevice, return);
|
||||
|
||||
if (!success || d->stopRequested) {
|
||||
setInactive();
|
||||
emit remoteProcessFinished(InvalidExitCode);
|
||||
return;
|
||||
}
|
||||
|
||||
d->connection = SshConnectionManager::instance().acquireConnection(d->devConfig->sshParameters());
|
||||
d->state = Connecting;
|
||||
d->exitStatus = -1;
|
||||
d->freePorts = d->initialFreePorts;
|
||||
connect(d->connection, SIGNAL(connected()), SLOT(handleConnected()));
|
||||
connect(d->connection, SIGNAL(error(QSsh::SshError)),
|
||||
SLOT(handleConnectionFailure()));
|
||||
if (d->connection->state() == SshConnection::Connected) {
|
||||
handleConnected();
|
||||
} else {
|
||||
emit reportProgress(tr("Connecting to device..."));
|
||||
if (d->connection->state() == QSsh::SshConnection::Unconnected)
|
||||
d->connection->connectToHost();
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handleInitialCleanupDone(bool success)
|
||||
{
|
||||
QTC_ASSERT(d->state == AdditionalPreRunCleaning, return);
|
||||
|
||||
if (!success || d->stopRequested) {
|
||||
setInactive();
|
||||
emit remoteProcessFinished(InvalidExitCode);
|
||||
return;
|
||||
}
|
||||
|
||||
d->state = GatheringPorts;
|
||||
d->portsGatherer.start(d->devConfig);
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handleInitializationsDone(bool success)
|
||||
{
|
||||
QTC_ASSERT(d->state == AdditionalInitializing, return);
|
||||
|
||||
if (!success) {
|
||||
setInactive();
|
||||
emit remoteProcessFinished(InvalidExitCode);
|
||||
return;
|
||||
}
|
||||
if (d->stopRequested) {
|
||||
d->state = PostRunCleaning;
|
||||
doPostRunCleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
d->state = ReadyForExecution;
|
||||
emit readyForExecution();
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxApplicationRunner::handlePostRunCleanupDone()
|
||||
{
|
||||
QTC_ASSERT(d->state == PostRunCleaning, return);
|
||||
|
||||
const bool wasStopRequested = d->stopRequested;
|
||||
setInactive();
|
||||
if (wasStopRequested)
|
||||
emit remoteProcessFinished(InvalidExitCode);
|
||||
else if (d->exitStatus == SshRemoteProcess::NormalExit)
|
||||
emit remoteProcessFinished(d->runner->exitCode());
|
||||
else
|
||||
emit error(tr("Error running remote process: %1").arg(d->runner->errorString()));
|
||||
}
|
||||
|
||||
QString AbstractRemoteLinuxApplicationRunner::killApplicationCommandLine() const
|
||||
{
|
||||
return QString::fromLatin1("cd /proc; for pid in `ls -d [0123456789]*`; "
|
||||
"do "
|
||||
"if [ \"`readlink /proc/$pid/exe`\" = \"%1\" ]; then "
|
||||
" kill $pid; sleep 1; kill -9 $pid; "
|
||||
"fi; "
|
||||
"done").arg(remoteExecutable());
|
||||
}
|
||||
|
||||
|
||||
const qint64 AbstractRemoteLinuxApplicationRunner::InvalidExitCode = std::numeric_limits<qint64>::min();
|
||||
|
||||
|
||||
GenericRemoteLinuxApplicationRunner::GenericRemoteLinuxApplicationRunner(RemoteLinuxRunConfiguration *runConfig,
|
||||
QObject *parent)
|
||||
: AbstractRemoteLinuxApplicationRunner(runConfig, parent)
|
||||
{
|
||||
}
|
||||
|
||||
GenericRemoteLinuxApplicationRunner::~GenericRemoteLinuxApplicationRunner()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GenericRemoteLinuxApplicationRunner::doDeviceSetup()
|
||||
{
|
||||
handleDeviceSetupDone(true);
|
||||
}
|
||||
|
||||
void GenericRemoteLinuxApplicationRunner::doAdditionalInitialCleanup()
|
||||
{
|
||||
handleInitialCleanupDone(true);
|
||||
}
|
||||
|
||||
void GenericRemoteLinuxApplicationRunner::doAdditionalInitializations()
|
||||
{
|
||||
handleInitializationsDone(true);
|
||||
}
|
||||
|
||||
void GenericRemoteLinuxApplicationRunner::doPostRunCleanup()
|
||||
{
|
||||
handlePostRunCleanupDone();
|
||||
}
|
||||
|
||||
void GenericRemoteLinuxApplicationRunner::doAdditionalConnectionErrorHandling()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace RemoteLinux
|
||||
|
@@ -1,145 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef REMOTELINUXAPPLICATIONRUNNER_H
|
||||
#define REMOTELINUXAPPLICATIONRUNNER_H
|
||||
|
||||
#include "remotelinux_export.h"
|
||||
|
||||
#include <projectexplorer/devicesupport/idevice.h>
|
||||
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
|
||||
|
||||
namespace QSsh { class SshConnection; }
|
||||
namespace Utils { class PortList; }
|
||||
|
||||
namespace RemoteLinux {
|
||||
class RemoteLinuxRunConfiguration;
|
||||
|
||||
namespace Internal { class AbstractRemoteLinuxApplicationRunnerPrivate; }
|
||||
|
||||
class REMOTELINUX_EXPORT AbstractRemoteLinuxApplicationRunner : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(AbstractRemoteLinuxApplicationRunner)
|
||||
public:
|
||||
AbstractRemoteLinuxApplicationRunner(RemoteLinuxRunConfiguration *runConfig,
|
||||
QObject *parent = 0);
|
||||
~AbstractRemoteLinuxApplicationRunner();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void startExecution(const QByteArray &remoteCall);
|
||||
|
||||
ProjectExplorer::IDevice::ConstPtr devConfig() const;
|
||||
QSsh::SshConnection *connection() const;
|
||||
ProjectExplorer::DeviceUsedPortsGatherer *usedPortsGatherer() const;
|
||||
Utils::PortList *freePorts();
|
||||
QString remoteExecutable() const;
|
||||
QString arguments() const;
|
||||
QString commandPrefix() const;
|
||||
|
||||
static const qint64 InvalidExitCode;
|
||||
|
||||
signals:
|
||||
void error(const QString &error);
|
||||
void readyForExecution();
|
||||
void remoteOutput(const QByteArray &output);
|
||||
void remoteErrorOutput(const QByteArray &output);
|
||||
void reportProgress(const QString &progressOutput);
|
||||
void remoteProcessStarted();
|
||||
void remoteProcessFinished(qint64 exitCode);
|
||||
|
||||
protected:
|
||||
// Override to to additional checks.
|
||||
virtual bool canRun(QString &whyNot) const;
|
||||
|
||||
void handleDeviceSetupDone(bool success);
|
||||
void handleInitialCleanupDone(bool success);
|
||||
void handleInitializationsDone(bool success);
|
||||
void handlePostRunCleanupDone();
|
||||
|
||||
private slots:
|
||||
void handleConnected();
|
||||
void handleConnectionFailure();
|
||||
void handleCleanupFinished(int exitStatus);
|
||||
void handleRemoteProcessStarted();
|
||||
void handleRemoteProcessFinished(int exitStatus);
|
||||
void handlePortsGathererError(const QString &errorMsg);
|
||||
void handleUsedPortsAvailable();
|
||||
void handleRemoteStdout();
|
||||
void handleRemoteStderr();
|
||||
|
||||
private:
|
||||
|
||||
virtual QString killApplicationCommandLine() const;
|
||||
|
||||
// Implement to do custom setup of the device *before* connecting.
|
||||
// Call handleDeviceSetupDone() afterwards.
|
||||
virtual void doDeviceSetup() = 0;
|
||||
|
||||
// Implement to do additional pre-run cleanup and call handleInitialCleanupDone().
|
||||
virtual void doAdditionalInitialCleanup() = 0;
|
||||
|
||||
// Implement to do additional initializations right before the application is ready.
|
||||
// Call handleInitializationsDone() afterwards.
|
||||
virtual void doAdditionalInitializations() = 0;
|
||||
|
||||
// Implement to do cleanups after application exit and call handlePostRunCleanupDone();
|
||||
virtual void doPostRunCleanup() = 0;
|
||||
|
||||
virtual void doAdditionalConnectionErrorHandling() = 0;
|
||||
|
||||
void setInactive();
|
||||
void emitError(const QString &errorMsg, bool force = false);
|
||||
void cleanup();
|
||||
|
||||
Internal::AbstractRemoteLinuxApplicationRunnerPrivate * const d;
|
||||
};
|
||||
|
||||
|
||||
class REMOTELINUX_EXPORT GenericRemoteLinuxApplicationRunner : public AbstractRemoteLinuxApplicationRunner
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GenericRemoteLinuxApplicationRunner(RemoteLinuxRunConfiguration *runConfig,
|
||||
QObject *parent = 0);
|
||||
~GenericRemoteLinuxApplicationRunner();
|
||||
|
||||
protected:
|
||||
void doDeviceSetup();
|
||||
void doAdditionalInitialCleanup();
|
||||
void doAdditionalInitializations();
|
||||
void doPostRunCleanup();
|
||||
void doAdditionalConnectionErrorHandling();
|
||||
};
|
||||
|
||||
} // namespace RemoteLinux
|
||||
|
||||
#endif // REMOTELINUXAPPLICATIONRUNNER_H
|
@@ -29,8 +29,8 @@
|
||||
|
||||
#include "remotelinuxdebugsupport.h"
|
||||
|
||||
#include "remotelinuxapplicationrunner.h"
|
||||
#include "remotelinuxrunconfiguration.h"
|
||||
#include "remotelinuxutils.h"
|
||||
|
||||
#include <debugger/debuggerengine.h>
|
||||
#include <debugger/debuggerstartparameters.h>
|
||||
@@ -42,6 +42,8 @@
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <projectexplorer/toolchain.h>
|
||||
#include <projectexplorer/devicesupport/deviceapplicationrunner.h>
|
||||
#include <utils/portlist.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QPointer>
|
||||
@@ -54,19 +56,23 @@ using namespace ProjectExplorer;
|
||||
namespace RemoteLinux {
|
||||
namespace Internal {
|
||||
namespace {
|
||||
enum State { Inactive, StartingRunner, StartingRemoteProcess, Debugging };
|
||||
enum State { Inactive, GatheringPorts, StartingRunner, Debugging };
|
||||
} // anonymous namespace
|
||||
|
||||
class AbstractRemoteLinuxDebugSupportPrivate
|
||||
class LinuxDeviceDebugSupportPrivate
|
||||
{
|
||||
public:
|
||||
AbstractRemoteLinuxDebugSupportPrivate(RunConfiguration *runConfig,
|
||||
LinuxDeviceDebugSupportPrivate(const RemoteLinuxRunConfiguration *runConfig,
|
||||
DebuggerEngine *engine)
|
||||
: engine(engine),
|
||||
qmlDebugging(runConfig->debuggerAspect()->useQmlDebugger()),
|
||||
cppDebugging(runConfig->debuggerAspect()->useCppDebugger()),
|
||||
state(Inactive),
|
||||
gdbServerPort(-1), qmlPort(-1)
|
||||
gdbServerPort(-1), qmlPort(-1),
|
||||
device(DeviceProfileInformation::device(runConfig->target()->profile())),
|
||||
remoteFilePath(runConfig->remoteExecutableFilePath()),
|
||||
arguments(runConfig->arguments()),
|
||||
commandPrefix(runConfig->commandPrefix())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -77,21 +83,20 @@ public:
|
||||
State state;
|
||||
int gdbServerPort;
|
||||
int qmlPort;
|
||||
};
|
||||
|
||||
class RemoteLinuxDebugSupportPrivate
|
||||
{
|
||||
public:
|
||||
RemoteLinuxDebugSupportPrivate(RemoteLinuxRunConfiguration *runConfig) : runner(runConfig) {}
|
||||
|
||||
GenericRemoteLinuxApplicationRunner runner;
|
||||
DeviceApplicationRunner appRunner;
|
||||
DeviceUsedPortsGatherer portsGatherer;
|
||||
const ProjectExplorer::IDevice::ConstPtr device;
|
||||
Utils::PortList portList;
|
||||
const QString remoteFilePath;
|
||||
const QString arguments;
|
||||
const QString commandPrefix;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
using namespace Internal;
|
||||
|
||||
DebuggerStartParameters AbstractRemoteLinuxDebugSupport::startParameters(const RemoteLinuxRunConfiguration *runConfig)
|
||||
DebuggerStartParameters LinuxDeviceDebugSupport::startParameters(const RemoteLinuxRunConfiguration *runConfig)
|
||||
{
|
||||
DebuggerStartParameters params;
|
||||
Target *target = runConfig->target();
|
||||
@@ -130,39 +135,90 @@ DebuggerStartParameters AbstractRemoteLinuxDebugSupport::startParameters(const R
|
||||
return params;
|
||||
}
|
||||
|
||||
AbstractRemoteLinuxDebugSupport::AbstractRemoteLinuxDebugSupport(RunConfiguration *runConfig,
|
||||
LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunConfiguration *runConfig,
|
||||
DebuggerEngine *engine)
|
||||
: QObject(engine), d(new AbstractRemoteLinuxDebugSupportPrivate(runConfig, engine))
|
||||
: QObject(engine),
|
||||
d(new LinuxDeviceDebugSupportPrivate(static_cast<RemoteLinuxRunConfiguration *>(runConfig), engine))
|
||||
{
|
||||
connect(d->engine, SIGNAL(requestRemoteSetup()), this, SLOT(handleRemoteSetupRequested()));
|
||||
}
|
||||
|
||||
AbstractRemoteLinuxDebugSupport::~AbstractRemoteLinuxDebugSupport()
|
||||
LinuxDeviceDebugSupport::~LinuxDeviceDebugSupport()
|
||||
{
|
||||
setFinished();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::showMessage(const QString &msg, int channel)
|
||||
void LinuxDeviceDebugSupport::setApplicationRunnerPreRunAction(DeviceApplicationHelperAction *action)
|
||||
{
|
||||
if (d->engine)
|
||||
d->appRunner.setPreRunAction(action);
|
||||
}
|
||||
|
||||
void LinuxDeviceDebugSupport::setApplicationRunnerPostRunAction(DeviceApplicationHelperAction *action)
|
||||
{
|
||||
d->appRunner.setPostRunAction(action);
|
||||
}
|
||||
|
||||
void LinuxDeviceDebugSupport::showMessage(const QString &msg, int channel)
|
||||
{
|
||||
if (d->state != Inactive && d->engine)
|
||||
d->engine->showMessage(msg, channel);
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::handleRemoteSetupRequested()
|
||||
void LinuxDeviceDebugSupport::handleRemoteSetupRequested()
|
||||
{
|
||||
QTC_ASSERT(d->state == Inactive, return);
|
||||
|
||||
d->state = StartingRunner;
|
||||
showMessage(tr("Preparing remote side...\n"), AppStuff);
|
||||
disconnect(runner(), 0, this, 0);
|
||||
connect(runner(), SIGNAL(error(QString)), this, SLOT(handleSshError(QString)));
|
||||
connect(runner(), SIGNAL(readyForExecution()), this, SLOT(startExecution()));
|
||||
connect(runner(), SIGNAL(reportProgress(QString)), this, SLOT(handleProgressReport(QString)));
|
||||
runner()->start();
|
||||
d->state = GatheringPorts;
|
||||
showMessage(tr("Checking available ports...\n"), LogStatus);
|
||||
connect(&d->portsGatherer, SIGNAL(error(QString)), SLOT(handlePortsGathererError(QString)));
|
||||
connect(&d->portsGatherer, SIGNAL(portListReady()), SLOT(handlePortListReady()));
|
||||
d->portsGatherer.start(d->device);
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::handleSshError(const QString &error)
|
||||
void LinuxDeviceDebugSupport::handlePortsGathererError(const QString &message)
|
||||
{
|
||||
QTC_ASSERT(d->state == GatheringPorts, return);
|
||||
handleAdapterSetupFailed(message);
|
||||
}
|
||||
|
||||
void LinuxDeviceDebugSupport::handlePortListReady()
|
||||
{
|
||||
QTC_ASSERT(d->state == GatheringPorts, return);
|
||||
|
||||
d->portList = d->device->freePorts();
|
||||
startExecution();
|
||||
}
|
||||
|
||||
void LinuxDeviceDebugSupport::startExecution()
|
||||
{
|
||||
QTC_ASSERT(d->state == GatheringPorts, return);
|
||||
|
||||
if (d->cppDebugging && !setPort(d->gdbServerPort))
|
||||
return;
|
||||
if (d->qmlDebugging && !setPort(d->qmlPort))
|
||||
return;
|
||||
|
||||
d->state = StartingRunner;
|
||||
d->gdbserverOutput.clear();
|
||||
|
||||
connect(&d->appRunner, SIGNAL(remoteStderr(QByteArray)),
|
||||
SLOT(handleRemoteErrorOutput(QByteArray)));
|
||||
connect(&d->appRunner, SIGNAL(remoteStdout(QByteArray)), SLOT(handleRemoteOutput(QByteArray)));
|
||||
if (d->qmlDebugging && !d->cppDebugging)
|
||||
connect(&d->appRunner, SIGNAL(remoteProcessStarted()), SLOT(handleRemoteProcessStarted()));
|
||||
QString args = d->arguments;
|
||||
if (d->qmlDebugging)
|
||||
args += QString::fromLocal8Bit(" -qmljsdebugger=port:%1,block").arg(d->qmlPort);
|
||||
const QString remoteCommandLine = (d->qmlDebugging && !d->cppDebugging)
|
||||
? QString::fromLatin1("%1 %2 %3").arg(d->commandPrefix).arg(d->remoteFilePath).arg(args)
|
||||
: QString::fromLatin1("%1 gdbserver :%2 %3 %4").arg(d->commandPrefix)
|
||||
.arg(d->gdbServerPort).arg(d->remoteFilePath).arg(args);
|
||||
connect(&d->appRunner, SIGNAL(finished(bool)), SLOT(handleAppRunnerFinished(bool)));
|
||||
d->appRunner.start(d->device, remoteCommandLine.toUtf8());
|
||||
}
|
||||
|
||||
void LinuxDeviceDebugSupport::handleAppRunnerError(const QString &error)
|
||||
{
|
||||
if (d->state == Debugging) {
|
||||
showMessage(error, AppError);
|
||||
@@ -173,49 +229,7 @@ void AbstractRemoteLinuxDebugSupport::handleSshError(const QString &error)
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::startExecution()
|
||||
{
|
||||
if (d->state == Inactive)
|
||||
return;
|
||||
|
||||
QTC_ASSERT(d->state == StartingRunner, return);
|
||||
|
||||
if (d->cppDebugging && !setPort(d->gdbServerPort))
|
||||
return;
|
||||
if (d->qmlDebugging && !setPort(d->qmlPort))
|
||||
return;
|
||||
|
||||
d->state = StartingRemoteProcess;
|
||||
d->gdbserverOutput.clear();
|
||||
connect(runner(), SIGNAL(remoteErrorOutput(QByteArray)), this,
|
||||
SLOT(handleRemoteErrorOutput(QByteArray)));
|
||||
connect(runner(), SIGNAL(remoteOutput(QByteArray)), this,
|
||||
SLOT(handleRemoteOutput(QByteArray)));
|
||||
if (d->qmlDebugging && !d->cppDebugging) {
|
||||
connect(runner(), SIGNAL(remoteProcessStarted()),
|
||||
SLOT(handleRemoteProcessStarted()));
|
||||
}
|
||||
const QString &remoteExe = runner()->remoteExecutable();
|
||||
QString args = runner()->arguments();
|
||||
if (d->qmlDebugging) {
|
||||
args += QString::fromLatin1(" -qmljsdebugger=port:%1,block")
|
||||
.arg(d->qmlPort);
|
||||
}
|
||||
|
||||
const QHostAddress peerAddress = runner()->connection()->connectionInfo().peerAddress;
|
||||
QString peerAddressString = peerAddress.toString();
|
||||
if (peerAddress.protocol() == QAbstractSocket::IPv6Protocol)
|
||||
peerAddressString.prepend(QLatin1Char('[')).append(QLatin1Char(']'));
|
||||
const QString remoteCommandLine = (d->qmlDebugging && !d->cppDebugging)
|
||||
? QString::fromLatin1("%1 %2 %3").arg(runner()->commandPrefix()).arg(remoteExe).arg(args)
|
||||
: QString::fromLatin1("%1 gdbserver %5:%2 %3 %4").arg(runner()->commandPrefix())
|
||||
.arg(d->gdbServerPort).arg(remoteExe).arg(args).arg(peerAddressString);
|
||||
connect(runner(), SIGNAL(remoteProcessFinished(qint64)),
|
||||
SLOT(handleRemoteProcessFinished(qint64)));
|
||||
runner()->startExecution(remoteCommandLine.toUtf8());
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::handleRemoteProcessFinished(qint64 exitCode)
|
||||
void LinuxDeviceDebugSupport::handleAppRunnerFinished(bool success)
|
||||
{
|
||||
if (!d->engine || d->state == Inactive)
|
||||
return;
|
||||
@@ -224,39 +238,35 @@ void AbstractRemoteLinuxDebugSupport::handleRemoteProcessFinished(qint64 exitCod
|
||||
// The QML engine does not realize on its own that the application has finished.
|
||||
if (d->qmlDebugging && !d->cppDebugging)
|
||||
d->engine->quitDebugger();
|
||||
else if (exitCode != 0)
|
||||
else if (!success)
|
||||
d->engine->notifyInferiorIll();
|
||||
|
||||
} else {
|
||||
const QString errorMsg = (d->qmlDebugging && !d->cppDebugging)
|
||||
? tr("Remote application failed with exit code %1.").arg(exitCode)
|
||||
: tr("The gdbserver process closed unexpectedly.");
|
||||
d->engine->notifyEngineRemoteSetupFailed(errorMsg);
|
||||
d->engine->notifyEngineRemoteSetupFailed(tr("Debugging failed."));
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::handleDebuggingFinished()
|
||||
void LinuxDeviceDebugSupport::handleDebuggingFinished()
|
||||
{
|
||||
setFinished();
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::handleRemoteOutput(const QByteArray &output)
|
||||
void LinuxDeviceDebugSupport::handleRemoteOutput(const QByteArray &output)
|
||||
{
|
||||
QTC_ASSERT(d->state == Inactive || d->state == Debugging, return);
|
||||
|
||||
showMessage(QString::fromUtf8(output), AppOutput);
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::handleRemoteErrorOutput(const QByteArray &output)
|
||||
void LinuxDeviceDebugSupport::handleRemoteErrorOutput(const QByteArray &output)
|
||||
{
|
||||
QTC_ASSERT(d->state == Inactive || d->state == StartingRemoteProcess || d->state == Debugging,
|
||||
return);
|
||||
QTC_ASSERT(d->state != GatheringPorts, return);
|
||||
|
||||
if (!d->engine)
|
||||
return;
|
||||
|
||||
showMessage(QString::fromUtf8(output), AppOutput);
|
||||
if (d->state == StartingRemoteProcess && d->cppDebugging) {
|
||||
showMessage(QString::fromUtf8(output), AppError);
|
||||
if (d->state == StartingRunner && d->cppDebugging) {
|
||||
d->gdbserverOutput += output;
|
||||
if (d->gdbserverOutput.contains("Listening on port")) {
|
||||
handleAdapterSetupDone();
|
||||
@@ -265,42 +275,45 @@ void AbstractRemoteLinuxDebugSupport::handleRemoteErrorOutput(const QByteArray &
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::handleProgressReport(const QString &progressOutput)
|
||||
void LinuxDeviceDebugSupport::handleProgressReport(const QString &progressOutput)
|
||||
{
|
||||
showMessage(progressOutput + QLatin1Char('\n'), AppStuff);
|
||||
showMessage(progressOutput + QLatin1Char('\n'), LogStatus);
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::handleAdapterSetupFailed(const QString &error)
|
||||
void LinuxDeviceDebugSupport::handleAdapterSetupFailed(const QString &error)
|
||||
{
|
||||
setFinished();
|
||||
d->engine->notifyEngineRemoteSetupFailed(tr("Initial setup failed: %1").arg(error));
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::handleAdapterSetupDone()
|
||||
void LinuxDeviceDebugSupport::handleAdapterSetupDone()
|
||||
{
|
||||
d->state = Debugging;
|
||||
d->engine->notifyEngineRemoteSetupDone(d->gdbServerPort, d->qmlPort);
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::handleRemoteProcessStarted()
|
||||
void LinuxDeviceDebugSupport::handleRemoteProcessStarted()
|
||||
{
|
||||
Q_ASSERT(d->qmlDebugging && !d->cppDebugging);
|
||||
QTC_ASSERT(d->state == StartingRemoteProcess, return);
|
||||
QTC_ASSERT(d->qmlDebugging && !d->cppDebugging, return);
|
||||
QTC_ASSERT(d->state == StartingRunner, return);
|
||||
|
||||
handleAdapterSetupDone();
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxDebugSupport::setFinished()
|
||||
void LinuxDeviceDebugSupport::setFinished()
|
||||
{
|
||||
if (d->state == Inactive)
|
||||
return;
|
||||
d->portsGatherer.disconnect(this);
|
||||
d->appRunner.disconnect(this);
|
||||
if (d->state == StartingRunner)
|
||||
d->appRunner.stop(RemoteLinuxUtils::killApplicationCommandLine(d->remoteFilePath).toUtf8());
|
||||
d->state = Inactive;
|
||||
runner()->stop();
|
||||
}
|
||||
|
||||
bool AbstractRemoteLinuxDebugSupport::setPort(int &port)
|
||||
bool LinuxDeviceDebugSupport::setPort(int &port)
|
||||
{
|
||||
port = runner()->usedPortsGatherer()->getNextFreePort(runner()->freePorts());
|
||||
port = d->portsGatherer.getNextFreePort(&d->portList);
|
||||
if (port == -1) {
|
||||
handleAdapterSetupFailed(tr("Not enough free ports on device for debugging."));
|
||||
return false;
|
||||
@@ -308,22 +321,4 @@ bool AbstractRemoteLinuxDebugSupport::setPort(int &port)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
RemoteLinuxDebugSupport::RemoteLinuxDebugSupport(RemoteLinuxRunConfiguration *runConfig,
|
||||
DebuggerEngine *engine)
|
||||
: AbstractRemoteLinuxDebugSupport(runConfig, engine),
|
||||
d(new RemoteLinuxDebugSupportPrivate(runConfig))
|
||||
{
|
||||
}
|
||||
|
||||
RemoteLinuxDebugSupport::~RemoteLinuxDebugSupport()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
AbstractRemoteLinuxApplicationRunner *RemoteLinuxDebugSupport::runner() const
|
||||
{
|
||||
return &d->runner;
|
||||
}
|
||||
|
||||
} // namespace RemoteLinux
|
||||
|
@@ -40,65 +40,49 @@ class DebuggerStartParameters;
|
||||
}
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class RunControl;
|
||||
class DeviceApplicationHelperAction;
|
||||
class RunConfiguration;
|
||||
}
|
||||
|
||||
namespace RemoteLinux {
|
||||
class RemoteLinuxRunConfiguration;
|
||||
class AbstractRemoteLinuxApplicationRunner;
|
||||
|
||||
namespace Internal {
|
||||
class AbstractRemoteLinuxDebugSupportPrivate;
|
||||
class RemoteLinuxDebugSupportPrivate;
|
||||
} // namespace Internal
|
||||
namespace Internal { class LinuxDeviceDebugSupportPrivate; }
|
||||
|
||||
class REMOTELINUX_EXPORT AbstractRemoteLinuxDebugSupport : public QObject
|
||||
class REMOTELINUX_EXPORT LinuxDeviceDebugSupport : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(AbstractRemoteLinuxDebugSupport)
|
||||
public:
|
||||
static Debugger::DebuggerStartParameters startParameters(const RemoteLinuxRunConfiguration *runConfig);
|
||||
|
||||
AbstractRemoteLinuxDebugSupport(ProjectExplorer::RunConfiguration *runConfig,
|
||||
Debugger::DebuggerEngine *engine);
|
||||
~AbstractRemoteLinuxDebugSupport();
|
||||
LinuxDeviceDebugSupport(ProjectExplorer::RunConfiguration *runConfig,
|
||||
Debugger::DebuggerEngine *engine);
|
||||
~LinuxDeviceDebugSupport();
|
||||
|
||||
void setApplicationRunnerPreRunAction(ProjectExplorer::DeviceApplicationHelperAction *action);
|
||||
void setApplicationRunnerPostRunAction(ProjectExplorer::DeviceApplicationHelperAction *action);
|
||||
|
||||
private slots:
|
||||
void handleRemoteSetupRequested();
|
||||
void handleSshError(const QString &error);
|
||||
void handleAppRunnerError(const QString &error);
|
||||
void startExecution();
|
||||
void handleDebuggingFinished();
|
||||
void handleRemoteOutput(const QByteArray &output);
|
||||
void handleRemoteErrorOutput(const QByteArray &output);
|
||||
void handleProgressReport(const QString &progressOutput);
|
||||
void handleRemoteProcessStarted();
|
||||
void handleRemoteProcessFinished(qint64 exitCode);
|
||||
void handleAppRunnerFinished(bool success);
|
||||
void handlePortsGathererError(const QString &message);
|
||||
void handlePortListReady();
|
||||
|
||||
private:
|
||||
virtual AbstractRemoteLinuxApplicationRunner *runner() const = 0;
|
||||
|
||||
void handleAdapterSetupFailed(const QString &error);
|
||||
void handleAdapterSetupDone();
|
||||
void setFinished();
|
||||
bool setPort(int &port);
|
||||
void showMessage(const QString &msg, int channel);
|
||||
|
||||
Internal::AbstractRemoteLinuxDebugSupportPrivate * const d;
|
||||
};
|
||||
|
||||
|
||||
class REMOTELINUX_EXPORT RemoteLinuxDebugSupport : public AbstractRemoteLinuxDebugSupport
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RemoteLinuxDebugSupport(RemoteLinuxRunConfiguration *runConfig, Debugger::DebuggerEngine *engine);
|
||||
~RemoteLinuxDebugSupport();
|
||||
|
||||
private:
|
||||
AbstractRemoteLinuxApplicationRunner *runner() const;
|
||||
|
||||
Internal::RemoteLinuxDebugSupportPrivate * const d;
|
||||
Internal::LinuxDeviceDebugSupportPrivate * const d;
|
||||
};
|
||||
|
||||
} // namespace RemoteLinux
|
||||
|
@@ -29,10 +29,13 @@
|
||||
|
||||
#include "remotelinuxruncontrol.h"
|
||||
|
||||
#include "remotelinuxapplicationrunner.h"
|
||||
#include "remotelinuxrunconfiguration.h"
|
||||
#include "remotelinuxutils.h"
|
||||
|
||||
#include <projectexplorer/devicesupport/deviceapplicationrunner.h>
|
||||
#include <projectexplorer/profileinformation.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QString>
|
||||
@@ -42,120 +45,112 @@ using namespace ProjectExplorer;
|
||||
|
||||
namespace RemoteLinux {
|
||||
|
||||
using ProjectExplorer::RunConfiguration;
|
||||
|
||||
AbstractRemoteLinuxRunControl::AbstractRemoteLinuxRunControl(RunConfiguration *rc)
|
||||
: RunControl(rc, ProjectExplorer::NormalRunMode)
|
||||
, m_running(false)
|
||||
class RemoteLinuxRunControl::RemoteLinuxRunControlPrivate
|
||||
{
|
||||
}
|
||||
public:
|
||||
bool running;
|
||||
ProjectExplorer::DeviceApplicationRunner runner;
|
||||
IDevice::ConstPtr device;
|
||||
QString remoteExecutable;
|
||||
QString arguments;
|
||||
QString prefix;
|
||||
QByteArray stopCommand;
|
||||
};
|
||||
|
||||
AbstractRemoteLinuxRunControl::~AbstractRemoteLinuxRunControl()
|
||||
{
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxRunControl::start()
|
||||
{
|
||||
m_running = true;
|
||||
emit started();
|
||||
disconnect(runner(), 0, this, 0);
|
||||
connect(runner(), SIGNAL(error(QString)), SLOT(handleSshError(QString)));
|
||||
connect(runner(), SIGNAL(readyForExecution()), SLOT(startExecution()));
|
||||
connect(runner(), SIGNAL(remoteErrorOutput(QByteArray)),
|
||||
SLOT(handleRemoteErrorOutput(QByteArray)));
|
||||
connect(runner(), SIGNAL(remoteOutput(QByteArray)),
|
||||
SLOT(handleRemoteOutput(QByteArray)));
|
||||
connect(runner(), SIGNAL(remoteProcessStarted()),
|
||||
SLOT(handleRemoteProcessStarted()));
|
||||
connect(runner(), SIGNAL(remoteProcessFinished(qint64)),
|
||||
SLOT(handleRemoteProcessFinished(qint64)));
|
||||
connect(runner(), SIGNAL(reportProgress(QString)),
|
||||
SLOT(handleProgressReport(QString)));
|
||||
runner()->start();
|
||||
}
|
||||
|
||||
RunControl::StopResult AbstractRemoteLinuxRunControl::stop()
|
||||
{
|
||||
runner()->stop();
|
||||
return AsynchronousStop;
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxRunControl::handleSshError(const QString &error)
|
||||
{
|
||||
handleError(error);
|
||||
setFinished();
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxRunControl::startExecution()
|
||||
{
|
||||
appendMessage(tr("Starting remote process...\n"), Utils::NormalMessageFormat);
|
||||
runner()->startExecution(QString::fromLatin1("%1 %2 %3")
|
||||
.arg(runner()->commandPrefix())
|
||||
.arg(runner()->remoteExecutable())
|
||||
.arg(runner()->arguments()).toUtf8());
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxRunControl::handleRemoteProcessFinished(qint64 exitCode)
|
||||
{
|
||||
if (exitCode != AbstractRemoteLinuxApplicationRunner::InvalidExitCode) {
|
||||
appendMessage(tr("Finished running remote process. Exit code was %1.\n")
|
||||
.arg(exitCode), Utils::NormalMessageFormat);
|
||||
}
|
||||
setFinished();
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxRunControl::handleRemoteOutput(const QByteArray &output)
|
||||
{
|
||||
appendMessage(QString::fromUtf8(output), Utils::StdOutFormatSameLine);
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxRunControl::handleRemoteErrorOutput(const QByteArray &output)
|
||||
{
|
||||
appendMessage(QString::fromUtf8(output), Utils::StdErrFormatSameLine);
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxRunControl::handleProgressReport(const QString &progressString)
|
||||
{
|
||||
appendMessage(progressString + QLatin1Char('\n'), Utils::NormalMessageFormat);
|
||||
}
|
||||
|
||||
bool AbstractRemoteLinuxRunControl::isRunning() const
|
||||
{
|
||||
return m_running;
|
||||
}
|
||||
|
||||
QIcon AbstractRemoteLinuxRunControl::icon() const
|
||||
{
|
||||
return QIcon(ProjectExplorer::Constants::ICON_RUN_SMALL);
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxRunControl::handleError(const QString &errString)
|
||||
{
|
||||
stop();
|
||||
appendMessage(errString, Utils::ErrorMessageFormat);
|
||||
}
|
||||
|
||||
void AbstractRemoteLinuxRunControl::setFinished()
|
||||
{
|
||||
disconnect(runner(), 0, this, 0);
|
||||
m_running = false;
|
||||
emit finished();
|
||||
}
|
||||
|
||||
|
||||
RemoteLinuxRunControl::RemoteLinuxRunControl(ProjectExplorer::RunConfiguration *runConfig)
|
||||
: AbstractRemoteLinuxRunControl(runConfig),
|
||||
m_runner(new GenericRemoteLinuxApplicationRunner(qobject_cast<RemoteLinuxRunConfiguration *>(runConfig), this))
|
||||
RemoteLinuxRunControl::RemoteLinuxRunControl(RunConfiguration *rc)
|
||||
: RunControl(rc, ProjectExplorer::NormalRunMode), d(new RemoteLinuxRunControlPrivate)
|
||||
{
|
||||
d->running = false;
|
||||
d->device = DeviceProfileInformation::device(rc->target()->profile());
|
||||
const RemoteLinuxRunConfiguration * const lrc = qobject_cast<RemoteLinuxRunConfiguration *>(rc);
|
||||
d->remoteExecutable = lrc->remoteExecutableFilePath();
|
||||
d->arguments = lrc->arguments();
|
||||
d->prefix = lrc->commandPrefix();
|
||||
d->stopCommand = RemoteLinuxUtils::killApplicationCommandLine(d->remoteExecutable).toUtf8();
|
||||
}
|
||||
|
||||
RemoteLinuxRunControl::~RemoteLinuxRunControl()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
AbstractRemoteLinuxApplicationRunner *RemoteLinuxRunControl::runner() const
|
||||
void RemoteLinuxRunControl::start()
|
||||
{
|
||||
return m_runner;
|
||||
d->running = true;
|
||||
emit started();
|
||||
d->runner.disconnect(this);
|
||||
connect(&d->runner, SIGNAL(reportError(QString)), SLOT(handleErrorMessage(QString)));
|
||||
connect(&d->runner, SIGNAL(remoteStderr(QByteArray)),
|
||||
SLOT(handleRemoteErrorOutput(QByteArray)));
|
||||
connect(&d->runner, SIGNAL(remoteStdout(QByteArray)), SLOT(handleRemoteOutput(QByteArray)));
|
||||
connect(&d->runner, SIGNAL(finished(bool)), SLOT(handleRunnerFinished()));
|
||||
connect(&d->runner, SIGNAL(reportProgress(QString)), SLOT(handleProgressReport(QString)));
|
||||
const QString commandLine = QString::fromLatin1("%1 %2 %3")
|
||||
.arg(d->prefix, d->remoteExecutable, d->arguments);
|
||||
d->runner.start(d->device, commandLine.toUtf8());
|
||||
}
|
||||
|
||||
RunControl::StopResult RemoteLinuxRunControl::stop()
|
||||
{
|
||||
d->runner.stop(d->stopCommand);
|
||||
return AsynchronousStop;
|
||||
}
|
||||
|
||||
void RemoteLinuxRunControl::handleErrorMessage(const QString &error)
|
||||
{
|
||||
appendMessage(error, Utils::ErrorMessageFormat);
|
||||
}
|
||||
|
||||
void RemoteLinuxRunControl::handleRunnerFinished()
|
||||
{
|
||||
setFinished();
|
||||
}
|
||||
|
||||
void RemoteLinuxRunControl::handleRemoteOutput(const QByteArray &output)
|
||||
{
|
||||
appendMessage(QString::fromUtf8(output), Utils::StdOutFormatSameLine);
|
||||
}
|
||||
|
||||
void RemoteLinuxRunControl::handleRemoteErrorOutput(const QByteArray &output)
|
||||
{
|
||||
appendMessage(QString::fromUtf8(output), Utils::StdErrFormatSameLine);
|
||||
}
|
||||
|
||||
void RemoteLinuxRunControl::handleProgressReport(const QString &progressString)
|
||||
{
|
||||
appendMessage(progressString + QLatin1Char('\n'), Utils::NormalMessageFormat);
|
||||
}
|
||||
|
||||
bool RemoteLinuxRunControl::isRunning() const
|
||||
{
|
||||
return d->running;
|
||||
}
|
||||
|
||||
QIcon RemoteLinuxRunControl::icon() const
|
||||
{
|
||||
return QIcon(ProjectExplorer::Constants::ICON_RUN_SMALL);
|
||||
}
|
||||
|
||||
void RemoteLinuxRunControl::setApplicationRunnerPreRunAction(DeviceApplicationHelperAction *action)
|
||||
{
|
||||
d->runner.setPreRunAction(action);
|
||||
}
|
||||
|
||||
void RemoteLinuxRunControl::setApplicationRunnerPostRunAction(DeviceApplicationHelperAction *action)
|
||||
{
|
||||
d->runner.setPostRunAction(action);
|
||||
}
|
||||
|
||||
void RemoteLinuxRunControl::overrideStopCommandLine(const QByteArray &commandLine)
|
||||
{
|
||||
d->stopCommand = commandLine;
|
||||
}
|
||||
|
||||
void RemoteLinuxRunControl::setFinished()
|
||||
{
|
||||
d->runner.disconnect(this);
|
||||
d->running = false;
|
||||
emit finished();
|
||||
}
|
||||
|
||||
} // namespace RemoteLinux
|
||||
|
@@ -34,54 +34,38 @@
|
||||
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QString)
|
||||
namespace ProjectExplorer { class DeviceApplicationHelperAction; }
|
||||
|
||||
namespace RemoteLinux {
|
||||
class AbstractRemoteLinuxApplicationRunner;
|
||||
|
||||
class REMOTELINUX_EXPORT AbstractRemoteLinuxRunControl : public ProjectExplorer::RunControl
|
||||
class REMOTELINUX_EXPORT RemoteLinuxRunControl : public ProjectExplorer::RunControl
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(AbstractRemoteLinuxRunControl)
|
||||
public:
|
||||
explicit AbstractRemoteLinuxRunControl(ProjectExplorer::RunConfiguration *runConfig);
|
||||
virtual ~AbstractRemoteLinuxRunControl();
|
||||
explicit RemoteLinuxRunControl(ProjectExplorer::RunConfiguration *runConfig);
|
||||
virtual ~RemoteLinuxRunControl();
|
||||
|
||||
virtual void start();
|
||||
virtual StopResult stop();
|
||||
virtual bool isRunning() const;
|
||||
virtual QIcon icon() const;
|
||||
|
||||
virtual AbstractRemoteLinuxApplicationRunner *runner() const = 0;
|
||||
void setApplicationRunnerPreRunAction(ProjectExplorer::DeviceApplicationHelperAction *action);
|
||||
void setApplicationRunnerPostRunAction(ProjectExplorer::DeviceApplicationHelperAction *action);
|
||||
void overrideStopCommandLine(const QByteArray &commandLine);
|
||||
|
||||
private slots:
|
||||
void startExecution();
|
||||
void handleSshError(const QString &error);
|
||||
void handleRemoteProcessStarted() {}
|
||||
void handleRemoteProcessFinished(qint64 exitCode);
|
||||
void handleErrorMessage(const QString &error);
|
||||
void handleRunnerFinished();
|
||||
void handleRemoteOutput(const QByteArray &output);
|
||||
void handleRemoteErrorOutput(const QByteArray &output);
|
||||
void handleProgressReport(const QString &progressString);
|
||||
|
||||
private:
|
||||
void setFinished();
|
||||
void handleError(const QString &errString);
|
||||
|
||||
bool m_running;
|
||||
};
|
||||
|
||||
|
||||
class REMOTELINUX_EXPORT RemoteLinuxRunControl : public AbstractRemoteLinuxRunControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RemoteLinuxRunControl(ProjectExplorer::RunConfiguration *runConfig);
|
||||
virtual ~RemoteLinuxRunControl();
|
||||
private:
|
||||
virtual AbstractRemoteLinuxApplicationRunner *runner() const;
|
||||
|
||||
AbstractRemoteLinuxApplicationRunner * const m_runner;
|
||||
class RemoteLinuxRunControlPrivate;
|
||||
RemoteLinuxRunControlPrivate * const d;
|
||||
};
|
||||
|
||||
} // namespace RemoteLinux
|
||||
|
@@ -89,14 +89,14 @@ RunControl *RemoteLinuxRunControlFactory::create(RunConfiguration *runConfig, Ru
|
||||
if (mode == ProjectExplorer::NormalRunMode)
|
||||
return new RemoteLinuxRunControl(rc);
|
||||
|
||||
DebuggerStartParameters params = AbstractRemoteLinuxDebugSupport::startParameters(rc);
|
||||
DebuggerStartParameters params = LinuxDeviceDebugSupport::startParameters(rc);
|
||||
if (mode == ProjectExplorer::DebugRunModeWithBreakOnMain)
|
||||
params.breakOnMain = true;
|
||||
DebuggerRunControl * const runControl = DebuggerPlugin::createDebugger(params, rc);
|
||||
if (!runControl)
|
||||
return 0;
|
||||
RemoteLinuxDebugSupport *debugSupport =
|
||||
new RemoteLinuxDebugSupport(rc, runControl->engine());
|
||||
LinuxDeviceDebugSupport * const debugSupport =
|
||||
new LinuxDeviceDebugSupport(rc, runControl->engine());
|
||||
connect(runControl, SIGNAL(finished()), debugSupport, SLOT(handleDebuggingFinished()));
|
||||
return runControl;
|
||||
}
|
||||
|
@@ -41,9 +41,14 @@ using namespace ExtensionSystem;
|
||||
|
||||
namespace RemoteLinux {
|
||||
|
||||
QString RemoteLinuxUtils::deviceConfigurationName(const LinuxDeviceConfiguration::ConstPtr &devConf)
|
||||
QString RemoteLinuxUtils::killApplicationCommandLine(const QString &applicationFilePath)
|
||||
{
|
||||
return devConf ? devConf->displayName() : QCoreApplication::translate("RemoteLinux", "(No device)");
|
||||
return QString::fromLatin1("cd /proc; for pid in `ls -d [0123456789]*`; "
|
||||
"do "
|
||||
"if [ \"`readlink /proc/$pid/exe`\" = \"%1\" ]; then "
|
||||
" kill $pid; sleep 1; kill -9 $pid; "
|
||||
"fi; "
|
||||
"done").arg(applicationFilePath);
|
||||
}
|
||||
|
||||
} // namespace RemoteLinux
|
||||
|
@@ -40,7 +40,7 @@ class LinuxDeviceConfiguration;
|
||||
class REMOTELINUX_EXPORT RemoteLinuxUtils
|
||||
{
|
||||
public:
|
||||
static QString deviceConfigurationName(const QSharedPointer<const LinuxDeviceConfiguration> &devConf);
|
||||
static QString killApplicationCommandLine(const QString &applicationFilePath);
|
||||
};
|
||||
|
||||
} // namespace RemoteLinux
|
||||
|
Reference in New Issue
Block a user