Maemo: Get rid of MaemoDebugRunControl.

Use Debugger::DebuggerRunControl directly instead of wrapping it
into another RunControl.

Reviewed-by: hjk
This commit is contained in:
ck
2010-07-15 16:43:56 +02:00
parent db99f82863
commit 08bc6c0027
16 changed files with 536 additions and 337 deletions

View File

@@ -924,7 +924,8 @@ public slots:
QVariant configValue(const QString &name) const QVariant configValue(const QString &name) const
{ return settings()->value(name); } { return settings()->value(name); }
DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp); DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp,
ProjectExplorer::RunConfiguration *rc = 0);
void startDebugger(ProjectExplorer::RunControl *runControl); void startDebugger(ProjectExplorer::RunControl *runControl);
void displayDebugger(ProjectExplorer::RunControl *runControl); void displayDebugger(ProjectExplorer::RunControl *runControl);
@@ -1921,9 +1922,10 @@ void DebuggerPluginPrivate::showToolTip(ITextEditor *editor, const QPoint &point
} }
DebuggerRunControl * DebuggerRunControl *
DebuggerPluginPrivate::createDebugger(const DebuggerStartParameters &sp) DebuggerPluginPrivate::createDebugger(const DebuggerStartParameters &sp,
ProjectExplorer::RunConfiguration *rc)
{ {
return m_debuggerRunControlFactory->create(sp); return m_debuggerRunControlFactory->create(sp, rc);
} }
void DebuggerPluginPrivate::displayDebugger(ProjectExplorer::RunControl *rc) void DebuggerPluginPrivate::displayDebugger(ProjectExplorer::RunControl *rc)
@@ -2643,9 +2645,10 @@ QWidget *DebuggerPlugin::mainWindow() const
} }
DebuggerRunControl * DebuggerRunControl *
DebuggerPlugin::createDebugger(const DebuggerStartParameters &sp) DebuggerPlugin::createDebugger(const DebuggerStartParameters &sp,
ProjectExplorer::RunConfiguration *rc)
{ {
return instance()->d->createDebugger(sp); return instance()->d->createDebugger(sp, rc);
} }
void DebuggerPlugin::startDebugger(ProjectExplorer::RunControl *runControl) void DebuggerPlugin::startDebugger(ProjectExplorer::RunControl *runControl)

View File

@@ -44,6 +44,7 @@ class Snapshot;
} }
namespace ProjectExplorer { namespace ProjectExplorer {
class RunConfiguration;
class RunControl; class RunControl;
} }
@@ -82,7 +83,8 @@ public:
void readSettings(); void readSettings();
void writeSettings() const; void writeSettings() const;
static DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp); static DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp,
ProjectExplorer::RunConfiguration *rc = 0);
static void startDebugger(ProjectExplorer::RunControl *runControl); static void startDebugger(ProjectExplorer::RunControl *runControl);
static void displayDebugger(ProjectExplorer::RunControl *runControl); static void displayDebugger(ProjectExplorer::RunControl *runControl);

View File

@@ -179,7 +179,6 @@ static QByteArray parsePlainConsoleStream(const GdbResponse &response)
GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters) GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters)
: DebuggerEngine(startParameters) : DebuggerEngine(startParameters)
{ {
m_gdbAdapter = 0;
m_progress = 0; m_progress = 0;
m_commandTimer = new QTimer(this); m_commandTimer = new QTimer(this);
@@ -189,6 +188,7 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters)
// Needs no resetting in initializeVariables() // Needs no resetting in initializeVariables()
m_busy = false; m_busy = false;
initializeVariables(); initializeVariables();
m_gdbAdapter = createAdapter();
connect(theDebuggerAction(AutoDerefPointers), SIGNAL(valueChanged(QVariant)), connect(theDebuggerAction(AutoDerefPointers), SIGNAL(valueChanged(QVariant)),
this, SLOT(setAutoDerefPointers(QVariant))); this, SLOT(setAutoDerefPointers(QVariant)));
@@ -1754,7 +1754,6 @@ void GdbEngine::setupEngine()
//qDebug() << "GDB START DEBUGGER"; //qDebug() << "GDB START DEBUGGER";
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
QTC_ASSERT(m_debuggingHelperState == DebuggingHelperUninitialized, /**/); QTC_ASSERT(m_debuggingHelperState == DebuggingHelperUninitialized, /**/);
QTC_ASSERT(m_gdbAdapter == 0, /**/);
m_progress = new QFutureInterface<void>(); m_progress = new QFutureInterface<void>();
m_progress->setProgressRange(0, 100); m_progress->setProgressRange(0, 100);
@@ -1763,7 +1762,6 @@ void GdbEngine::setupEngine()
fp->setKeepOnFinish(false); fp->setKeepOnFinish(false);
m_progress->reportStarted(); m_progress->reportStarted();
m_gdbAdapter = createAdapter();
//qDebug() << "CREATED ADAPTER: " << m_gdbAdapter; //qDebug() << "CREATED ADAPTER: " << m_gdbAdapter;
if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) { if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) {

View File

@@ -83,13 +83,14 @@ enum DebuggingHelperState
}; };
class GdbEngine : public DebuggerEngine class DEBUGGER_EXPORT GdbEngine : public DebuggerEngine
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit GdbEngine(const DebuggerStartParameters &startParameters); explicit GdbEngine(const DebuggerStartParameters &startParameters);
~GdbEngine(); ~GdbEngine();
AbstractGdbAdapter *gdbAdapter() const { return m_gdbAdapter; }
private: private:
friend class AbstractGdbAdapter; friend class AbstractGdbAdapter;

View File

@@ -62,6 +62,8 @@ RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine, int toolChainT
this, SLOT(readUploadStandardOutput())); this, SLOT(readUploadStandardOutput()));
connect(&m_uploadProc, SIGNAL(readyReadStandardError()), connect(&m_uploadProc, SIGNAL(readyReadStandardError()),
this, SLOT(readUploadStandardError())); this, SLOT(readUploadStandardError()));
connect(&m_uploadProc, SIGNAL(finished(int)), this,
SLOT(uploadProcFinished()));
} }
AbstractGdbAdapter::DumperHandling RemoteGdbServerAdapter::dumperHandling() const AbstractGdbAdapter::DumperHandling RemoteGdbServerAdapter::dumperHandling() const
@@ -86,22 +88,13 @@ void RemoteGdbServerAdapter::startAdapter()
{ {
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
showMessage(_("TRYING TO START ADAPTER")); showMessage(_("TRYING TO START ADAPTER"));
// FIXME: make asynchroneous
// Start the remote server
if (startParameters().serverStartScript.isEmpty()) { if (startParameters().serverStartScript.isEmpty()) {
showMessage(_("No server start script given. " showMessage(_("No server start script given. "), StatusBar);
"Assuming server runs already."), StatusBar); emit requestSetup();
} else { } else {
m_uploadProc.start(_("/bin/sh ") + startParameters().serverStartScript); m_uploadProc.start(_("/bin/sh ") + startParameters().serverStartScript);
m_uploadProc.waitForStarted(); m_uploadProc.waitForStarted();
} }
if (!m_engine->startGdb(QStringList(), startParameters().debuggerCommand))
// FIXME: cleanup missing
return;
m_engine->handleAdapterStarted();
} }
void RemoteGdbServerAdapter::uploadProcError(QProcess::ProcessError error) void RemoteGdbServerAdapter::uploadProcError(QProcess::ProcessError error)
@@ -154,6 +147,15 @@ void RemoteGdbServerAdapter::readUploadStandardError()
showMessage(msg, AppError); showMessage(msg, AppError);
} }
void RemoteGdbServerAdapter::uploadProcFinished()
{
if (m_uploadProc.exitStatus() == QProcess::NormalExit
&& m_uploadProc.exitCode() == 0)
handleSetupDone();
else
handleSetupFailed(m_uploadProc.errorString());
}
void RemoteGdbServerAdapter::setupInferior() void RemoteGdbServerAdapter::setupInferior()
{ {
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
@@ -245,5 +247,20 @@ void RemoteGdbServerAdapter::shutdownAdapter()
m_engine->notifyAdapterShutdownOk(); m_engine->notifyAdapterShutdownOk();
} }
void RemoteGdbServerAdapter::handleSetupDone()
{
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
if (m_engine->startGdb(QStringList(), startParameters().debuggerCommand))
m_engine->handleAdapterStarted();
}
void RemoteGdbServerAdapter::handleSetupFailed(const QString &reason)
{
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
m_engine->handleAdapterStartFailed(reason);
}
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -43,12 +43,14 @@ namespace Internal {
// //
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
class RemoteGdbServerAdapter : public AbstractGdbAdapter class DEBUGGER_EXPORT RemoteGdbServerAdapter : public AbstractGdbAdapter
{ {
Q_OBJECT Q_OBJECT
public: public:
RemoteGdbServerAdapter(GdbEngine *engine, int toolChainType, QObject *parent = 0); RemoteGdbServerAdapter(GdbEngine *engine, int toolChainType, QObject *parent = 0);
void handleSetupDone();
void handleSetupFailed(const QString &reason);
private: private:
DumperHandling dumperHandling() const; DumperHandling dumperHandling() const;
@@ -62,9 +64,14 @@ private:
AbstractGdbProcess *gdbProc() { return &m_gdbProc; } AbstractGdbProcess *gdbProc() { return &m_gdbProc; }
signals:
void requestSetup();
private:
Q_SLOT void readUploadStandardOutput(); Q_SLOT void readUploadStandardOutput();
Q_SLOT void readUploadStandardError(); Q_SLOT void readUploadStandardError();
Q_SLOT void uploadProcError(QProcess::ProcessError error); Q_SLOT void uploadProcError(QProcess::ProcessError error);
Q_SLOT void uploadProcFinished();
void handleSetTargetAsync(const GdbResponse &response); void handleSetTargetAsync(const GdbResponse &response);
void handleFileExecAndSymbols(const GdbResponse &response); void handleFileExecAndSymbols(const GdbResponse &response);

View File

@@ -48,13 +48,7 @@ void RemotePlainGdbAdapter::startAdapter()
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
showMessage(QLatin1String("TRYING TO START ADAPTER")); showMessage(QLatin1String("TRYING TO START ADAPTER"));
if (!startParameters().workingDirectory.isEmpty()) emit requestSetup();
m_gdbProc.setWorkingDirectory(startParameters().workingDirectory);
if (!startParameters().environment.isEmpty())
m_gdbProc.setEnvironment(startParameters().environment);
if (m_engine->startGdb(QStringList(), m_engine->startParameters().debuggerCommand))
m_engine->handleAdapterStarted();
} }
void RemotePlainGdbAdapter::interruptInferior() void RemotePlainGdbAdapter::interruptInferior()
@@ -97,5 +91,25 @@ void RemotePlainGdbAdapter::shutdownAdapter()
m_engine->notifyAdapterShutdownOk(); m_engine->notifyAdapterShutdownOk();
} }
void RemotePlainGdbAdapter::handleSetupDone()
{
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
if (!startParameters().workingDirectory.isEmpty())
m_gdbProc.setWorkingDirectory(startParameters().workingDirectory);
if (!startParameters().environment.isEmpty())
m_gdbProc.setEnvironment(startParameters().environment);
if (m_engine->startGdb(QStringList(), m_engine->startParameters().debuggerCommand))
m_engine->handleAdapterStarted();
}
void RemotePlainGdbAdapter::handleSetupFailed(const QString &reason)
{
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
m_engine->handleAdapterStartFailed(reason);
}
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -36,13 +36,18 @@
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
class RemotePlainGdbAdapter : public AbstractPlainGdbAdapter class DEBUGGER_EXPORT RemotePlainGdbAdapter : public AbstractPlainGdbAdapter
{ {
Q_OBJECT Q_OBJECT
public: public:
friend class RemoteGdbProcess; friend class RemoteGdbProcess;
RemotePlainGdbAdapter(GdbEngine *engine, QObject *parent = 0); RemotePlainGdbAdapter(GdbEngine *engine, QObject *parent = 0);
void handleSetupDone();
void handleSetupFailed(const QString &reason);
signals:
void requestSetup();
private: private:
void startAdapter(); void startAdapter();

View File

@@ -0,0 +1,292 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Creator.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "maemodebugsupport.h"
#include "maemodeployables.h"
#include "maemodeploystep.h"
#include "maemoglobal.h"
#include "maemorunconfiguration.h"
#include "maemosshrunner.h"
#include <coreplugin/ssh/sftpchannel.h>
#include <debugger/debuggerengine.h>
#include <debugger/debuggerplugin.h>
#include <debugger/debuggerrunner.h>
#include <debugger/gdb/remotegdbserveradapter.h>
#include <debugger/gdb/remoteplaingdbadapter.h>
#include <projectexplorer/toolchain.h>
#include <QtCore/QFileInfo>
using namespace Core;
using namespace Debugger;
using namespace Debugger::Internal;
using namespace ProjectExplorer;
namespace Qt4ProjectManager {
namespace Internal {
RunControl *MaemoDebugSupport::createDebugRunControl(MaemoRunConfiguration *runConfig)
{
DebuggerStartParameters params;
const MaemoDeviceConfig &devConf = runConfig->deviceConfig();
#ifdef USE_GDBSERVER
params.startMode = AttachToRemote;
params.executable = runConfig->localExecutableFilePath();
params.debuggerCommand = runConfig->gdbCmd();
params.remoteChannel = devConf.server.host + QLatin1Char(':')
+ gdbServerPort(runConfig, devConf);
params.remoteArchitecture = QLatin1String("arm");
#else
params.startMode = StartRemoteGdb;
params.executable = runConfig->remoteExecutableFilePath();
params.debuggerCommand = MaemoGlobal::remoteCommandPrefix(runConfig->remoteExecutableFilePath())
+ QLatin1String(" /usr/bin/gdb");
params.connParams = devConf.server;
#endif
params.processArgs = runConfig->arguments();
params.sysRoot = runConfig->sysRoot();
params.toolChainType = ToolChain::GCC_MAEMO;
params.dumperLibrary = runConfig->dumperLib();
params.remoteDumperLib = uploadDir(devConf).toUtf8() + '/'
+ QFileInfo(runConfig->dumperLib()).fileName().toUtf8();
DebuggerRunControl * const debuggerRunControl
= DebuggerPlugin::createDebugger(params, runConfig);
new MaemoDebugSupport(runConfig, debuggerRunControl);
return debuggerRunControl;
}
MaemoDebugSupport::MaemoDebugSupport(MaemoRunConfiguration *runConfig,
DebuggerRunControl *runControl)
: QObject(runControl), m_runControl(runControl), m_runConfig(runConfig),
m_deviceConfig(m_runConfig->deviceConfig()),
m_runner(new MaemoSshRunner(this, m_runConfig))
{
GdbEngine *engine = qobject_cast<GdbEngine *>(m_runControl->engine());
Q_ASSERT(engine);
m_gdbAdapter = qobject_cast<GdbAdapter *>(engine->gdbAdapter());
Q_ASSERT(m_gdbAdapter);
connect(m_gdbAdapter, SIGNAL(requestSetup()), this,
SLOT(handleAdapterSetupRequested()));
connect(m_runControl, SIGNAL(finished()), this,
SLOT(handleDebuggingFinished()));
#ifdef USE_GDBSERVER
m_runner->addProcsToKill(QStringList() << QLatin1String("gdbserver"));
#else
m_runner->addProcsToKill(QStringList() << QLatin1String("gdb"));
#endif
}
MaemoDebugSupport::~MaemoDebugSupport() {}
void MaemoDebugSupport::handleAdapterSetupRequested()
{
if (!m_deviceConfig.isValid()) {
handleAdapterSetupFailed(tr("No device configuration set for run configuration."));
return;
}
m_adapterStarted = false;
m_stopped = false;
m_runControl->showMessage(tr("Preparing remote side ..."), AppStuff);
disconnect(m_runner, 0, this, 0);
connect(m_runner, SIGNAL(error(QString)), this,
SLOT(handleSshError(QString)));
connect(m_runner, SIGNAL(readyForExecution()), this,
SLOT(startExecution()));
m_runner->start();
}
void MaemoDebugSupport::handleSshError(const QString &error)
{
if (!m_stopped && !m_adapterStarted)
handleAdapterSetupFailed(error);
}
void MaemoDebugSupport::startExecution()
{
if (m_stopped)
return;
const QString &dumperLib = m_runConfig->dumperLib();
if (!dumperLib.isEmpty()
&& m_runConfig->deployStep()->currentlyNeedsDeployment(m_deviceConfig.server.host,
MaemoDeployable(dumperLib, uploadDir(m_deviceConfig)))) {
m_uploader = m_runner->connection()->createSftpChannel();
connect(m_uploader.data(), SIGNAL(initialized()), this,
SLOT(handleSftpChannelInitialized()));
connect(m_uploader.data(), SIGNAL(initializationFailed(QString)), this,
SLOT(handleSftpChannelInitializationFailed(QString)));
connect(m_uploader.data(), SIGNAL(finished(Core::SftpJobId, QString)),
this, SLOT(handleSftpJobFinished(Core::SftpJobId, QString)));
m_uploader->initialize();
} else {
startDebugging();
}
}
void MaemoDebugSupport::handleSftpChannelInitialized()
{
if (m_stopped)
return;
const QString dumperLib = m_runConfig->dumperLib();
const QString fileName = QFileInfo(dumperLib).fileName();
const QString remoteFilePath = uploadDir(m_deviceConfig) + '/' + fileName;
m_uploadJob = m_uploader->uploadFile(dumperLib, remoteFilePath,
SftpOverwriteExisting);
if (m_uploadJob == SftpInvalidJob) {
handleAdapterSetupFailed(tr("Upload failed: Could not open file '%1'")
.arg(dumperLib));
} else {
m_runControl->showMessage(tr("Started uploading debugging helpers ('%1').")
.arg(dumperLib), AppStuff);
}
}
void MaemoDebugSupport::handleSftpChannelInitializationFailed(const QString &error)
{
if (m_stopped)
return;
handleAdapterSetupFailed(error);
}
void MaemoDebugSupport::handleSftpJobFinished(Core::SftpJobId job,
const QString &error)
{
if (m_stopped)
return;
if (job != m_uploadJob) {
qWarning("Warning: Unknown debugging helpers upload job %d finished.", job);
return;
}
if (!error.isEmpty()) {
handleAdapterSetupFailed(tr("Could not upload debugging helpers: %1.")
.arg(error));
} else {
m_runConfig->deployStep()->setDeployed(m_deviceConfig.server.host,
MaemoDeployable(m_runConfig->dumperLib(), uploadDir(m_deviceConfig)));
m_runControl->showMessage(tr("Finished uploading debugging helpers."), AppStuff);
startDebugging();
}
m_uploadJob = SftpInvalidJob;
}
void MaemoDebugSupport::startDebugging()
{
#ifdef USE_GDBSERVER
connect(m_runner, SIGNAL(remoteErrorOutput(QByteArray)), this,
SLOT(handleRemoteErrorOutput(QByteArray)));
connect(m_runner, SIGNAL(remoteOutput(QByteArray)), this,
SLOT(handleRemoteOutput(QByteArray)));
connect(m_runner, SIGNAL(remoteProcessStarted()), this,
SLOT(handleRemoteProcessStarted()));
const QString &remoteExe = m_runConfig->remoteExecutableFilePath();
m_runner->startExecution(QString::fromLocal8Bit("%1 gdbserver :%2 %3 %4")
.arg(MaemoGlobal::remoteCommandPrefix(remoteExe))
.arg(gdbServerPort(m_runConfig, m_deviceConfig))
.arg(remoteExe).arg(m_runConfig->arguments()
.join(QLatin1String(" "))).toUtf8());
#else
stopSsh();
handleAdapterSetupDone();
#endif
}
void MaemoDebugSupport::handleRemoteProcessStarted()
{
handleAdapterSetupDone();
}
void MaemoDebugSupport::handleDebuggingFinished()
{
m_stopped = true;
stopSsh();
}
void MaemoDebugSupport::handleRemoteOutput(const QByteArray &output)
{
m_runControl->showMessage(QString::fromUtf8(output), AppOutput);
}
void MaemoDebugSupport::handleRemoteErrorOutput(const QByteArray &output)
{
m_runControl->showMessage(QString::fromUtf8(output), AppOutput);
}
void MaemoDebugSupport::stopSsh()
{
disconnect(m_runner, 0, this, 0);
if (m_uploader) {
disconnect(m_uploader.data(), 0, this, 0);
m_uploader->closeChannel();
}
m_runner->stop();
}
void MaemoDebugSupport::handleAdapterSetupFailed(const QString &error)
{
m_gdbAdapter->handleSetupFailed(tr("Initial setup failed: %1").arg(error));
m_stopped = true;
stopSsh();
}
void MaemoDebugSupport::handleAdapterSetupDone()
{
m_adapterStarted = true;
m_gdbAdapter->handleSetupDone();
}
QString MaemoDebugSupport::gdbServerPort(const MaemoRunConfiguration *rc,
const MaemoDeviceConfig &devConf)
{
// During configuration we don't know which port to use, so we display
// something in the config dialog, but we will make sure we use
// the right port from the information file.
return devConf.type == MaemoDeviceConfig::Physical
? QString::number(devConf.gdbServerPort)
: rc->runtimeGdbServerPort();
}
QString MaemoDebugSupport::uploadDir(const MaemoDeviceConfig &devConf)
{
return MaemoGlobal::homeDirOnDevice(devConf.server.uname);
}
} // namespace Internal
} // namespace Qt4ProjectManager

View File

@@ -0,0 +1,119 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Creator.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef MAEMODEBUGSUPPORT_H
#define MAEMODEBUGSUPPORT_H
#include "maemodeviceconfigurations.h"
#include <coreplugin/ssh/sftpdefs.h>
#include <QtCore/QObject>
#include <QtCore/QSharedPointer>
#define USE_GDBSERVER
namespace Core { class SftpChannel; }
namespace Debugger {
class DebuggerRunControl;
namespace Internal {
class RemoteGdbServerAdapter;
class RemotePlainGdbAdapter;
}
}
namespace ProjectExplorer { class RunControl; }
namespace Qt4ProjectManager {
namespace Internal {
class MaemoRunConfiguration;
class MaemoSshRunner;
class MaemoDebugSupport : public QObject
{
Q_OBJECT
public:
static ProjectExplorer::RunControl *createDebugRunControl(MaemoRunConfiguration *runConfig);
MaemoDebugSupport(MaemoRunConfiguration *runConfig,
Debugger::DebuggerRunControl *runControl);
~MaemoDebugSupport();
static QString gdbServerPort(const MaemoRunConfiguration *rc,
const MaemoDeviceConfig &devConf);
static QString uploadDir(const MaemoDeviceConfig &devConf);
private slots:
void handleAdapterSetupRequested();
void handleSshError(const QString &error);
void startExecution();
void handleSftpChannelInitialized();
void handleSftpChannelInitializationFailed(const QString &error);
void handleSftpJobFinished(Core::SftpJobId job, const QString &error);
void handleRemoteProcessStarted();
void handleDebuggingFinished();
void handleRemoteOutput(const QByteArray &output);
void handleRemoteErrorOutput(const QByteArray &output);
private:
void stopSsh();
void handleAdapterSetupFailed(const QString &error);
void handleAdapterSetupDone();
void startDebugging();
Debugger::DebuggerRunControl *m_runControl;
MaemoRunConfiguration * const m_runConfig;
const MaemoDeviceConfig m_deviceConfig;
MaemoSshRunner * const m_runner;
#ifdef USE_GDBSERVER
typedef Debugger::Internal::RemoteGdbServerAdapter GdbAdapter;
#else
typedef Debugger::Internal::RemotePlainGdbAdapter GdbAdapter;
#endif
GdbAdapter *m_gdbAdapter;
QSharedPointer<Core::SftpChannel> m_uploader;
Core::SftpJobId m_uploadJob;
bool m_adapterStarted;
bool m_stopped;
};
} // namespace Internal
} // namespace Qt4ProjectManager
#endif // MAEMODEBUGSUPPORT_H

View File

@@ -46,5 +46,11 @@ QString MaemoGlobal::remoteSudo()
return QLatin1String("/usr/lib/mad-developer/devrootsh"); return QLatin1String("/usr/lib/mad-developer/devrootsh");
} }
QString MaemoGlobal::remoteCommandPrefix(const QString &commandFilePath)
{
return QString::fromLocal8Bit("%1 chmod a+x %2 && source /etc/profile && DISPLAY=:0.0 ")
.arg(remoteSudo()).arg(commandFilePath);
}
} // namespace Internal } // namespace Internal
} // namespace Qt4ProjectManager } // namespace Qt4ProjectManager

View File

@@ -46,6 +46,7 @@ class MaemoGlobal
public: public:
static QString homeDirOnDevice(const QString &uname); static QString homeDirOnDevice(const QString &uname);
static QString remoteSudo(); static QString remoteSudo();
static QString remoteCommandPrefix(const QString &commandFilePath);
template<class T> static T *buildStep(const ProjectExplorer::BuildConfiguration *bc) template<class T> static T *buildStep(const ProjectExplorer::BuildConfiguration *bc)
{ {

View File

@@ -39,21 +39,10 @@
#include "maemorunconfiguration.h" #include "maemorunconfiguration.h"
#include "maemosshrunner.h" #include "maemosshrunner.h"
#include <coreplugin/icore.h>
#include <coreplugin/ssh/sftpchannel.h>
#include <coreplugin/ssh/sshconnection.h>
#include <debugger/debuggerengine.h>
#include <debugger/debuggerplugin.h>
#include <debugger/debuggerrunner.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchain.h> #include <projectexplorer/toolchain.h>
#include <qt4projectmanager/qt4buildconfiguration.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QtCore/QFileInfo>
#include <QtCore/QStringBuilder>
#include <QtGui/QMessageBox> #include <QtGui/QMessageBox>
using namespace Core; using namespace Core;
@@ -61,15 +50,11 @@ using namespace Core;
namespace Qt4ProjectManager { namespace Qt4ProjectManager {
namespace Internal { namespace Internal {
#define USE_GDBSERVER
using ProjectExplorer::RunConfiguration; using ProjectExplorer::RunConfiguration;
using ProjectExplorer::ToolChain; using ProjectExplorer::ToolChain;
using namespace Debugger;
MaemoRunControl::MaemoRunControl(RunConfiguration *rc)
AbstractMaemoRunControl::AbstractMaemoRunControl(RunConfiguration *rc, QString mode) : RunControl(rc, ProjectExplorer::Constants::RUNMODE)
: RunControl(rc, mode)
, m_runConfig(qobject_cast<MaemoRunConfiguration *>(rc)) , m_runConfig(qobject_cast<MaemoRunConfiguration *>(rc))
, m_devConfig(m_runConfig ? m_runConfig->deviceConfig() : MaemoDeviceConfig()) , m_devConfig(m_runConfig ? m_runConfig->deviceConfig() : MaemoDeviceConfig())
, m_runner(new MaemoSshRunner(this, m_runConfig)) , m_runner(new MaemoSshRunner(this, m_runConfig))
@@ -77,11 +62,12 @@ AbstractMaemoRunControl::AbstractMaemoRunControl(RunConfiguration *rc, QString m
{ {
} }
AbstractMaemoRunControl::~AbstractMaemoRunControl() MaemoRunControl::~MaemoRunControl()
{ {
stop();
} }
void AbstractMaemoRunControl::start() void MaemoRunControl::start()
{ {
if (!m_devConfig.isValid()) { if (!m_devConfig.isValid()) {
handleError(tr("No device configuration set for run configuration.")); handleError(tr("No device configuration set for run configuration."));
@@ -90,6 +76,7 @@ void AbstractMaemoRunControl::start()
m_running = true; m_running = true;
m_stopped = false; m_stopped = false;
emit started(); emit started();
disconnect(m_runner, 0, this, 0);
connect(m_runner, SIGNAL(error(QString)), this, connect(m_runner, SIGNAL(error(QString)), this,
SLOT(handleSshError(QString))); SLOT(handleSshError(QString)));
connect(m_runner, SIGNAL(readyForExecution()), this, connect(m_runner, SIGNAL(readyForExecution()), this,
@@ -106,29 +93,32 @@ void AbstractMaemoRunControl::start()
} }
} }
void AbstractMaemoRunControl::stop() void MaemoRunControl::stop()
{ {
m_stopped = true; m_stopped = true;
if (m_runner) if (m_runner) {
disconnect(m_runner, 0, this, 0);
m_runner->stop(); m_runner->stop();
stopInternal(); }
setFinished();
} }
void AbstractMaemoRunControl::handleSshError(const QString &error) void MaemoRunControl::handleSshError(const QString &error)
{ {
handleError(error); handleError(error);
setFinished(); setFinished();
} }
void AbstractMaemoRunControl::startExecution() void MaemoRunControl::startExecution()
{ {
emit appendMessage(this, tr("Starting remote process ..."), false); emit appendMessage(this, tr("Starting remote process ..."), false);
const QString &remoteExe = m_runConfig->remoteExecutableFilePath();
m_runner->startExecution(QString::fromLocal8Bit("%1 %2 %3") m_runner->startExecution(QString::fromLocal8Bit("%1 %2 %3")
.arg(targetCmdLinePrefix()).arg(m_runConfig->remoteExecutableFilePath()) .arg(MaemoGlobal::remoteCommandPrefix(remoteExe)).arg(remoteExe)
.arg(arguments()).toUtf8()); .arg(m_runConfig->arguments().join(QLatin1String(" "))).toUtf8());
} }
void AbstractMaemoRunControl::handleRemoteProcessFinished(int exitCode) void MaemoRunControl::handleRemoteProcessFinished(int exitCode)
{ {
if (m_stopped) if (m_stopped)
return; return;
@@ -139,232 +129,33 @@ void AbstractMaemoRunControl::handleRemoteProcessFinished(int exitCode)
setFinished(); setFinished();
} }
void AbstractMaemoRunControl::handleRemoteOutput(const QByteArray &output) void MaemoRunControl::handleRemoteOutput(const QByteArray &output)
{ {
emit addToOutputWindowInline(this, QString::fromUtf8(output), false); emit addToOutputWindowInline(this, QString::fromUtf8(output), false);
} }
void AbstractMaemoRunControl::handleRemoteErrorOutput(const QByteArray &output) void MaemoRunControl::handleRemoteErrorOutput(const QByteArray &output)
{ {
emit addToOutputWindowInline(this, QString::fromUtf8(output), true); emit addToOutputWindowInline(this, QString::fromUtf8(output), true);
} }
bool AbstractMaemoRunControl::isRunning() const bool MaemoRunControl::isRunning() const
{ {
return m_running; return m_running;
} }
const QString AbstractMaemoRunControl::targetCmdLinePrefix() const void MaemoRunControl::handleError(const QString &errString)
{
return QString::fromLocal8Bit("%1 chmod a+x %2 && source /etc/profile && DISPLAY=:0.0 ")
.arg(MaemoGlobal::remoteSudo())
.arg(m_runConfig->remoteExecutableFilePath());
}
QString AbstractMaemoRunControl::arguments() const
{
return m_runConfig->arguments().join(" ");
}
void AbstractMaemoRunControl::handleError(const QString &errString)
{ {
QMessageBox::critical(0, tr("Remote Execution Failure"), errString); QMessageBox::critical(0, tr("Remote Execution Failure"), errString);
emit appendMessage(this, errString, true); emit appendMessage(this, errString, true);
stop(); stop();
} }
void AbstractMaemoRunControl::setFinished() void MaemoRunControl::setFinished()
{ {
m_running = false; m_running = false;
emit finished(); emit finished();
} }
MaemoRunControl::MaemoRunControl(RunConfiguration *runConfiguration)
: AbstractMaemoRunControl(runConfiguration, ProjectExplorer::Constants::RUNMODE)
{
}
MaemoRunControl::~MaemoRunControl()
{
stop();
}
void MaemoRunControl::stopInternal()
{
setFinished();
}
MaemoDebugRunControl::MaemoDebugRunControl(RunConfiguration *runConfiguration)
: AbstractMaemoRunControl(runConfiguration, ProjectExplorer::Constants::DEBUGMODE)
, m_debuggerRunControl(0)
, m_startParams(new DebuggerStartParameters)
, m_uploadJob(SftpInvalidJob)
{
#ifdef USE_GDBSERVER
m_startParams->startMode = AttachToRemote;
m_startParams->executable = m_runConfig->localExecutableFilePath();
m_startParams->debuggerCommand = m_runConfig->gdbCmd();
m_startParams->remoteChannel
= m_devConfig.server.host % QLatin1Char(':') % gdbServerPort();
m_startParams->remoteArchitecture = QLatin1String("arm");
m_runner->addProcsToKill(QStringList() << QLatin1String("gdbserver"));
#else
m_startParams->startMode = StartRemoteGdb;
m_startParams->executable = m_runConfig->remoteExecutableFilePath();
m_startParams->debuggerCommand = targetCmdLinePrefix()
+ QLatin1String(" /usr/bin/gdb");
m_startParams->connParams = m_devConfig.server;
m_runner->addProcsToKill(QStringList() << QLatin1String("gdb"));
#endif
m_startParams->processArgs = m_runConfig->arguments();
m_startParams->sysRoot = m_runConfig->sysRoot();
m_startParams->toolChainType = ToolChain::GCC_MAEMO;
m_startParams->dumperLibrary = m_runConfig->dumperLib();
m_startParams->remoteDumperLib = uploadDir().toUtf8() + '/'
+ QFileInfo(m_runConfig->dumperLib()).fileName().toUtf8();
m_debuggerRunControl = DebuggerPlugin::createDebugger(*m_startParams.data());
connect(m_debuggerRunControl, SIGNAL(finished()), this,
SLOT(debuggingFinished()), Qt::QueuedConnection);
}
MaemoDebugRunControl::~MaemoDebugRunControl()
{
disconnect(SIGNAL(addToOutputWindow(ProjectExplorer::RunControl*,QString, bool)));
disconnect(SIGNAL(addToOutputWindowInline(ProjectExplorer::RunControl*,QString, bool)));
stop();
}
void MaemoDebugRunControl::startExecution()
{
const QString &dumperLib = m_runConfig->dumperLib();
if (!dumperLib.isEmpty()
&& m_runConfig->deployStep()->currentlyNeedsDeployment(m_devConfig.server.host,
MaemoDeployable(dumperLib, uploadDir()))) {
m_uploader = m_runner->connection()->createSftpChannel();
connect(m_uploader.data(), SIGNAL(initialized()), this,
SLOT(handleSftpChannelInitialized()));
connect(m_uploader.data(), SIGNAL(initializationFailed(QString)), this,
SLOT(handleSftpChannelInitializationFailed(QString)));
connect(m_uploader.data(), SIGNAL(finished(Core::SftpJobId, QString)),
this, SLOT(handleSftpJobFinished(Core::SftpJobId, QString)));
m_uploader->initialize();
} else {
startDebugging();
}
}
void MaemoDebugRunControl::handleSftpChannelInitialized()
{
if (m_stopped)
return;
const QString dumperLib = m_runConfig->dumperLib();
const QString fileName = QFileInfo(dumperLib).fileName();
const QString remoteFilePath = uploadDir() + '/' + fileName;
m_uploadJob = m_uploader->uploadFile(dumperLib, remoteFilePath,
SftpOverwriteExisting);
if (m_uploadJob == SftpInvalidJob) {
handleError(tr("Upload failed: Could not open file '%1'")
.arg(dumperLib));
} else {
emit appendMessage(this,
tr("Started uploading debugging helpers ('%1').").arg(dumperLib),
false);
}
}
void MaemoDebugRunControl::handleSftpChannelInitializationFailed(const QString &error)
{
handleError(error);
}
void MaemoDebugRunControl::handleSftpJobFinished(Core::SftpJobId job,
const QString &error)
{
if (m_stopped)
return;
if (job != m_uploadJob) {
qWarning("Warning: Unknown debugging helpers upload job %d finished.", job);
return;
}
if (!error.isEmpty()) {
handleError(tr("Error: Could not upload debugging helpers."));
} else {
m_runConfig->deployStep()->setDeployed(m_devConfig.server.host,
MaemoDeployable(m_runConfig->dumperLib(), uploadDir()));
emit appendMessage(this,
tr("Finished uploading debugging helpers."), false);
startDebugging();
}
}
void MaemoDebugRunControl::startDebugging()
{
#ifdef USE_GDBSERVER
m_runner->startExecution(QString::fromLocal8Bit("%1 gdbserver :%2 %3 %4")
.arg(targetCmdLinePrefix()).arg(gdbServerPort())
.arg(m_runConfig->remoteExecutableFilePath())
.arg(arguments()).toUtf8());
#else
DebuggerPlugin::startDebugger(m_debuggerRunControl);
#endif
}
bool MaemoDebugRunControl::isDeploying() const
{
return m_uploader && m_uploadJob != SftpInvalidJob;
}
void MaemoDebugRunControl::stopInternal()
{
if (isDeploying()) {
disconnect(m_uploader.data(), 0, this, 0);
m_uploader->closeChannel();
m_uploadJob = SftpInvalidJob;
setFinished();
} else if (m_debuggerRunControl && m_debuggerRunControl->engine()) {
m_debuggerRunControl->engine()->quitDebugger();
} else {
setFinished();
}
}
void MaemoDebugRunControl::debuggingFinished()
{
#ifdef USE_GDBSERVER
m_runner->stop();
#endif
setFinished();
}
void MaemoDebugRunControl::handleRemoteProcessStarted()
{
DebuggerPlugin::startDebugger(m_debuggerRunControl);
}
void MaemoDebugRunControl::debuggerOutput(const QString &output)
{
emit appendMessage(this, QLatin1String("[gdb says:] ") + output, true);
}
QString MaemoDebugRunControl::gdbServerPort() const
{
return m_devConfig.type == MaemoDeviceConfig::Physical
? QString::number(m_devConfig.gdbServerPort)
: m_runConfig->runtimeGdbServerPort(); // During configuration we don't
// know which port to use, so we display something in the config dialog,
// but we will make sure we use the right port from the information file.
}
QString MaemoDebugRunControl::uploadDir() const
{
return MaemoGlobal::homeDirOnDevice(m_devConfig.server.uname);
}
} // namespace Internal } // namespace Internal
} // namespace Qt4ProjectManager } // namespace Qt4ProjectManager

View File

@@ -37,105 +37,45 @@
#include "maemodeviceconfigurations.h" #include "maemodeviceconfigurations.h"
#include <coreplugin/ssh/sftpdefs.h>
#include <projectexplorer/runconfiguration.h> #include <projectexplorer/runconfiguration.h>
#include <QtCore/QString> #include <QtCore/QString>
namespace Core {
class SftpChannel;
class SshConnection;
class SshRemoteProcess;
}
namespace Debugger {
class DebuggerRunControl;
class DebuggerStartParameters;
} // namespace Debugger
namespace Qt4ProjectManager { namespace Qt4ProjectManager {
namespace Internal { namespace Internal {
class MaemoRunConfiguration; class MaemoRunConfiguration;
class MaemoSshRunner; class MaemoSshRunner;
class AbstractMaemoRunControl : public ProjectExplorer::RunControl class MaemoRunControl : public ProjectExplorer::RunControl
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AbstractMaemoRunControl(ProjectExplorer::RunConfiguration *runConfig, QString mode); explicit MaemoRunControl(ProjectExplorer::RunConfiguration *runConfig);
virtual ~AbstractMaemoRunControl(); virtual ~MaemoRunControl();
protected:
virtual void start();
virtual void stop();
void setFinished();
void handleError(const QString &errString);
const QString targetCmdLinePrefix() const;
QString arguments() const;
private slots: private slots:
virtual void startExecution(); void startExecution();
void handleSshError(const QString &error); void handleSshError(const QString &error);
virtual void handleRemoteProcessStarted() {} void handleRemoteProcessStarted() {}
void handleRemoteProcessFinished(int exitCode); void handleRemoteProcessFinished(int exitCode);
void handleRemoteOutput(const QByteArray &output); void handleRemoteOutput(const QByteArray &output);
void handleRemoteErrorOutput(const QByteArray &output); void handleRemoteErrorOutput(const QByteArray &output);
protected: private:
virtual void start();
virtual void stop();
virtual bool isRunning() const;
void setFinished();
void handleError(const QString &errString);
MaemoRunConfiguration *m_runConfig; // TODO this pointer can be invalid MaemoRunConfiguration *m_runConfig; // TODO this pointer can be invalid
const MaemoDeviceConfig m_devConfig; const MaemoDeviceConfig m_devConfig;
MaemoSshRunner * const m_runner; MaemoSshRunner * const m_runner;
bool m_stopped; bool m_stopped;
private:
virtual bool isRunning() const;
virtual void stopInternal()=0;
bool m_running; bool m_running;
}; };
class MaemoRunControl : public AbstractMaemoRunControl
{
Q_OBJECT
public:
explicit MaemoRunControl(ProjectExplorer::RunConfiguration *runConfiguration);
~MaemoRunControl();
private:
virtual void stopInternal();
};
class MaemoDebugRunControl : public AbstractMaemoRunControl
{
Q_OBJECT
public:
explicit MaemoDebugRunControl(ProjectExplorer::RunConfiguration *runConfiguration);
~MaemoDebugRunControl();
private slots:
virtual void handleRemoteProcessStarted();
void debuggerOutput(const QString &output);
void debuggingFinished();
void handleSftpChannelInitialized();
void handleSftpChannelInitializationFailed(const QString &error);
void handleSftpJobFinished(Core::SftpJobId job, const QString &error);
private:
virtual void stopInternal();
virtual void startExecution();
QString uploadDir() const;
QString gdbServerPort() const;
void startDebugging();
bool isDeploying() const;
Debugger::DebuggerRunControl *m_debuggerRunControl;
QSharedPointer<Debugger::DebuggerStartParameters> m_startParams;
QSharedPointer<Core::SftpChannel> m_uploader;
Core::SftpJobId m_uploadJob;
};
} // namespace Internal } // namespace Internal
} // namespace Qt4ProjectManager } // namespace Qt4ProjectManager

View File

@@ -35,6 +35,7 @@
#include "maemorunfactories.h" #include "maemorunfactories.h"
#include "maemoconstants.h" #include "maemoconstants.h"
#include "maemodebugsupport.h"
#include "maemorunconfiguration.h" #include "maemorunconfiguration.h"
#include "maemoruncontrol.h" #include "maemoruncontrol.h"
@@ -171,7 +172,7 @@ RunControl* MaemoRunControlFactory::create(RunConfiguration *runConfig,
|| mode == ProjectExplorer::Constants::DEBUGMODE); || mode == ProjectExplorer::Constants::DEBUGMODE);
if (mode == ProjectExplorer::Constants::RUNMODE) if (mode == ProjectExplorer::Constants::RUNMODE)
return new MaemoRunControl(rc); return new MaemoRunControl(rc);
return new MaemoDebugRunControl(rc); return MaemoDebugSupport::createDebugRunControl(rc);
} }
QString MaemoRunControlFactory::displayName() const QString MaemoRunControlFactory::displayName() const

View File

@@ -24,7 +24,8 @@ HEADERS += \
$$PWD/maemodeploystepwidget.h \ $$PWD/maemodeploystepwidget.h \
$$PWD/maemodeploystepfactory.h \ $$PWD/maemodeploystepfactory.h \
$$PWD/maemoglobal.h \ $$PWD/maemoglobal.h \
$$PWD/maemosshrunner.h $$PWD/maemosshrunner.h \
$$PWD/maemodebugsupport.h
SOURCES += \ SOURCES += \
$$PWD/maemoconfigtestdialog.cpp \ $$PWD/maemoconfigtestdialog.cpp \
@@ -50,7 +51,8 @@ SOURCES += \
$$PWD/maemodeploystepwidget.cpp \ $$PWD/maemodeploystepwidget.cpp \
$$PWD/maemodeploystepfactory.cpp \ $$PWD/maemodeploystepfactory.cpp \
$$PWD/maemoglobal.cpp \ $$PWD/maemoglobal.cpp \
$$PWD/maemosshrunner.cpp $$PWD/maemosshrunner.cpp \
$$PWD/maemodebugsupport.cpp
FORMS += \ FORMS += \
$$PWD/maemoconfigtestdialog.ui \ $$PWD/maemoconfigtestdialog.ui \