ProjectExplorer: Split Target and ToolRunners into smaller tasks

This increases re-usability of activities like 'port gathering',
and makes their use less dependent on actual device implementations.

Change-Id: I017cb74874f2b38c487ba2d03906a675d5618647
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
hjk
2017-05-09 10:25:11 +02:00
parent 9b93d5a330
commit 89f02cba2c
56 changed files with 1270 additions and 1843 deletions

View File

@@ -27,8 +27,11 @@
#include "utils_global.h" #include "utils_global.h"
#include "qtcassert.h" #include "qtcassert.h"
#include <limits>
#include <QMetaType> #include <QMetaType>
#include <QString>
#include <limits>
namespace Utils { namespace Utils {
@@ -50,6 +53,8 @@ public:
quint16 number() const { QTC_ASSERT(isValid(), return 0); return quint16(m_port); } quint16 number() const { QTC_ASSERT(isValid(), return 0); return quint16(m_port); }
bool isValid() const { return m_port != -1; } bool isValid() const { return m_port != -1; }
QString toString() const { return QString::number(m_port); }
private: private:
int m_port; int m_port;
}; };

View File

@@ -48,7 +48,8 @@ namespace Internal {
RunControl *AndroidAnalyzeSupport::createAnalyzeRunControl(RunConfiguration *runConfig, Core::Id runMode) RunControl *AndroidAnalyzeSupport::createAnalyzeRunControl(RunConfiguration *runConfig, Core::Id runMode)
{ {
RunControl *runControl = Debugger::createAnalyzerRunControl(runConfig, runMode); auto runControl = new RunControl(runConfig, runMode);
runControl->createWorker(runMode);
QTC_ASSERT(runControl, return 0); QTC_ASSERT(runControl, return 0);
AnalyzerConnection connection; AnalyzerConnection connection;
if (runMode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { if (runMode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) {
@@ -64,7 +65,7 @@ RunControl *AndroidAnalyzeSupport::createAnalyzeRunControl(RunConfiguration *run
} }
AndroidAnalyzeSupport::AndroidAnalyzeSupport(RunControl *runControl) AndroidAnalyzeSupport::AndroidAnalyzeSupport(RunControl *runControl)
: ToolRunner(runControl) : RunWorker(runControl)
{ {
auto runner = new AndroidRunner(this, runControl->runConfiguration(), runControl->runMode()); auto runner = new AndroidRunner(this, runControl->runConfiguration(), runControl->runMode());

View File

@@ -34,7 +34,7 @@
namespace Android { namespace Android {
namespace Internal { namespace Internal {
class AndroidAnalyzeSupport : public ProjectExplorer::ToolRunner class AndroidAnalyzeSupport : public ProjectExplorer::RunWorker
{ {
Q_OBJECT Q_OBJECT

View File

@@ -40,6 +40,7 @@ struct ANDROID_EXPORT AndroidRunnable
QVector<QStringList> afterFinishADBCommands; QVector<QStringList> afterFinishADBCommands;
QString deviceSerialNumber; QString deviceSerialNumber;
QString displayName() const { return packageName; }
static void *staticTypeId; static void *staticTypeId;
}; };

View File

@@ -71,8 +71,9 @@ namespace Internal {
ClangStaticAnalyzerToolRunner::ClangStaticAnalyzerToolRunner(RunControl *runControl, ClangStaticAnalyzerToolRunner::ClangStaticAnalyzerToolRunner(RunControl *runControl,
QString *errorMessage) QString *errorMessage)
: ToolRunner(runControl) : RunWorker(runControl)
{ {
setDisplayName("ClangStaticAnalyzerRunner");
runControl->setDisplayName(tr("Clang Static Analyzer")); runControl->setDisplayName(tr("Clang Static Analyzer"));
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR); runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
runControl->setSupportsReRunning(false); runControl->setSupportsReRunning(false);
@@ -585,7 +586,7 @@ void ClangStaticAnalyzerToolRunner::start()
return; return;
} }
reportSuccess(); reportStarted();
while (m_runners.size() < parallelRuns && !m_unitsToProcess.isEmpty()) while (m_runners.size() < parallelRuns && !m_unitsToProcess.isEmpty())
analyzeNextFile(); analyzeNextFile();

View File

@@ -47,7 +47,7 @@ struct AnalyzeUnit {
}; };
typedef QList<AnalyzeUnit> AnalyzeUnits; typedef QList<AnalyzeUnit> AnalyzeUnits;
class ClangStaticAnalyzerToolRunner : public ProjectExplorer::ToolRunner class ClangStaticAnalyzerToolRunner : public ProjectExplorer::RunWorker
{ {
Q_OBJECT Q_OBJECT

View File

@@ -145,7 +145,7 @@ ClangStaticAnalyzerTool::ClangStaticAnalyzerTool()
{{ClangStaticAnalyzerDockId, m_diagnosticView, {}, Perspective::SplitVertical}} {{ClangStaticAnalyzerDockId, m_diagnosticView, {}, Perspective::SplitVertical}}
)); ));
Debugger::registerAction(Constants::CLANGSTATICANALYZER_RUN_MODE, {}); //Debugger::registerAction(Constants::CLANGSTATICANALYZER_RUN_MODE, {});
action = new QAction(tr("Clang Static Analyzer"), this); action = new QAction(tr("Clang Static Analyzer"), this);
action->setToolTip(toolTip); action->setToolTip(toolTip);
menu->addAction(ActionManager::registerAction(action, "ClangStaticAnalyzer.Action"), menu->addAction(ActionManager::registerAction(action, "ClangStaticAnalyzer.Action"),

View File

@@ -59,16 +59,12 @@ enum ToolMode {
//AnyMode = DebugMode | ProfileMode | ReleaseMode //AnyMode = DebugMode | ProfileMode | ReleaseMode
}; };
using RunControlCreator = std::function<ProjectExplorer::RunControl *
(ProjectExplorer::RunConfiguration *runConfiguration, Core::Id runMode)>;
// FIXME: Merge with something sensible. // FIXME: Merge with something sensible.
DEBUGGER_EXPORT bool wantRunTool(ToolMode toolMode, const QString &toolName); DEBUGGER_EXPORT bool wantRunTool(ToolMode toolMode, const QString &toolName);
DEBUGGER_EXPORT void showCannotStartDialog(const QString &toolName); DEBUGGER_EXPORT void showCannotStartDialog(const QString &toolName);
DEBUGGER_EXPORT ProjectExplorer::RunConfiguration *startupRunConfiguration(); DEBUGGER_EXPORT ProjectExplorer::RunConfiguration *startupRunConfiguration();
// Register a tool for a given start mode. // Register a tool for a given start mode.
DEBUGGER_EXPORT void registerAction(Core::Id runMode, const RunControlCreator &runControlCreator);
DEBUGGER_EXPORT void registerPerspective(const QByteArray &perspectiveId, const Utils::Perspective *perspective); DEBUGGER_EXPORT void registerPerspective(const QByteArray &perspectiveId, const Utils::Perspective *perspective);
DEBUGGER_EXPORT void registerToolbar(const QByteArray &perspectiveId, const Utils::ToolbarDescription &desc); DEBUGGER_EXPORT void registerToolbar(const QByteArray &perspectiveId, const Utils::ToolbarDescription &desc);
@@ -85,7 +81,4 @@ DEBUGGER_EXPORT void showPermanentStatusMessage(const QString &message);
DEBUGGER_EXPORT QAction *createStartAction(); DEBUGGER_EXPORT QAction *createStartAction();
DEBUGGER_EXPORT QAction *createStopAction(); DEBUGGER_EXPORT QAction *createStopAction();
DEBUGGER_EXPORT ProjectExplorer::RunControl *createAnalyzerRunControl(
ProjectExplorer::RunConfiguration *runConfiguration, Core::Id runMode);
} // namespace Debugger } // namespace Debugger

View File

@@ -561,7 +561,7 @@ void DebuggerEngine::setRunTool(DebuggerRunTool *runTool)
d->m_runTool = runTool; d->m_runTool = runTool;
} }
void DebuggerEngine::prepare() void DebuggerEngine::start()
{ {
QTC_ASSERT(d->m_runTool, notifyEngineSetupFailed(); return); QTC_ASSERT(d->m_runTool, notifyEngineSetupFailed(); return);
@@ -602,25 +602,7 @@ void DebuggerEngine::prepare()
} }
d->queueSetupEngine(); d->queueSetupEngine();
}
void DebuggerEngine::start()
{
Internal::runControlStarted(this);
// We might get a synchronous startFailed() notification on Windows,
// when launching the process fails. Emit a proper finished() sequence.
//runControl()->reportApplicationStart();
showMessage("QUEUE: SETUP INFERIOR");
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
// if (isMasterEngine())
d->queueSetupInferior();
}
void DebuggerEngine::startDebugger()
{
d->queueRunEngine();
} }
void DebuggerEngine::resetLocation() void DebuggerEngine::resetLocation()
@@ -822,7 +804,9 @@ void DebuggerEngine::notifyEngineSetupOk()
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
setState(EngineSetupOk); setState(EngineSetupOk);
runTool()->reportSuccess();
Internal::runControlStarted(this);
d->queueSetupInferior();
} }
void DebuggerEngine::setupSlaveInferior() void DebuggerEngine::setupSlaveInferior()
@@ -1313,6 +1297,11 @@ void DebuggerEngine::setState(DebuggerState state, bool forced)
DebuggerToolTipManager::registerEngine(this); DebuggerToolTipManager::registerEngine(this);
} }
if (state == InferiorUnrunnable || state == InferiorRunOk) {
if (isMasterEngine() && runTool())
runTool()->reportStarted();
}
if (state == DebuggerFinished) { if (state == DebuggerFinished) {
// Give up ownership on claimed breakpoints. // Give up ownership on claimed breakpoints.
foreach (Breakpoint bp, breakHandler()->engineBreakpoints(this)) foreach (Breakpoint bp, breakHandler()->engineBreakpoints(this))

View File

@@ -202,11 +202,8 @@ public:
virtual void setRunTool(DebuggerRunTool *runTool); virtual void setRunTool(DebuggerRunTool *runTool);
DebuggerRunTool *runTool() const; DebuggerRunTool *runTool() const;
void prepare();
void start(); void start();
void startDebugger();
enum { enum {
// Remove need to qualify each use. // Remove need to qualify each use.
NeedsTemporaryStop = DebuggerCommand::NeedsTemporaryStop, NeedsTemporaryStop = DebuggerCommand::NeedsTemporaryStop,

View File

@@ -973,7 +973,6 @@ public:
QPointer<QWidget> m_modeWindow; QPointer<QWidget> m_modeWindow;
QPointer<DebugMode> m_mode; QPointer<DebugMode> m_mode;
QHash<Id, RunControlCreator> m_runControlCreators;
ActionContainer *m_menu = 0; ActionContainer *m_menu = 0;
// DockWidgetEventFilter m_resizeEventFilter; // DockWidgetEventFilter m_resizeEventFilter;
@@ -3527,11 +3526,6 @@ bool wantRunTool(ToolMode toolMode, const QString &toolName)
return true; return true;
} }
void registerAction(Id runMode, const RunControlCreator &runControlCreator)
{
dd->m_runControlCreators.insert(runMode, runControlCreator);
}
void registerToolbar(const QByteArray &perspectiveId, const ToolbarDescription &desc) void registerToolbar(const QByteArray &perspectiveId, const ToolbarDescription &desc)
{ {
auto toolbar = new QWidget; auto toolbar = new QWidget;
@@ -3605,14 +3599,6 @@ void showPermanentStatusMessage(const QString &message)
dd->m_mainWindow->showStatusMessage(message, -1); dd->m_mainWindow->showStatusMessage(message, -1);
} }
RunControl *createAnalyzerRunControl(RunConfiguration *runConfiguration, Id runMode)
{
RunControlCreator rcc = dd->m_runControlCreators.value(runMode);
if (rcc)
return rcc(runConfiguration, runMode);
return nullptr;
}
namespace Internal { namespace Internal {
static bool s_testRun = false; static bool s_testRun = false;

View File

@@ -109,19 +109,15 @@ static QLatin1String engineTypeName(DebuggerEngineType et)
return QLatin1String("No engine"); return QLatin1String("No engine");
} }
void DebuggerRunTool::prepare() void DebuggerRunTool::start()
{ {
Debugger::Internal::saveModeToRestore(); Debugger::Internal::saveModeToRestore();
Debugger::selectPerspective(Debugger::Constants::CppPerspectiveId); Debugger::selectPerspective(Debugger::Constants::CppPerspectiveId);
TaskHub::clearTasks(Debugger::Constants::TASK_CATEGORY_DEBUGGER_DEBUGINFO); TaskHub::clearTasks(Debugger::Constants::TASK_CATEGORY_DEBUGGER_DEBUGINFO);
TaskHub::clearTasks(Debugger::Constants::TASK_CATEGORY_DEBUGGER_RUNTIME); TaskHub::clearTasks(Debugger::Constants::TASK_CATEGORY_DEBUGGER_RUNTIME);
m_engine->prepare();
}
void DebuggerRunTool::start()
{
DebuggerEngine *engine = m_engine; DebuggerEngine *engine = m_engine;
QTC_ASSERT(engine, return); QTC_ASSERT(engine, return);
const DebuggerRunParameters &rp = engine->runParameters(); const DebuggerRunParameters &rp = engine->runParameters();
// User canceled input dialog asking for executable when working on library project. // User canceled input dialog asking for executable when working on library project.
@@ -177,11 +173,6 @@ void DebuggerRunTool::notifyEngineRemoteSetupFinished(const RemoteSetupResult &r
m_engine->notifyEngineRemoteSetupFinished(result); m_engine->notifyEngineRemoteSetupFinished(result);
} }
void DebuggerRunTool::setRemoteParameters(const RemoteSetupResult &result)
{
m_engine->setRemoteParameters(result);
}
void DebuggerRunTool::stop() void DebuggerRunTool::stop()
{ {
m_engine->quitDebugger(); m_engine->quitDebugger();
@@ -199,7 +190,7 @@ void DebuggerRunTool::onTargetFailure()
void DebuggerRunTool::debuggingFinished() void DebuggerRunTool::debuggingFinished()
{ {
runControl()->reportApplicationStop(); reportStopped();
} }
DebuggerStartParameters &DebuggerRunTool::startParameters() DebuggerStartParameters &DebuggerRunTool::startParameters()
@@ -495,10 +486,11 @@ static DebuggerRunConfigurationAspect *debuggerAspect(const RunControl *runContr
/// DebuggerRunTool /// DebuggerRunTool
DebuggerRunTool::DebuggerRunTool(RunControl *runControl) DebuggerRunTool::DebuggerRunTool(RunControl *runControl)
: ToolRunner(runControl), : RunWorker(runControl),
m_isCppDebugging(debuggerAspect(runControl)->useCppDebugger()), m_isCppDebugging(debuggerAspect(runControl)->useCppDebugger()),
m_isQmlDebugging(debuggerAspect(runControl)->useQmlDebugger()) m_isQmlDebugging(debuggerAspect(runControl)->useQmlDebugger())
{ {
setDisplayName("DebuggerRunTool");
} }
DebuggerRunTool::DebuggerRunTool(RunControl *runControl, const DebuggerStartParameters &sp, QString *errorMessage) DebuggerRunTool::DebuggerRunTool(RunControl *runControl, const DebuggerStartParameters &sp, QString *errorMessage)
@@ -577,7 +569,7 @@ DebuggerRunTool::~DebuggerRunTool()
void DebuggerRunTool::onFinished() void DebuggerRunTool::onFinished()
{ {
appendMessage(tr("Debugging has finished") + '\n', NormalMessageFormat); appendMessage(tr("Debugging has finished"), NormalMessageFormat);
runControlFinished(m_engine); runControlFinished(m_engine);
} }
@@ -619,8 +611,9 @@ public:
QTC_ASSERT(runConfig, return 0); QTC_ASSERT(runConfig, return 0);
QTC_ASSERT(mode == DebugRunMode || mode == DebugRunModeWithBreakOnMain, return 0); QTC_ASSERT(mode == DebugRunMode || mode == DebugRunModeWithBreakOnMain, return 0);
DebuggerStartParameters sp;
auto runControl = new RunControl(runConfig, mode); auto runControl = new RunControl(runConfig, mode);
(void) new DebuggerRunTool(runControl, DebuggerStartParameters(), errorMessage); (void) new DebuggerRunTool(runControl, sp, errorMessage);
return runControl; return runControl;
} }
@@ -690,10 +683,109 @@ RunControl *createAndScheduleRun(const DebuggerRunParameters &rp, Kit *kit)
QTC_ASSERT(runConfig, return nullptr); QTC_ASSERT(runConfig, return nullptr);
auto runControl = new RunControl(runConfig, DebugRunMode); auto runControl = new RunControl(runConfig, DebugRunMode);
(void) new DebuggerRunTool(runControl, rp); (void) new DebuggerRunTool(runControl, rp);
QTC_ASSERT(runControl, return nullptr);
ProjectExplorerPlugin::startRunControl(runControl); ProjectExplorerPlugin::startRunControl(runControl);
return runControl; return runControl;
} }
} // Internal } // Internal
// GdbServerPortGatherer
GdbServerPortsGatherer::GdbServerPortsGatherer(RunControl *runControl)
: RunWorker(runControl)
{
}
GdbServerPortsGatherer::~GdbServerPortsGatherer()
{
}
void GdbServerPortsGatherer::start()
{
appendMessage(tr("Checking available ports..."), NormalMessageFormat);
connect(&m_portsGatherer, &DeviceUsedPortsGatherer::error, this, [this](const QString &msg) {
reportFailure(msg);
});
connect(&m_portsGatherer, &DeviceUsedPortsGatherer::portListReady, this, [this] {
Utils::PortList portList = device()->freePorts();
appendMessage(tr("Found %1 free ports").arg(portList.count()), NormalMessageFormat);
if (m_useGdbServer) {
m_gdbServerPort = m_portsGatherer.getNextFreePort(&portList);
if (!m_gdbServerPort.isValid()) {
reportFailure(tr("Not enough free ports on device for C++ debugging."));
return;
}
}
if (m_useQmlServer) {
m_qmlServerPort = m_portsGatherer.getNextFreePort(&portList);
if (!m_qmlServerPort.isValid()) {
reportFailure(tr("Not enough free ports on device for QML debugging."));
return;
}
}
reportStarted();
});
m_portsGatherer.start(device());
}
// GdbServerRunner
GdbServerRunner::GdbServerRunner(RunControl *runControl)
: RunWorker(runControl)
{
setDisplayName("GdbServerRunner");
}
GdbServerRunner::~GdbServerRunner()
{
}
void GdbServerRunner::start()
{
auto portsGatherer = runControl()->worker<GdbServerPortsGatherer>();
QTC_ASSERT(portsGatherer, reportFailure(); return);
StandardRunnable r = runnable().as<StandardRunnable>();
QStringList args = QtcProcess::splitArgs(r.commandLineArguments, OsTypeLinux);
QString command;
const bool isQmlDebugging = portsGatherer->useQmlServer();
const bool isCppDebugging = portsGatherer->useGdbServer();
if (isQmlDebugging) {
args.prepend(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices,
portsGatherer->qmlServerPort()));
}
if (isQmlDebugging && !isCppDebugging) {
command = r.executable;
} else {
command = device()->debugServerPath();
if (command.isEmpty())
command = "gdbserver";
args.clear();
args.append(QString("--multi"));
args.append(QString(":%1").arg(portsGatherer->gdbServerPort().number()));
}
r.executable = command;
r.commandLineArguments = QtcProcess::joinArgs(args, OsTypeLinux);
connect(&m_gdbServer, &ApplicationLauncher::error, this, [this] {
reportFailure(tr("GDBserver start failed"));
});
connect(&m_gdbServer, &ApplicationLauncher::remoteProcessStarted, this, [this] {
appendMessage(tr("GDBserver started") + '\n', NormalMessageFormat);
reportStarted();
});
appendMessage(tr("Starting GDBserver...") + '\n', NormalMessageFormat);
m_gdbServer.start(r, device());
}
void GdbServerRunner::onFinished()
{
m_gdbServer.stop();
}
} // namespace Debugger } // namespace Debugger

View File

@@ -30,13 +30,14 @@
#include "debuggerengine.h" #include "debuggerengine.h"
#include <projectexplorer/runconfiguration.h> #include <projectexplorer/runconfiguration.h>
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
namespace Debugger { namespace Debugger {
class RemoteSetupResult; class RemoteSetupResult;
class DebuggerStartParameters; class DebuggerStartParameters;
class DEBUGGER_EXPORT DebuggerRunTool : public ProjectExplorer::ToolRunner class DEBUGGER_EXPORT DebuggerRunTool : public ProjectExplorer::RunWorker
{ {
Q_OBJECT Q_OBJECT
@@ -60,16 +61,14 @@ public:
void showMessage(const QString &msg, int channel = LogDebug, int timeout = -1); void showMessage(const QString &msg, int channel = LogDebug, int timeout = -1);
void prepare() override;
void start() override; void start() override;
void stop() override; void stop() override;
void onTargetFailure() override;
void onFinished() override; void onFinished() override;
void startFailed(); void startFailed();
void onTargetFailure();
void notifyEngineRemoteServerRunning(const QByteArray &msg, int pid); void notifyEngineRemoteServerRunning(const QByteArray &msg, int pid);
void notifyEngineRemoteSetupFinished(const RemoteSetupResult &result); void notifyEngineRemoteSetupFinished(const RemoteSetupResult &result);
void setRemoteParameters(const RemoteSetupResult &result);
void notifyInferiorIll(); void notifyInferiorIll();
Q_SLOT void notifyInferiorExited(); Q_SLOT void notifyInferiorExited();
void quitDebugger(); void quitDebugger();
@@ -97,4 +96,48 @@ private:
const bool m_isQmlDebugging; const bool m_isQmlDebugging;
}; };
class DEBUGGER_EXPORT GdbServerPortsGatherer : public ProjectExplorer::RunWorker
{
Q_OBJECT
public:
explicit GdbServerPortsGatherer(ProjectExplorer::RunControl *runControl);
~GdbServerPortsGatherer();
void setUseGdbServer(bool useIt) { m_useGdbServer = useIt; }
bool useGdbServer() const { return m_useGdbServer; }
Utils::Port gdbServerPort() const { return m_gdbServerPort; }
void setUseQmlServer(bool useIt) { m_useQmlServer = useIt; }
bool useQmlServer() const { return m_useQmlServer; }
Utils::Port qmlServerPort() const { return m_qmlServerPort; }
private:
void start();
ProjectExplorer::DeviceUsedPortsGatherer m_portsGatherer;
bool m_useGdbServer = false;
bool m_useQmlServer = false;
Utils::Port m_gdbServerPort;
Utils::Port m_qmlServerPort;
};
class DEBUGGER_EXPORT GdbServerRunner : public ProjectExplorer::RunWorker
{
Q_OBJECT
public:
explicit GdbServerRunner(ProjectExplorer::RunControl *runControl);
~GdbServerRunner();
private:
void start() override;
void onFinished() override;
ProjectExplorer::ApplicationLauncher m_gdbServer;
};
extern DEBUGGER_EXPORT const char GdbServerRunnerWorkerId[];
extern DEBUGGER_EXPORT const char GdbServerPortGathererWorkerId[];
} // namespace Debugger } // namespace Debugger

View File

@@ -32,7 +32,7 @@ namespace Ios {
namespace Internal { namespace Internal {
IosAnalyzeSupport::IosAnalyzeSupport(RunControl *runControl, bool cppDebug, bool qmlDebug) IosAnalyzeSupport::IosAnalyzeSupport(RunControl *runControl, bool cppDebug, bool qmlDebug)
: ToolRunner(runControl), : RunWorker(runControl),
m_runner(new IosRunner(this, runControl, cppDebug, qmlDebug ? QmlDebug::QmlProfilerServices : m_runner(new IosRunner(this, runControl, cppDebug, qmlDebug ? QmlDebug::QmlProfilerServices :
QmlDebug::NoQmlDebugServices)) QmlDebug::NoQmlDebugServices))
{ {

View File

@@ -34,7 +34,7 @@ namespace Internal {
class IosRunner; class IosRunner;
class IosAnalyzeSupport : public ProjectExplorer::ToolRunner class IosAnalyzeSupport : public ProjectExplorer::RunWorker
{ {
Q_OBJECT Q_OBJECT

View File

@@ -184,11 +184,8 @@ RunControl *IosRunControlFactory::create(RunConfiguration *runConfig,
if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE) if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE)
res = new Ios::Internal::IosRunControl(rc); res = new Ios::Internal::IosRunControl(rc);
else if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { else if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) {
RunControl *runControl = Debugger::createAnalyzerRunControl(runConfig, mode); auto runControl = new RunControl(runConfig, mode);
QTC_ASSERT(runControl, return 0); runControl->createWorker(mode);
IDevice::ConstPtr device = DeviceKitInformation::device(target->kit());
if (device.isNull())
return 0;
auto iosRunConfig = qobject_cast<IosRunConfiguration *>(runConfig); auto iosRunConfig = qobject_cast<IosRunConfiguration *>(runConfig);
StandardRunnable runnable; StandardRunnable runnable;
runnable.executable = iosRunConfig->localExecutable().toUserOutput(); runnable.executable = iosRunConfig->localExecutable().toUserOutput();

View File

@@ -525,11 +525,16 @@ void AppOutputPane::attachToRunControl()
void AppOutputPane::stopRunControl() void AppOutputPane::stopRunControl()
{ {
const int index = currentIndex(); const int index = currentIndex();
QTC_ASSERT(index != -1 && m_runControlTabs.at(index).runControl->isRunning(), return); QTC_ASSERT(index != -1, return);
RunControl *rc = m_runControlTabs.at(index).runControl; RunControl *rc = m_runControlTabs.at(index).runControl;
QTC_ASSERT(rc, return);
if (rc->isRunning() && optionallyPromptToStop(rc)) if (rc->isRunning() && optionallyPromptToStop(rc))
rc->initiateStop(); rc->initiateStop();
else if (rc->isStarting()) {
QTC_CHECK(false);
rc->initiateStop();
}
if (debug) if (debug)
qDebug() << "OutputPane::stopRunControl " << rc; qDebug() << "OutputPane::stopRunControl " << rc;

View File

@@ -190,4 +190,40 @@ void DeviceUsedPortsGatherer::handleRemoteStdErr()
d->remoteStderr += d->process->readAllStandardError(); d->remoteStderr += d->process->readAllStandardError();
} }
// PortGatherer
PortsGatherer::PortsGatherer(RunControl *runControl)
: RunWorker(runControl)
{
setDisplayName("PortGatherer");
}
PortsGatherer::~PortsGatherer()
{
}
void PortsGatherer::start()
{
appendMessage(tr("Checking available ports...") + '\n', NormalMessageFormat);
connect(&m_portsGatherer, &DeviceUsedPortsGatherer::error, this, [this](const QString &msg) {
reportFailure(msg);
});
connect(&m_portsGatherer, &DeviceUsedPortsGatherer::portListReady, this, [this] {
m_portList = device()->freePorts();
appendMessage(tr("Found %1 free ports").arg(m_portList.count()) + '\n', NormalMessageFormat);
reportStarted();
});
m_portsGatherer.start(device());
}
Port PortsGatherer::findPort()
{
return m_portsGatherer.getNextFreePort(&m_portList);
}
void PortsGatherer::stop()
{
m_portsGatherer.stop();
}
} // namespace ProjectExplorer } // namespace ProjectExplorer

View File

@@ -27,10 +27,9 @@
#include "idevice.h" #include "idevice.h"
namespace Utils { #include <projectexplorer/runconfiguration.h>
class Port;
class PortList; #include <utils/portlist.h>
} // namespace Utils
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { class DeviceUsedPortsGathererPrivate; } namespace Internal { class DeviceUsedPortsGathererPrivate; }
@@ -64,4 +63,23 @@ private:
Internal::DeviceUsedPortsGathererPrivate * const d; Internal::DeviceUsedPortsGathererPrivate * const d;
}; };
class PROJECTEXPLORER_EXPORT PortsGatherer : public RunWorker
{
Q_OBJECT
public:
explicit PortsGatherer(RunControl *runControl);
~PortsGatherer() override;
Utils::Port findPort();
protected:
void start() override;
void stop() override;
private:
DeviceUsedPortsGatherer m_portsGatherer;
Utils::PortList m_portList;
};
} // namespace ProjectExplorer } // namespace ProjectExplorer

View File

@@ -35,6 +35,8 @@
#include <QSharedPointer> #include <QSharedPointer>
#include <QVariantMap> #include <QVariantMap>
#include <functional>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QWidget; class QWidget;
QT_END_NAMESPACE QT_END_NAMESPACE
@@ -54,6 +56,8 @@ class Connection;
class DeviceProcess; class DeviceProcess;
class DeviceProcessList; class DeviceProcessList;
class Kit; class Kit;
class RunControl;
class RunWorker;
namespace Internal { class IDevicePrivate; } namespace Internal { class IDevicePrivate; }
@@ -162,6 +166,8 @@ public:
virtual DeviceProcessSignalOperation::Ptr signalOperation() const = 0; virtual DeviceProcessSignalOperation::Ptr signalOperation() const = 0;
virtual DeviceEnvironmentFetcher::Ptr environmentFetcher() const; virtual DeviceEnvironmentFetcher::Ptr environmentFetcher() const;
virtual std::function<RunWorker *(RunControl *)> workerCreator(Core::Id) const { return {}; }
enum DeviceState { DeviceReadyToUse, DeviceConnected, DeviceDisconnected, DeviceStateUnknown }; enum DeviceState { DeviceReadyToUse, DeviceConnected, DeviceDisconnected, DeviceStateUnknown };
DeviceState deviceState() const; DeviceState deviceState() const;
void setDeviceState(const DeviceState state); void setDeviceState(const DeviceState state);

File diff suppressed because it is too large Load Diff

View File

@@ -51,11 +51,10 @@ class RunConfiguration;
class RunConfigWidget; class RunConfigWidget;
class RunControl; class RunControl;
class Target; class Target;
class TargetRunner;
class ToolRunner;
namespace Internal { namespace Internal {
class RunControlPrivate; class RunControlPrivate;
class RunWorkerPrivate;
class SimpleRunControlPrivate; class SimpleRunControlPrivate;
} // Internal } // Internal
@@ -148,6 +147,7 @@ class PROJECTEXPLORER_EXPORT Runnable
virtual ~Concept() {} virtual ~Concept() {}
virtual Concept *clone() const = 0; virtual Concept *clone() const = 0;
virtual bool canReUseOutputPane(const std::unique_ptr<Concept> &other) const = 0; virtual bool canReUseOutputPane(const std::unique_ptr<Concept> &other) const = 0;
virtual QString displayName() const = 0;
virtual void *typeId() const = 0; virtual void *typeId() const = 0;
}; };
@@ -168,6 +168,8 @@ class PROJECTEXPLORER_EXPORT Runnable
return m_data == that->m_data; return m_data == that->m_data;
} }
QString displayName() const override { return m_data.displayName(); }
void *typeId() const override { return T::staticTypeId; } void *typeId() const override { return T::staticTypeId; }
T m_data; T m_data;
@@ -190,6 +192,7 @@ public:
} }
bool canReUseOutputPane(const Runnable &other) const; bool canReUseOutputPane(const Runnable &other) const;
QString displayName() const { return d->displayName(); }
private: private:
std::unique_ptr<Concept> d; std::unique_ptr<Concept> d;
@@ -351,6 +354,61 @@ signals:
void displayNameChanged(const QString &); void displayNameChanged(const QString &);
}; };
class PROJECTEXPLORER_EXPORT RunWorker : public QObject
{
Q_OBJECT
public:
explicit RunWorker(RunControl *runControl);
~RunWorker() override;
RunControl *runControl() const;
void addDependency(RunWorker *dependency);
QString displayName() const;
void setDisplayName(const QString &displayName);
void setStartTimeout(int ms);
void setStopTimeout(int ms);
void reportData(int channel, const QVariant &data);
void recordData(const QString &channel, const QVariant &data);
QVariant recordedData(const QString &channel);
// Part of read-only interface of RunControl for convenience.
void appendMessage(const QString &msg, Utils::OutputFormat format);
IDevice::ConstPtr device() const;
const Runnable &runnable() const;
const Connection &connection() const;
Core::Id runMode() const;
// States
void initiateStart();
void reportStarted();
void initiateStop();
void reportStopped();
void reportFailure(const QString &msg = QString());
signals:
void dataReported(int channel, const QVariant &data);
void started();
void stopped();
protected:
void virtual start();
void virtual stop();
void virtual onFinished() {}
private:
friend class Internal::RunControlPrivate;
friend class Internal::RunWorkerPrivate;
Internal::RunWorkerPrivate *d;
};
/** /**
* A RunControl controls the running of an application or tool * A RunControl controls the running of an application or tool
* on a target device. It controls start and stop, and handles * on a target device. It controls start and stop, and handles
@@ -380,6 +438,8 @@ public:
void setDisplayName(const QString &displayName); void setDisplayName(const QString &displayName);
bool isRunning() const; bool isRunning() const;
bool isStarting() const;
bool isStopping() const;
void setIcon(const Utils::Icon &icon); void setIcon(const Utils::Icon &icon);
Utils::Icon icon() const; Utils::Icon icon() const;
@@ -402,12 +462,6 @@ public:
const Connection &connection() const; const Connection &connection() const;
void setConnection(const Connection &connection); void setConnection(const Connection &connection);
ToolRunner *toolRunner() const;
void setToolRunner(ToolRunner *tool);
TargetRunner *targetRunner() const;
void setTargetRunner(TargetRunner *tool);
virtual void appendMessage(const QString &msg, Utils::OutputFormat format); virtual void appendMessage(const QString &msg, Utils::OutputFormat format);
virtual void bringApplicationToForeground(); virtual void bringApplicationToForeground();
@@ -415,8 +469,9 @@ public:
virtual void notifyRemoteSetupFailed(const QString &) {} // Same. virtual void notifyRemoteSetupFailed(const QString &) {} // Same.
virtual void notifyRemoteFinished() {} // Same. virtual void notifyRemoteFinished() {} // Same.
void reportApplicationStart(); // Call this when the application starts to run void reportApplicationStart(); // FIXME: Don't use
void reportApplicationStop(); // Call this when the application has stopped for any reason void reportApplicationStop(); // FIXME: Don't use
void reportFailure(const QString &msg = QString());
static bool showPromptToStopDialog(const QString &title, const QString &text, static bool showPromptToStopDialog(const QString &title, const QString &text,
const QString &stopButtonText = QString(), const QString &stopButtonText = QString(),
@@ -426,6 +481,25 @@ public:
virtual void start(); virtual void start();
virtual void stop(); virtual void stop();
using WorkerCreator = std::function<RunWorker *(RunControl *)>;
static void registerWorkerCreator(Core::Id id, const WorkerCreator &workerCreator);
RunWorker *workerById(Core::Id id) const;
QList<QPointer<RunWorker>> workers() const;
template <class T> T *worker() const {
for (const QPointer<RunWorker> &worker : workers()) {
if (worker) {
if (auto res = qobject_cast<T *>(worker.data()))
return res;
}
}
return nullptr;
}
using RunWorkerCreator = std::function<RunWorker *(RunControl *)>;
static void registerRunWorkerCreator(Core::Id id, const RunWorkerCreator &creator);
RunWorker *createWorker(Core::Id id);
signals: signals:
void appendMessageRequested(ProjectExplorer::RunControl *runControl, void appendMessageRequested(ProjectExplorer::RunControl *runControl,
const QString &msg, Utils::OutputFormat format); const QString &msg, Utils::OutputFormat format);
@@ -436,114 +510,29 @@ signals:
void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle
private: private:
friend class Internal::RunControlPrivate; friend class RunWorker;
friend class TargetRunner; friend class Internal::RunWorkerPrivate;
friend class ToolRunner;
void bringApplicationToForegroundInternal(); void bringApplicationToForegroundInternal();
Internal::RunControlPrivate *d; Internal::RunControlPrivate *d;
}; };
/**
* A base for target-specific additions to the RunControl.
*/
class PROJECTEXPLORER_EXPORT TargetRunner : public QObject
{
Q_OBJECT
public:
explicit TargetRunner(RunControl *runControl);
~TargetRunner() override;
RunControl *runControl() const;
void appendMessage(const QString &msg, Utils::OutputFormat format);
IDevice::ConstPtr device() const;
// Preparation phase.
virtual void prepare(); // Initiate setup. Needs to report result.
// Startup phase.
virtual void start(); // Initiates start. Needs to report result.
// Stopping phase.
virtual void stop(); // Initiates stop. Needs to report result.
//
void reportStopped();
// Generic success report, proceed to next stage.
void reportSuccess();
// Generic error, start ramp down.
void reportFailure(const QString &msg = QString());
// Customization points. No reporting required nor wanted.
virtual void onStop() {}
virtual void onToolFailure() {}
virtual void onTargetFailure() {}
virtual void onFinished() {}
private:
QPointer<RunControl> m_runControl;
};
/**
* A base for tool-specific additions to RunControl.
*/
class PROJECTEXPLORER_EXPORT ToolRunner : public QObject
{
Q_OBJECT
public:
explicit ToolRunner(RunControl *runControl);
~ToolRunner() override;
RunControl *runControl() const;
// Part of read-only interface of RunControl for convenience.
void appendMessage(const QString &msg, Utils::OutputFormat format);
IDevice::ConstPtr device() const;
const Runnable &runnable() const;
const Connection &connection() const;
// Preparation phase.
virtual void prepare(); // Initiates preparation, needs to report success or failure.
// Start phase.
virtual void start();
// Stop phase.
virtual void stop();
//
void reportStopped();
// Generic success report, proceed to next stage.
void reportSuccess();
// Generic error, start ramp down.
void reportFailure(const QString &msg = QString());
// Customization points. No reporting required nor wanted.
virtual void onStop() {}
virtual void onToolFailure() {}
virtual void onTargetFailure() {}
virtual void onFinished() {}
private:
QPointer<RunControl> m_runControl;
};
/** /**
* A simple TargetRunner for cases where a plain ApplicationLauncher is * A simple TargetRunner for cases where a plain ApplicationLauncher is
* sufficient for running purposes. * sufficient for running purposes.
*/ */
class PROJECTEXPLORER_EXPORT SimpleTargetRunner : public TargetRunner class PROJECTEXPLORER_EXPORT SimpleTargetRunner : public RunWorker
{ {
public: public:
explicit SimpleTargetRunner(RunControl *runControl); explicit SimpleTargetRunner(RunControl *runControl);
ApplicationLauncher *applicationLauncher() { return &m_launcher; } protected:
private:
void start() override; void start() override;
void stop() override; void stop() override;
private:
void onProcessStarted(); void onProcessStarted();
void onProcessFinished(int exitCode, QProcess::ExitStatus status); void onProcessFinished(int exitCode, QProcess::ExitStatus status);

View File

@@ -32,6 +32,7 @@
#include <utils/environment.h> #include <utils/environment.h>
#include <QDir>
#include <QUrl> #include <QUrl>
namespace ProjectExplorer { namespace ProjectExplorer {
@@ -46,6 +47,7 @@ public:
ApplicationLauncher::Mode runMode = ApplicationLauncher::Gui; ApplicationLauncher::Mode runMode = ApplicationLauncher::Gui;
IDevice::ConstPtr device; // Override the kit's device. Keep unset by default. IDevice::ConstPtr device; // Override the kit's device. Keep unset by default.
QString displayName() const { return QDir::toNativeSeparators(executable); }
static void *staticTypeId; static void *staticTypeId;
}; };

View File

@@ -67,7 +67,6 @@ namespace QmlProfiler {
class QmlProfilerRunControl::QmlProfilerRunControlPrivate class QmlProfilerRunControl::QmlProfilerRunControlPrivate
{ {
public: public:
Internal::QmlProfilerTool *m_tool = 0;
QmlProfilerStateManager *m_profilerState = 0; QmlProfilerStateManager *m_profilerState = 0;
QTimer m_noDebugOutputTimer; QTimer m_noDebugOutputTimer;
}; };
@@ -76,15 +75,13 @@ public:
// QmlProfilerRunControl // QmlProfilerRunControl
// //
QmlProfilerRunControl::QmlProfilerRunControl(RunConfiguration *runConfiguration, QmlProfilerRunControl::QmlProfilerRunControl(RunConfiguration *runConfiguration)
Internal::QmlProfilerTool *tool)
: RunControl(runConfiguration, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) : RunControl(runConfiguration, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE)
, d(new QmlProfilerRunControlPrivate) , d(new QmlProfilerRunControlPrivate)
{ {
setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR); setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
setSupportsReRunning(false); setSupportsReRunning(false);
d->m_tool = tool;
// Only wait 4 seconds for the 'Waiting for connection' on application output, then just try to connect // Only wait 4 seconds for the 'Waiting for connection' on application output, then just try to connect
// (application output might be redirected / blocked) // (application output might be redirected / blocked)
d->m_noDebugOutputTimer.setSingleShot(true); d->m_noDebugOutputTimer.setSingleShot(true);
@@ -104,7 +101,7 @@ QmlProfilerRunControl::~QmlProfilerRunControl()
void QmlProfilerRunControl::start() void QmlProfilerRunControl::start()
{ {
reportApplicationStart(); reportApplicationStart();
d->m_tool->finalizeRunControl(this); Internal::QmlProfilerTool::instance()->finalizeRunControl(this);
QTC_ASSERT(d->m_profilerState, reportApplicationStop(); return); QTC_ASSERT(d->m_profilerState, reportApplicationStop(); return);
QTC_ASSERT(connection().is<AnalyzerConnection>(), reportApplicationStop(); return); QTC_ASSERT(connection().is<AnalyzerConnection>(), reportApplicationStop(); return);

View File

@@ -32,15 +32,12 @@
namespace QmlProfiler { namespace QmlProfiler {
namespace Internal { class QmlProfilerTool; }
class QmlProfilerRunControl : public ProjectExplorer::RunControl class QmlProfilerRunControl : public ProjectExplorer::RunControl
{ {
Q_OBJECT Q_OBJECT
public: public:
QmlProfilerRunControl(ProjectExplorer::RunConfiguration *runConfiguration, QmlProfilerRunControl(ProjectExplorer::RunConfiguration *runConfiguration);
Internal::QmlProfilerTool *tool);
~QmlProfilerRunControl() override; ~QmlProfilerRunControl() override;
void registerProfilerStateManager( QmlProfilerStateManager *profilerState ); void registerProfilerStateManager( QmlProfilerStateManager *profilerState );

View File

@@ -92,10 +92,7 @@ RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfigurat
connection.analyzerPort = LocalQmlProfilerRunner::findFreePort(connection.analyzerHost); connection.analyzerPort = LocalQmlProfilerRunner::findFreePort(connection.analyzerHost);
} }
auto runControl = qobject_cast<QmlProfilerRunControl *> auto runControl = new QmlProfilerRunControl(runConfiguration);
(Debugger::createAnalyzerRunControl(runConfiguration, mode));
QTC_ASSERT(runControl, return 0);
runControl->setRunnable(runnable); runControl->setRunnable(runnable);
runControl->setConnection(connection); runControl->setConnection(connection);

View File

@@ -127,9 +127,12 @@ public:
bool m_toolBusy = false; bool m_toolBusy = false;
}; };
static QmlProfilerTool *s_instance;
QmlProfilerTool::QmlProfilerTool(QObject *parent) QmlProfilerTool::QmlProfilerTool(QObject *parent)
: QObject(parent), d(new QmlProfilerToolPrivate) : QObject(parent), d(new QmlProfilerToolPrivate)
{ {
s_instance = this;
setObjectName(QLatin1String("QmlProfilerTool")); setObjectName(QLatin1String("QmlProfilerTool"));
d->m_profilerState = new QmlProfilerStateManager(this); d->m_profilerState = new QmlProfilerStateManager(this);
@@ -244,8 +247,9 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
// is available, then we can populate the file finder // is available, then we can populate the file finder
d->m_profilerModelManager->populateFileFinder(); d->m_profilerModelManager->populateFileFinder();
auto runControlCreator = [this](RunConfiguration *runConfiguration, Core::Id) { auto runWorkerCreator = [this](RunControl *runControl) {
return createRunControl(runConfiguration); // return createRunControl(runConfiguration);
return nullptr; // FIXME
}; };
QString description = tr("The QML Profiler can be used to find performance " QString description = tr("The QML Profiler can be used to find performance "
@@ -254,7 +258,7 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
d->m_startAction = Debugger::createStartAction(); d->m_startAction = Debugger::createStartAction();
d->m_stopAction = Debugger::createStopAction(); d->m_stopAction = Debugger::createStopAction();
Debugger::registerAction(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, runControlCreator); RunControl::registerWorkerCreator(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, runWorkerCreator);
act = new QAction(tr("QML Profiler"), this); act = new QAction(tr("QML Profiler"), this);
act->setToolTip(description); act->setToolTip(description);
menu->addAction(ActionManager::registerAction(act, "QmlProfiler.Local"), menu->addAction(ActionManager::registerAction(act, "QmlProfiler.Local"),
@@ -270,7 +274,6 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
act->setEnabled(d->m_startAction->isEnabled()); act->setEnabled(d->m_startAction->isEnabled());
}); });
Debugger::registerAction(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, runControlCreator);
act = new QAction(tr("QML Profiler (External)"), this); act = new QAction(tr("QML Profiler (External)"), this);
act->setToolTip(description); act->setToolTip(description);
menu->addAction(ActionManager::registerAction(act, "QmlProfiler.Remote"), menu->addAction(ActionManager::registerAction(act, "QmlProfiler.Remote"),
@@ -305,6 +308,11 @@ QmlProfilerTool::~QmlProfilerTool()
delete d; delete d;
} }
QmlProfilerTool *QmlProfilerTool::instance()
{
return s_instance;
}
void QmlProfilerTool::updateRunActions() void QmlProfilerTool::updateRunActions()
{ {
if (d->m_toolBusy) { if (d->m_toolBusy) {
@@ -336,11 +344,11 @@ RunControl *QmlProfilerTool::createRunControl(RunConfiguration *runConfiguration
} }
} }
auto runControl = new QmlProfilerRunControl(runConfiguration, this); auto runControl = new QmlProfilerRunControl(runConfiguration);
connect(runControl, &RunControl::finished, this, [this, runControl] { connect(runControl, &RunControl::finished, this, [this, runControl] {
d->m_toolBusy = false; d->m_toolBusy = false;
updateRunActions(); updateRunActions();
disconnect(d->m_stopAction, &QAction::triggered, runControl, &QmlProfilerRunControl::stop); disconnect(d->m_stopAction, &QAction::triggered, runControl, &RunControl::stop);
}); });
connect(d->m_stopAction, &QAction::triggered, runControl, &QmlProfilerRunControl::stop); connect(d->m_stopAction, &QAction::triggered, runControl, &QmlProfilerRunControl::stop);

View File

@@ -49,6 +49,8 @@ public:
explicit QmlProfilerTool(QObject *parent); explicit QmlProfilerTool(QObject *parent);
~QmlProfilerTool(); ~QmlProfilerTool();
static QmlProfilerTool *instance();
ProjectExplorer::RunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration = 0); ProjectExplorer::RunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration = 0);
void finalizeRunControl(QmlProfilerRunControl *runControl); void finalizeRunControl(QmlProfilerRunControl *runControl);

View File

@@ -24,6 +24,9 @@
****************************************************************************/ ****************************************************************************/
#include "localqmlprofilerrunner_test.h" #include "localqmlprofilerrunner_test.h"
#include "../qmlprofilerruncontrol.h"
#include <debugger/analyzer/analyzermanager.h> #include <debugger/analyzer/analyzermanager.h>
#include <debugger/analyzer/analyzerstartparameters.h> #include <debugger/analyzer/analyzerstartparameters.h>
#include <QtTest> #include <QtTest>
@@ -57,8 +60,7 @@ void LocalQmlProfilerRunnerTest::testRunner()
// should not be used anywhere but cannot be empty // should not be used anywhere but cannot be empty
configuration.socket = connection.analyzerSocket = QString("invalid"); configuration.socket = connection.analyzerSocket = QString("invalid");
rc = Debugger::createAnalyzerRunControl( rc = new QmlProfilerRunControl(nullptr);
nullptr, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
rc->setConnection(connection); rc->setConnection(connection);
auto runner = new LocalQmlProfilerRunner(configuration, rc); auto runner = new LocalQmlProfilerRunner(configuration, rc);
connectRunner(runner); connectRunner(runner);
@@ -79,8 +81,7 @@ void LocalQmlProfilerRunnerTest::testRunner1()
configuration.debuggee.commandLineArguments = QString("-test QmlProfiler,"); configuration.debuggee.commandLineArguments = QString("-test QmlProfiler,");
delete rc; delete rc;
rc = Debugger::createAnalyzerRunControl( rc = new QmlProfilerRunControl(nullptr);
nullptr, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
rc->setConnection(connection); rc->setConnection(connection);
auto runner = new LocalQmlProfilerRunner(configuration, rc); auto runner = new LocalQmlProfilerRunner(configuration, rc);
connectRunner(runner); connectRunner(runner);
@@ -100,8 +101,7 @@ void LocalQmlProfilerRunnerTest::testRunner2()
connection.analyzerSocket.clear(); connection.analyzerSocket.clear();
configuration.port = connection.analyzerPort = configuration.port = connection.analyzerPort =
LocalQmlProfilerRunner::findFreePort(connection.analyzerHost); LocalQmlProfilerRunner::findFreePort(connection.analyzerHost);
rc = Debugger::createAnalyzerRunControl( rc = new QmlProfilerRunControl(nullptr);
nullptr, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
rc->setConnection(connection); rc->setConnection(connection);
auto runner = new LocalQmlProfilerRunner(configuration, rc); auto runner = new LocalQmlProfilerRunner(configuration, rc);
connectRunner(runner); connectRunner(runner);

View File

@@ -9,13 +9,11 @@ SOURCES += qnxplugin.cpp \
qnxdevicewizard.cpp \ qnxdevicewizard.cpp \
qnxrunconfiguration.cpp \ qnxrunconfiguration.cpp \
qnxruncontrolfactory.cpp \ qnxruncontrolfactory.cpp \
qnxabstractrunsupport.cpp \
qnxanalyzesupport.cpp \ qnxanalyzesupport.cpp \
qnxdebugsupport.cpp \ qnxdebugsupport.cpp \
qnxdeploystepfactory.cpp \ qnxdeploystepfactory.cpp \
qnxdeployconfigurationfactory.cpp \ qnxdeployconfigurationfactory.cpp \
qnxrunconfigurationfactory.cpp \ qnxrunconfigurationfactory.cpp \
qnxruncontrol.cpp \
qnxqtversionfactory.cpp \ qnxqtversionfactory.cpp \
qnxqtversion.cpp \ qnxqtversion.cpp \
qnxdeployconfiguration.cpp \ qnxdeployconfiguration.cpp \
@@ -44,13 +42,11 @@ HEADERS += qnxplugin.h\
qnxdevicewizard.h \ qnxdevicewizard.h \
qnxrunconfiguration.h \ qnxrunconfiguration.h \
qnxruncontrolfactory.h \ qnxruncontrolfactory.h \
qnxabstractrunsupport.h \
qnxanalyzesupport.h \ qnxanalyzesupport.h \
qnxdebugsupport.h \ qnxdebugsupport.h \
qnxdeploystepfactory.h \ qnxdeploystepfactory.h \
qnxdeployconfigurationfactory.h \ qnxdeployconfigurationfactory.h \
qnxrunconfigurationfactory.h \ qnxrunconfigurationfactory.h \
qnxruncontrol.h \
qnxqtversionfactory.h \ qnxqtversionfactory.h \
qnxqtversion.h \ qnxqtversion.h \
qnxdeployconfiguration.h \ qnxdeployconfiguration.h \

View File

@@ -33,8 +33,6 @@ QtcPlugin {
"qnxconstants.h", "qnxconstants.h",
"qnxconfiguration.cpp", "qnxconfiguration.cpp",
"qnxconfiguration.h", "qnxconfiguration.h",
"qnxabstractrunsupport.cpp",
"qnxabstractrunsupport.h",
"qnxanalyzesupport.cpp", "qnxanalyzesupport.cpp",
"qnxanalyzesupport.h", "qnxanalyzesupport.h",
"qnxdebugsupport.cpp", "qnxdebugsupport.cpp",
@@ -78,8 +76,6 @@ QtcPlugin {
"qnxrunconfiguration.h", "qnxrunconfiguration.h",
"qnxrunconfigurationfactory.cpp", "qnxrunconfigurationfactory.cpp",
"qnxrunconfigurationfactory.h", "qnxrunconfigurationfactory.h",
"qnxruncontrol.cpp",
"qnxruncontrol.h",
"qnxruncontrolfactory.cpp", "qnxruncontrolfactory.cpp",
"qnxruncontrolfactory.h", "qnxruncontrolfactory.h",
"qnxutils.cpp", "qnxutils.cpp",

View File

@@ -1,124 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "qnxabstractrunsupport.h"
#include "qnxrunconfiguration.h"
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
#include <utils/portlist.h>
#include <utils/qtcassert.h>
using namespace ProjectExplorer;
using namespace RemoteLinux;
namespace Qnx {
namespace Internal {
QnxAbstractRunSupport::QnxAbstractRunSupport(RunControl *runControl)
: ToolRunner(runControl)
, m_state(Inactive)
{
m_launcher = new ApplicationLauncher(this);
m_portsGatherer = new DeviceUsedPortsGatherer(this);
connect(m_portsGatherer, &DeviceUsedPortsGatherer::error,
this, &QnxAbstractRunSupport::handleError);
connect(m_portsGatherer, &DeviceUsedPortsGatherer::portListReady,
this, &QnxAbstractRunSupport::handlePortListReady);
}
void QnxAbstractRunSupport::handleAdapterSetupRequested()
{
QTC_ASSERT(m_state == Inactive, return);
m_state = GatheringPorts;
m_portsGatherer->start(m_device);
}
void QnxAbstractRunSupport::handlePortListReady()
{
QTC_ASSERT(m_state == GatheringPorts, return);
m_portList = device()->freePorts();
startExecution();
}
void QnxAbstractRunSupport::handleRemoteProcessStarted()
{
m_state = Running;
}
void QnxAbstractRunSupport::handleRemoteProcessFinished(bool)
{
}
void QnxAbstractRunSupport::setFinished()
{
if (m_state != GatheringPorts && m_state != Inactive)
m_launcher->stop();
m_state = Inactive;
}
QnxAbstractRunSupport::State QnxAbstractRunSupport::state() const
{
return m_state;
}
void QnxAbstractRunSupport::setState(QnxAbstractRunSupport::State state)
{
m_state = state;
}
ApplicationLauncher *QnxAbstractRunSupport::appRunner() const
{
return m_launcher;
}
void QnxAbstractRunSupport::handleProgressReport(const QString &)
{
}
void QnxAbstractRunSupport::handleRemoteOutput(const QByteArray &)
{
}
void QnxAbstractRunSupport::handleError(const QString &)
{
}
bool QnxAbstractRunSupport::setPort(Utils::Port &port)
{
port = m_portsGatherer->getNextFreePort(&m_portList);
if (!port.isValid()) {
handleError(tr("Not enough free ports on device for debugging."));
return false;
}
return true;
}
} // namespace Internal
} // namespace Qnx

View File

@@ -1,91 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/runconfiguration.h>
#include <utils/environment.h>
#include <utils/portlist.h>
#include <QObject>
#include <QString>
namespace ProjectExplorer {
class ApplicationLauncher;
class DeviceUsedPortsGatherer;
}
namespace Qnx {
namespace Internal {
class QnxAbstractRunSupport : public ProjectExplorer::ToolRunner
{
Q_OBJECT
protected:
enum State {
Inactive,
GatheringPorts,
StartingRemoteProcess,
Running
};
public:
explicit QnxAbstractRunSupport(ProjectExplorer::RunControl *runControl);
protected:
bool setPort(Utils::Port &port);
virtual void startExecution() = 0;
void setFinished();
State state() const;
void setState(State state);
ProjectExplorer::ApplicationLauncher *appRunner() const;
public slots:
virtual void handleAdapterSetupRequested();
virtual void handleRemoteProcessStarted();
virtual void handleRemoteProcessFinished(bool);
virtual void handleProgressReport(const QString &progressOutput);
virtual void handleRemoteOutput(const QByteArray &output);
virtual void handleError(const QString &);
private slots:
void handlePortListReady();
private:
ProjectExplorer::DeviceUsedPortsGatherer * m_portsGatherer;
Utils::PortList m_portList;
ProjectExplorer::IDevice::ConstPtr m_device;
ProjectExplorer::ApplicationLauncher *m_launcher;
State m_state;
};
} // namespace Internal
} // namespace Qnx

View File

@@ -29,12 +29,15 @@
#include "qnxrunconfiguration.h" #include "qnxrunconfiguration.h"
#include "slog2inforunner.h" #include "slog2inforunner.h"
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <projectexplorer/kitinformation.h> #include <projectexplorer/kitinformation.h>
#include <projectexplorer/runnables.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <qmldebug/qmldebugcommandlinearguments.h> #include <qmldebug/qmldebugcommandlinearguments.h>
#include <qmldebug/qmloutputparser.h>
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
@@ -42,122 +45,64 @@ using namespace Utils;
namespace Qnx { namespace Qnx {
namespace Internal { namespace Internal {
QnxAnalyzeSupport::QnxAnalyzeSupport(RunControl *runControl) class QnxAnalyzeeRunner : public ProjectExplorer::SimpleTargetRunner
: QnxAbstractRunSupport(runControl)
, m_runnable(runControl->runnable().as<StandardRunnable>())
, m_qmlPort(-1)
{ {
const ApplicationLauncher *runner = appRunner(); public:
connect(runner, &ApplicationLauncher::reportError, QnxAnalyzeeRunner(ProjectExplorer::RunControl *runControl)
this, &QnxAnalyzeSupport::handleError); : SimpleTargetRunner(runControl)
connect(runner, &ApplicationLauncher::remoteProcessStarted, {
this, &QnxAbstractRunSupport::handleRemoteProcessStarted); setDisplayName("QnxAnalyzeeRunner");
connect(runner, &ApplicationLauncher::finished,
this, &QnxAnalyzeSupport::handleRemoteProcessFinished);
connect(runner, &ApplicationLauncher::reportProgress,
this, &QnxAnalyzeSupport::handleProgressReport);
connect(runner, &ApplicationLauncher::remoteStdout,
this, &QnxAnalyzeSupport::handleRemoteOutput);
connect(runner, &ApplicationLauncher::remoteStderr,
this, &QnxAnalyzeSupport::handleRemoteOutput);
connect(runControl, &RunControl::starting,
this, &QnxAnalyzeSupport::handleAdapterSetupRequested);
connect(runControl, &RunControl::finished,
this, &QnxAnalyzeSupport::setFinished);
connect(&m_outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort,
this, &QnxAnalyzeSupport::remoteIsRunning);
IDevice::ConstPtr dev = DeviceKitInformation::device(runControl->runConfiguration()->target()->kit());
QnxDevice::ConstPtr qnxDevice = dev.dynamicCast<const QnxDevice>();
auto qnxRunConfig = qobject_cast<QnxRunConfiguration *>(runControl->runConfiguration());
const QString applicationId = FileName::fromString(qnxRunConfig->remoteExecutableFilePath()).fileName();
m_slog2Info = new Slog2InfoRunner(applicationId, qnxDevice, this);
connect(m_slog2Info, &Slog2InfoRunner::output,
this, &QnxAnalyzeSupport::showMessage);
connect(runner, &ApplicationLauncher::remoteProcessStarted,
m_slog2Info, &Slog2InfoRunner::start);
if (qnxDevice->qnxVersion() > 0x060500)
connect(m_slog2Info, &Slog2InfoRunner::commandMissing,
this, &QnxAnalyzeSupport::printMissingWarning);
}
void QnxAnalyzeSupport::handleAdapterSetupRequested()
{
QTC_ASSERT(state() == Inactive, return);
showMessage(tr("Preparing remote side...") + QLatin1Char('\n'), NormalMessageFormat);
QnxAbstractRunSupport::handleAdapterSetupRequested();
}
void QnxAnalyzeSupport::startExecution()
{
if (state() == Inactive)
return;
if (!setPort(m_qmlPort) && !m_qmlPort.isValid())
return;
setState(StartingRemoteProcess);
StandardRunnable r = m_runnable;
if (!r.commandLineArguments.isEmpty())
r.commandLineArguments += QLatin1Char(' ');
r.commandLineArguments += QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlProfilerServices,
m_qmlPort);
appRunner()->start(r, device());
}
void QnxAnalyzeSupport::handleRemoteProcessFinished(bool success)
{
if (!success)
showMessage(tr("The %1 process closed unexpectedly.").arg(m_runnable.executable),
NormalMessageFormat);
runControl()->notifyRemoteFinished();
m_slog2Info->stop();
}
void QnxAnalyzeSupport::handleProgressReport(const QString &progressOutput)
{
showMessage(progressOutput + QLatin1Char('\n'), NormalMessageFormat);
}
void QnxAnalyzeSupport::handleRemoteOutput(const QByteArray &output)
{
QTC_ASSERT(state() == Inactive || state() == Running, return);
showMessage(QString::fromUtf8(output), StdOutFormat);
}
void QnxAnalyzeSupport::handleError(const QString &error)
{
if (state() == Running) {
showMessage(error, ErrorMessageFormat);
} else if (state() != Inactive) {
showMessage(tr("Initial setup failed: %1").arg(error), NormalMessageFormat);
setFinished();
} }
private:
void start() override
{
auto portsGatherer = runControl()->worker<PortsGatherer>();
Utils::Port port = portsGatherer->findPort();
auto r = runnable().as<StandardRunnable>();
if (!r.commandLineArguments.isEmpty())
r.commandLineArguments += ' ';
r.commandLineArguments +=
QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlProfilerServices, port);
runControl()->setRunnable(r);
SimpleTargetRunner::start();
}
};
// QnxDebugSupport
QnxAnalyzeSupport::QnxAnalyzeSupport(RunControl *runControl)
: RunWorker(runControl)
{
setDisplayName("QnxAnalyzeSupport");
appendMessage(tr("Preparing remote side..."), Utils::LogMessageFormat);
auto portsGatherer = new PortsGatherer(runControl);
auto debuggeeRunner = new QnxAnalyzeeRunner(runControl);
debuggeeRunner->addDependency(portsGatherer);
auto slog2InfoRunner = new Slog2InfoRunner(runControl);
slog2InfoRunner->addDependency(debuggeeRunner);
addDependency(slog2InfoRunner);
// QmlDebug::QmlOutputParser m_outputParser;
// FIXME: m_outputParser needs to be fed with application output
// connect(&m_outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort,
// this, &QnxAnalyzeSupport::remoteIsRunning);
// m_outputParser.processOutput(msg);
} }
void QnxAnalyzeSupport::remoteIsRunning() void QnxAnalyzeSupport::start()
{ {
runControl()->notifyRemoteSetupDone(m_qmlPort); // runControl()->notifyRemoteSetupDone(m_qmlPort);
} reportStarted();
void QnxAnalyzeSupport::showMessage(const QString &msg, OutputFormat format)
{
if (state() != Inactive)
runControl()->appendMessage(msg, format);
m_outputParser.processOutput(msg);
}
void QnxAnalyzeSupport::printMissingWarning()
{
showMessage(tr("Warning: \"slog2info\" is not found on the device, debug output not available."),
ErrorMessageFormat);
} }
} // namespace Internal } // namespace Internal

View File

@@ -25,18 +25,14 @@
#pragma once #pragma once
#include "qnxabstractrunsupport.h" #include <projectexplorer/runconfiguration.h>
#include <projectexplorer/runnables.h>
#include <utils/outputformat.h>
#include <qmldebug/qmloutputparser.h>
namespace Qnx { namespace Qnx {
namespace Internal { namespace Internal {
class Slog2InfoRunner; class Slog2InfoRunner;
class QnxAnalyzeSupport : public QnxAbstractRunSupport class QnxAnalyzeSupport : public ProjectExplorer::RunWorker
{ {
Q_OBJECT Q_OBJECT
@@ -44,24 +40,7 @@ public:
explicit QnxAnalyzeSupport(ProjectExplorer::RunControl *runControl); explicit QnxAnalyzeSupport(ProjectExplorer::RunControl *runControl);
private: private:
void handleAdapterSetupRequested() override; void start() override;
void handleRemoteProcessFinished(bool success) override;
void handleProgressReport(const QString &progressOutput) override;
void handleRemoteOutput(const QByteArray &output) override;
void handleError(const QString &error) override;
void showMessage(const QString &, Utils::OutputFormat);
void printMissingWarning();
void remoteIsRunning();
void startExecution() override;
ProjectExplorer::StandardRunnable m_runnable;
QmlDebug::QmlOutputParser m_outputParser;
Utils::Port m_qmlPort;
Slog2InfoRunner *m_slog2Info;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -146,9 +146,9 @@ void QnxAttachDebugSupport::attachToProcess()
stopPDebug(); stopPDebug();
return; return;
} }
connect(qobject_cast<Debugger::DebuggerRunTool *>(runControl->toolRunner()), // connect(qobject_cast<Debugger::DebuggerRunTool *>(runControl->toolRunner()),
&Debugger::DebuggerRunTool::stateChanged, // &Debugger::DebuggerRunTool::stateChanged,
this, &QnxAttachDebugSupport::handleDebuggerStateChanged); // this, &QnxAttachDebugSupport::handleDebuggerStateChanged);
ProjectExplorerPlugin::startRunControl(runControl); ProjectExplorerPlugin::startRunControl(runControl);
} }

View File

@@ -28,182 +28,123 @@
#include "qnxdevice.h" #include "qnxdevice.h"
#include "qnxrunconfiguration.h" #include "qnxrunconfiguration.h"
#include "slog2inforunner.h" #include "slog2inforunner.h"
#include "qnxqtversion.h"
#include "qnxutils.h"
#include <debugger/debuggerrunconfigurationaspect.h>
#include <debugger/debuggerruncontrol.h> #include <debugger/debuggerruncontrol.h>
#include <debugger/debuggerstartparameters.h>
#include <projectexplorer/applicationlauncher.h>
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h> #include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <projectexplorer/kitinformation.h> #include <projectexplorer/kitinformation.h>
#include <projectexplorer/runnables.h> #include <projectexplorer/runnables.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
using namespace Debugger;
using namespace ProjectExplorer; using namespace ProjectExplorer;
namespace Qnx { namespace Qnx {
namespace Internal { namespace Internal {
QnxDebugSupport::QnxDebugSupport(RunControl *runControl) // QnxDebuggeeRunner
: QnxAbstractRunSupport(runControl)
class QnxDebuggeeRunner : public ProjectExplorer::SimpleTargetRunner
{ {
auto runConfig = runControl->runConfiguration(); public:
m_useCppDebugger = runConfig->extraAspect<Debugger::DebuggerRunConfigurationAspect>()->useCppDebugger(); QnxDebuggeeRunner(ProjectExplorer::RunControl *runControl)
m_useQmlDebugger = runConfig->extraAspect<Debugger::DebuggerRunConfigurationAspect>()->useQmlDebugger(); : SimpleTargetRunner(runControl)
m_runnable = runConfig->runnable().as<StandardRunnable>(); {
setDisplayName("QnxDebuggeeRunner");
}
const ApplicationLauncher *runner = appRunner(); private:
connect(runner, &ApplicationLauncher::reportError, this, &QnxDebugSupport::handleError); void start() override
connect(runner, &ApplicationLauncher::remoteProcessStarted, this, &QnxDebugSupport::handleRemoteProcessStarted); {
connect(runner, &ApplicationLauncher::finished, this, &QnxDebugSupport::handleRemoteProcessFinished); auto portsGatherer = runControl()->worker<GdbServerPortsGatherer>();
connect(runner, &ApplicationLauncher::reportProgress, this, &QnxDebugSupport::handleProgressReport);
connect(runner, &ApplicationLauncher::remoteStdout, this, &QnxDebugSupport::handleRemoteOutput);
connect(runner, &ApplicationLauncher::remoteStderr, this, &QnxDebugSupport::handleRemoteOutput);
connect(toolRunner(), &Debugger::DebuggerRunTool::requestRemoteSetup, StandardRunnable r = runnable().as<StandardRunnable>();
this, &QnxDebugSupport::handleAdapterSetupRequested); QStringList arguments;
connect(runControl, &RunControl::finished, if (portsGatherer->useGdbServer()) {
this, &QnxDebugSupport::handleDebuggingFinished); Utils::Port pdebugPort = portsGatherer->gdbServerPort();
r.executable = Constants::QNX_DEBUG_EXECUTABLE;
auto qnxRunConfig = qobject_cast<QnxRunConfiguration *>(runControl->runConfiguration()); arguments.append(pdebugPort.toString());
const QString applicationId = Utils::FileName::fromString(qnxRunConfig->remoteExecutableFilePath()).fileName(); }
IDevice::ConstPtr dev = DeviceKitInformation::device(runConfig->target()->kit()); if (portsGatherer->useQmlServer()) {
QnxDevice::ConstPtr qnxDevice = dev.dynamicCast<const QnxDevice>();
m_slog2Info = new Slog2InfoRunner(applicationId, qnxDevice, this);
connect(m_slog2Info, &Slog2InfoRunner::output, this, &QnxDebugSupport::handleApplicationOutput);
connect(runner, &ApplicationLauncher::remoteProcessStarted, m_slog2Info, &Slog2InfoRunner::start);
if (qnxDevice->qnxVersion() > 0x060500)
connect(m_slog2Info, &Slog2InfoRunner::commandMissing, this, &QnxDebugSupport::printMissingWarning);
}
void QnxDebugSupport::handleAdapterSetupRequested()
{
QTC_ASSERT(state() == Inactive, return);
toolRunner()->showMessage(tr("Preparing remote side...") + '\n', Debugger::AppStuff);
QnxAbstractRunSupport::handleAdapterSetupRequested();
}
void QnxDebugSupport::startExecution()
{
if (state() == Inactive)
return;
if (m_useCppDebugger && !setPort(m_pdebugPort))
return;
if (m_useQmlDebugger && !setPort(m_qmlPort))
return;
setState(StartingRemoteProcess);
StandardRunnable r = m_runnable;
QStringList arguments;
if (m_useCppDebugger)
arguments << QString::number(m_pdebugPort.number());
else {
if (m_useQmlDebugger) {
arguments.append(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices, arguments.append(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices,
m_qmlPort)); portsGatherer->qmlServerPort()));
} }
arguments.append(Utils::QtcProcess::splitArgs(r.commandLineArguments)); arguments.append(Utils::QtcProcess::splitArgs(r.commandLineArguments));
r.commandLineArguments = Utils::QtcProcess::joinArgs(arguments);
SimpleTargetRunner::start();
}
};
// QnxDebugSupport
QnxDebugSupport::QnxDebugSupport(RunControl *runControl)
: DebuggerRunTool(runControl)
{
setDisplayName("QnxDebugSupport");
appendMessage(tr("Preparing remote side..."), Utils::LogMessageFormat);
auto portsGatherer = new GdbServerPortsGatherer(runControl);
portsGatherer->setUseGdbServer(isCppDebugging());
portsGatherer->setUseQmlServer(isQmlDebugging());
auto debuggeeRunner = new QnxDebuggeeRunner(runControl);
debuggeeRunner->addDependency(portsGatherer);
auto slog2InfoRunner = new Slog2InfoRunner(runControl);
slog2InfoRunner->addDependency(debuggeeRunner);
addDependency(slog2InfoRunner);
}
void QnxDebugSupport::start()
{
auto portsGatherer = runControl()->worker<GdbServerPortsGatherer>();
Utils::Port pdebugPort = portsGatherer->gdbServerPort();
auto runConfig = qobject_cast<QnxRunConfiguration *>(runControl()->runConfiguration());
QTC_ASSERT(runConfig, return);
Target *target = runConfig->target();
Kit *k = target->kit();
DebuggerStartParameters params;
params.startMode = AttachToRemoteServer;
params.useCtrlCStub = true;
params.inferior.executable = runConfig->remoteExecutableFilePath();
params.symbolFile = runConfig->localExecutableFilePath();
params.remoteChannel = QString("%1:%2").arg(device()->sshParameters().host).arg(pdebugPort.number());
params.closeMode = KillAtClose;
params.inferior.commandLineArguments = runConfig->arguments();
if (isQmlDebugging()) {
params.qmlServer.host = device()->sshParameters().host;
params.qmlServer.port = portsGatherer->qmlServerPort();
params.inferior.commandLineArguments.replace("%qml_port%", params.qmlServer.port.toString());
} }
r.executable = processExecutable(); auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(k));
r.commandLineArguments = Utils::QtcProcess::joinArgs(arguments); if (qtVersion)
r.environment = m_runnable.environment; params.solibSearchPath = QnxUtils::searchPaths(qtVersion);
r.workingDirectory = m_runnable.workingDirectory;
appRunner()->start(r, device()); reportStarted();
} }
void QnxDebugSupport::handleRemoteProcessStarted() void QnxDebugSupport::stop()
{ {
QnxAbstractRunSupport::handleRemoteProcessStarted(); // We have to kill the inferior process, as invoking "kill" in
Debugger::RemoteSetupResult result; // gdb doesn't work on QNX gdb.
result.success = true; auto stdRunnable = runnable().as<StandardRunnable>();
result.gdbServerPort = m_pdebugPort; device()->signalOperation()->killProcess(stdRunnable.executable);
result.qmlServerPort = m_qmlPort;
toolRunner()->notifyEngineRemoteSetupFinished(result);
}
void QnxDebugSupport::handleRemoteProcessFinished(bool success)
{
if (state() == Inactive)
return;
if (state() == Running) {
if (!success)
toolRunner()->notifyInferiorIll();
} else {
Debugger::RemoteSetupResult result;
result.success = false;
result.reason = tr("The %1 process closed unexpectedly.").arg(processExecutable());
toolRunner()->notifyEngineRemoteSetupFinished(result);
}
}
void QnxDebugSupport::handleDebuggingFinished()
{
// setFinished() will kill "pdebug", but we also have to kill
// the inferior process, as invoking "kill" in gdb doesn't work
// on QNX gdb
setFinished();
m_slog2Info->stop();
killInferiorProcess();
}
QString QnxDebugSupport::processExecutable() const
{
return m_useCppDebugger? QLatin1String(Constants::QNX_DEBUG_EXECUTABLE) : m_runnable.executable;
}
void QnxDebugSupport::killInferiorProcess()
{
device()->signalOperation()->killProcess(m_runnable.executable);
}
void QnxDebugSupport::handleProgressReport(const QString &progressOutput)
{
toolRunner()->showMessage(progressOutput + QLatin1Char('\n'), Debugger::AppStuff);
}
void QnxDebugSupport::handleRemoteOutput(const QByteArray &output)
{
QTC_ASSERT(state() == Inactive || state() == Running, return);
toolRunner()->showMessage(QString::fromUtf8(output), Debugger::AppOutput);
}
void QnxDebugSupport::handleError(const QString &error)
{
if (state() == Running) {
toolRunner()->showMessage(error, Debugger::AppError);
toolRunner()->notifyInferiorIll();
} else if (state() != Inactive) {
setFinished();
Debugger::RemoteSetupResult result;
result.success = false;
result.reason = tr("Initial setup failed: %1").arg(error);
toolRunner()->notifyEngineRemoteSetupFinished(result);
}
}
void QnxDebugSupport::printMissingWarning()
{
toolRunner()->showMessage(tr("Warning: \"slog2info\" is not found "
"on the device, debug output not available."), Debugger::AppError);
}
void QnxDebugSupport::handleApplicationOutput(const QString &msg, Utils::OutputFormat outputFormat)
{
Q_UNUSED(outputFormat);
toolRunner()->showMessage(msg, Debugger::AppOutput);
}
Debugger::DebuggerRunTool *QnxDebugSupport::toolRunner()
{
return qobject_cast<Debugger::DebuggerRunTool *>(runControl()->toolRunner());
} }
} // namespace Internal } // namespace Internal

View File

@@ -25,55 +25,21 @@
#pragma once #pragma once
#include "qnxabstractrunsupport.h" #include <debugger/debuggerruncontrol.h>
#include <projectexplorer/runnables.h>
#include <utils/outputformat.h>
namespace Debugger { class DebuggerRunTool; }
namespace Qnx { namespace Qnx {
namespace Internal { namespace Internal {
class Slog2InfoRunner; class QnxDebugSupport : public Debugger::DebuggerRunTool
class QnxDebugSupport : public QnxAbstractRunSupport
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit QnxDebugSupport(ProjectExplorer::RunControl *runControl); explicit QnxDebugSupport(ProjectExplorer::RunControl *runControl);
void handleDebuggingFinished();
private: private:
void handleAdapterSetupRequested() override; void start() override;
void stop() override;
void handleRemoteProcessStarted() override;
void handleRemoteProcessFinished(bool success) override;
void handleProgressReport(const QString &progressOutput) override;
void handleRemoteOutput(const QByteArray &output) override;
void handleError(const QString &error) override;
void printMissingWarning();
void handleApplicationOutput(const QString &msg, Utils::OutputFormat outputFormat);
void startExecution() override;
Debugger::DebuggerRunTool *toolRunner();
QString processExecutable() const;
void killInferiorProcess();
ProjectExplorer::StandardRunnable m_runnable;
Slog2InfoRunner *m_slog2Info;
Utils::Port m_pdebugPort;
Utils::Port m_qmlPort;
bool m_useCppDebugger;
bool m_useQmlDebugger;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -1,72 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 BlackBerry Limited. All rights reserved.
** Contact: KDAB (info@kdab.com)
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "qnxruncontrol.h"
#include "qnxdevice.h"
#include "qnxrunconfiguration.h"
#include "slog2inforunner.h"
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
using namespace ProjectExplorer;
using namespace Utils;
namespace Qnx {
namespace Internal {
QnxRunControl::QnxRunControl(RunConfiguration *runConfig)
: RunControl(runConfig, ProjectExplorer::Constants::NORMAL_RUN_MODE)
, m_slog2Info(0)
{
IDevice::ConstPtr dev = DeviceKitInformation::device(runConfig->target()->kit());
QnxDevice::ConstPtr qnxDevice = dev.dynamicCast<const QnxDevice>();
QnxRunConfiguration *qnxRunConfig = qobject_cast<QnxRunConfiguration *>(runConfig);
QTC_CHECK(qnxRunConfig);
const QString applicationId = FileName::fromString(qnxRunConfig->remoteExecutableFilePath()).fileName();
m_slog2Info = new Slog2InfoRunner(applicationId, qnxDevice, this);
connect(m_slog2Info, &Slog2InfoRunner::output,
this, static_cast<void(RunControl::*)(const QString &, OutputFormat)>(&RunControl::appendMessage));
connect(this, &RunControl::started, m_slog2Info, &Slog2InfoRunner::start);
if (qnxDevice->qnxVersion() > 0x060500)
connect(m_slog2Info, &Slog2InfoRunner::commandMissing, this, &QnxRunControl::printMissingWarning);
}
void QnxRunControl::stop()
{
m_slog2Info->stop();
RunControl::stop();
}
void QnxRunControl::printMissingWarning()
{
appendMessage(tr("Warning: \"slog2info\" is not found on the device, debug output not available."), ErrorMessageFormat);
}
} // namespace Internal
} // namespace Qnx

View File

@@ -1,50 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 BlackBerry Limited. All rights reserved.
** Contact: KDAB (info@kdab.com)
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <projectexplorer/runconfiguration.h>
namespace Qnx {
namespace Internal {
class Slog2InfoRunner;
class QnxRunControl : public ProjectExplorer::RunControl
{
Q_OBJECT
public:
explicit QnxRunControl(ProjectExplorer::RunConfiguration *runConfig);
void stop() override;
private:
void printMissingWarning();
Slog2InfoRunner *m_slog2Info;
};
} // namespace Internal
} // namespace Qnx

View File

@@ -30,7 +30,7 @@
#include "qnxdevice.h" #include "qnxdevice.h"
#include "qnxanalyzesupport.h" #include "qnxanalyzesupport.h"
#include "qnxqtversion.h" #include "qnxqtversion.h"
#include "qnxruncontrol.h" #include "slog2inforunner.h"
#include "qnxutils.h" #include "qnxutils.h"
#include <debugger/debuggerruncontrol.h> #include <debugger/debuggerruncontrol.h>
@@ -53,38 +53,6 @@ using namespace ProjectExplorer;
namespace Qnx { namespace Qnx {
namespace Internal { namespace Internal {
static DebuggerStartParameters createDebuggerStartParameters(QnxRunConfiguration *runConfig)
{
DebuggerStartParameters params;
Target *target = runConfig->target();
Kit *k = target->kit();
const IDevice::ConstPtr device = DeviceKitInformation::device(k);
if (device.isNull())
return params;
params.startMode = AttachToRemoteServer;
params.useCtrlCStub = true;
params.inferior.executable = runConfig->remoteExecutableFilePath();
params.symbolFile = runConfig->localExecutableFilePath();
params.remoteChannel = device->sshParameters().host + QLatin1String(":-1");
params.remoteSetupNeeded = true;
params.closeMode = KillAtClose;
params.inferior.commandLineArguments = runConfig->arguments();
auto aspect = runConfig->extraAspect<DebuggerRunConfigurationAspect>();
if (aspect->useQmlDebugger()) {
params.qmlServer.host = device->sshParameters().host;
params.qmlServer.port = Utils::Port(); // QML port is handed out later
}
auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(k));
if (qtVersion)
params.solibSearchPath = QnxUtils::searchPaths(qtVersion);
return params;
}
QnxRunControlFactory::QnxRunControlFactory(QObject *parent) QnxRunControlFactory::QnxRunControlFactory(QObject *parent)
: IRunControlFactory(parent) : IRunControlFactory(parent)
{ {
@@ -108,48 +76,28 @@ bool QnxRunControlFactory::canRun(RunConfiguration *runConfiguration, Core::Id m
if (dev.isNull()) if (dev.isNull())
return false; return false;
if (mode == ProjectExplorer::Constants::DEBUG_RUN_MODE
|| mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) {
auto aspect = runConfiguration->extraAspect<DebuggerRunConfigurationAspect>();
int portsUsed = aspect ? aspect->portsUsedByDebugger() : 0;
return portsUsed <= dev->freePorts().count();
}
return true; return true;
} }
RunControl *QnxRunControlFactory::create(RunConfiguration *runConfig, Core::Id mode, QString *) RunControl *QnxRunControlFactory::create(RunConfiguration *runConfig, Core::Id mode, QString *)
{ {
QTC_ASSERT(canRun(runConfig, mode), return 0); QTC_ASSERT(canRun(runConfig, mode), return 0);
auto rc = qobject_cast<QnxRunConfiguration *>(runConfig);
QTC_ASSERT(rc, return 0);
if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE) { if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE) {
auto runControl = new QnxRunControl(rc); auto runControl = new RunControl(runConfig, mode);
(void) new SimpleTargetRunner(runControl); (void) new SimpleTargetRunner(runControl);
return runControl; return runControl;
} }
if (mode == ProjectExplorer::Constants::DEBUG_RUN_MODE) { if (mode == ProjectExplorer::Constants::DEBUG_RUN_MODE) {
const DebuggerStartParameters params = createDebuggerStartParameters(rc);
auto runControl = new RunControl(runConfig, mode); auto runControl = new RunControl(runConfig, mode);
// (void) new DebuggerRunTool(runControl, params, errorMessage); FIXME
(void) new QnxDebugSupport(runControl); (void) new QnxDebugSupport(runControl);
return runControl; return runControl;
} }
if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) {
Kit *kit = runConfig->target()->kit(); RunControl *runControl = new RunControl(runConfig, mode);
const IDevice::ConstPtr device = DeviceKitInformation::device(kit); runControl->createWorker(mode);
if (device.isNull())
return 0;
RunControl *runControl = Debugger::createAnalyzerRunControl(runConfig, mode);
QTC_ASSERT(runControl, return 0);
AnalyzerConnection connection;
connection.connParams = device->sshParameters();
connection.analyzerHost = connection.connParams.host;
connection.analyzerPort = Utils::Port(connection.connParams.port);
runControl->setConnection(connection);
(void) new QnxAnalyzeSupport(runControl); (void) new QnxAnalyzeSupport(runControl);
return runControl; return runControl;
} }

View File

@@ -25,7 +25,9 @@
#include "slog2inforunner.h" #include "slog2inforunner.h"
#include "qnxdevice.h"
#include "qnxdeviceprocess.h" #include "qnxdeviceprocess.h"
#include "qnxrunconfiguration.h"
#include <projectexplorer/runnables.h> #include <projectexplorer/runnables.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -33,28 +35,33 @@
#include <QRegExp> #include <QRegExp>
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils;
namespace Qnx { namespace Qnx {
namespace Internal { namespace Internal {
Slog2InfoRunner::Slog2InfoRunner(const QString &applicationId, Slog2InfoRunner::Slog2InfoRunner(RunControl *runControl)
const RemoteLinux::LinuxDevice::ConstPtr &device, QObject *parent) : RunWorker(runControl)
: QObject(parent)
, m_applicationId(applicationId)
, m_found(false)
, m_currentLogs(false)
{ {
auto qnxRunConfig = qobject_cast<QnxRunConfiguration *>(runControl->runConfiguration());
QTC_ASSERT(qnxRunConfig, return);
m_applicationId = FileName::fromString(qnxRunConfig->remoteExecutableFilePath()).fileName();
}
void Slog2InfoRunner::printMissingWarning()
{
appendMessage(tr("Warning: \"slog2info\" is not found on the device, debug output not available."), ErrorMessageFormat);
// See QTCREATORBUG-10712 for details. // See QTCREATORBUG-10712 for details.
// We need to limit length of ApplicationId to 63 otherwise it would not match one in slog2info. // We need to limit length of ApplicationId to 63 otherwise it would not match one in slog2info.
m_applicationId.truncate(63); m_applicationId.truncate(63);
m_testProcess = new QnxDeviceProcess(device, this); m_testProcess = new QnxDeviceProcess(device(), this);
connect(m_testProcess, &DeviceProcess::finished, this, &Slog2InfoRunner::handleTestProcessCompleted); connect(m_testProcess, &DeviceProcess::finished, this, &Slog2InfoRunner::handleTestProcessCompleted);
m_launchDateTimeProcess = new SshDeviceProcess(device, this); m_launchDateTimeProcess = new SshDeviceProcess(device(), this);
connect(m_launchDateTimeProcess, &DeviceProcess::finished, this, &Slog2InfoRunner::launchSlog2Info); connect(m_launchDateTimeProcess, &DeviceProcess::finished, this, &Slog2InfoRunner::launchSlog2Info);
m_logProcess = new QnxDeviceProcess(device, this); m_logProcess = new QnxDeviceProcess(device(), this);
connect(m_logProcess, &DeviceProcess::readyReadStandardOutput, this, &Slog2InfoRunner::readLogStandardOutput); connect(m_logProcess, &DeviceProcess::readyReadStandardOutput, this, &Slog2InfoRunner::readLogStandardOutput);
connect(m_logProcess, &DeviceProcess::readyReadStandardError, this, &Slog2InfoRunner::readLogStandardError); connect(m_logProcess, &DeviceProcess::readyReadStandardError, this, &Slog2InfoRunner::readLogStandardError);
connect(m_logProcess, &DeviceProcess::error, this, &Slog2InfoRunner::handleLogError); connect(m_logProcess, &DeviceProcess::error, this, &Slog2InfoRunner::handleLogError);
@@ -88,10 +95,14 @@ bool Slog2InfoRunner::commandFound() const
void Slog2InfoRunner::handleTestProcessCompleted() void Slog2InfoRunner::handleTestProcessCompleted()
{ {
m_found = (m_testProcess->exitCode() == 0); m_found = (m_testProcess->exitCode() == 0);
if (m_found) if (m_found) {
readLaunchTime(); readLaunchTime();
else } else {
emit commandMissing(); QnxDevice::ConstPtr qnxDevice = device().dynamicCast<const QnxDevice>();
if (qnxDevice->qnxVersion() > 0x060500) {
printMissingWarning();
}
}
} }
void Slog2InfoRunner::readLaunchTime() void Slog2InfoRunner::readLaunchTime()
@@ -174,18 +185,18 @@ void Slog2InfoRunner::processLogLine(const QString &line)
if (bufferName == QLatin1String("default") && bufferId == 8900) if (bufferName == QLatin1String("default") && bufferId == 8900)
return; return;
emit output(regexp.cap(6).trimmed() + QLatin1Char('\n'), Utils::StdOutFormat); appendMessage(regexp.cap(6).trimmed() + '\n', Utils::StdOutFormat);
} }
void Slog2InfoRunner::readLogStandardError() void Slog2InfoRunner::readLogStandardError()
{ {
const QString message = QString::fromLatin1(m_logProcess->readAllStandardError()); appendMessage(QString::fromLatin1(m_logProcess->readAllStandardError()), Utils::StdErrFormat);
emit output(message, Utils::StdErrFormat);
} }
void Slog2InfoRunner::handleLogError() void Slog2InfoRunner::handleLogError()
{ {
emit output(tr("Cannot show slog2info output. Error: %1").arg(m_logProcess->errorString()), Utils::StdErrFormat); appendMessage(tr("Cannot show slog2info output. Error: %1")
.arg(m_logProcess->errorString()), Utils::StdErrFormat);
} }
} // namespace Internal } // namespace Internal

View File

@@ -27,6 +27,7 @@
#include <QObject> #include <QObject>
#include <projectexplorer/runconfiguration.h>
#include <remotelinux/linuxdevice.h> #include <remotelinux/linuxdevice.h>
#include <utils/outputformat.h> #include <utils/outputformat.h>
@@ -38,26 +39,23 @@ namespace ProjectExplorer { class SshDeviceProcess; }
namespace Qnx { namespace Qnx {
namespace Internal { namespace Internal {
class Slog2InfoRunner : public QObject class Slog2InfoRunner : public ProjectExplorer::RunWorker
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit Slog2InfoRunner(const QString &applicationId, const RemoteLinux::LinuxDevice::ConstPtr &device, QObject *parent = 0); explicit Slog2InfoRunner(ProjectExplorer::RunControl *runControl);
void stop(); void start() override;
void stop() override;
bool commandFound() const; bool commandFound() const;
public slots:
void start();
signals: signals:
void commandMissing(); void commandMissing();
void started(); void started();
void finished(); void finished();
void output(const QString &msg, Utils::OutputFormat format);
private slots: private:
void handleTestProcessCompleted(); void handleTestProcessCompleted();
void launchSlog2Info(); void launchSlog2Info();
@@ -65,22 +63,21 @@ private slots:
void readLogStandardError(); void readLogStandardError();
void handleLogError(); void handleLogError();
private: void printMissingWarning();
void readLaunchTime(); void readLaunchTime();
void processLog(bool force); void processLog(bool force);
void processLogLine(const QString &line); void processLogLine(const QString &line);
QString m_applicationId; QString m_applicationId;
bool m_found;
QDateTime m_launchDateTime; QDateTime m_launchDateTime;
bool m_currentLogs; bool m_found = false;
bool m_currentLogs = false;
QString m_remainingData; QString m_remainingData;
ProjectExplorer::SshDeviceProcess *m_launchDateTimeProcess; ProjectExplorer::SshDeviceProcess *m_launchDateTimeProcess = nullptr;
ProjectExplorer::SshDeviceProcess *m_testProcess; ProjectExplorer::SshDeviceProcess *m_testProcess = nullptr;
ProjectExplorer::SshDeviceProcess *m_logProcess; ProjectExplorer::SshDeviceProcess *m_logProcess = nullptr;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -25,89 +25,34 @@
#include "abstractremotelinuxrunsupport.h" #include "abstractremotelinuxrunsupport.h"
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <projectexplorer/kitinformation.h> #include <projectexplorer/kitinformation.h>
#include <projectexplorer/runnables.h> #include <projectexplorer/runnables.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <utils/environment.h> #include <utils/environment.h>
#include <utils/portlist.h> #include <utils/portlist.h>
#include <utils/qtcprocess.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
namespace RemoteLinux { namespace RemoteLinux {
namespace Internal {
class AbstractRemoteLinuxRunSupportPrivate // FifoGatherer
FifoGatherer::FifoGatherer(RunControl *runControl)
: RunWorker(runControl)
{ {
public: setDisplayName("FifoGatherer");
ApplicationLauncher launcher; }
DeviceUsedPortsGatherer portsGatherer;
ApplicationLauncher fifoCreator;
PortList portList;
QString fifo;
bool usesFifo = false;
};
} // namespace Internal FifoGatherer::~FifoGatherer()
using namespace Internal;
AbstractRemoteLinuxRunSupport::AbstractRemoteLinuxRunSupport(RunControl *runControl)
: TargetRunner(runControl),
d(new AbstractRemoteLinuxRunSupportPrivate)
{ {
} }
AbstractRemoteLinuxRunSupport::~AbstractRemoteLinuxRunSupport() void FifoGatherer::start()
{
delete d;
}
ApplicationLauncher *AbstractRemoteLinuxRunSupport::applicationLauncher()
{
return &d->launcher;
}
void AbstractRemoteLinuxRunSupport::setUsesFifo(bool on)
{
d->usesFifo = on;
}
Port AbstractRemoteLinuxRunSupport::findPort() const
{
return d->portsGatherer.getNextFreePort(&d->portList);
}
QString AbstractRemoteLinuxRunSupport::fifo() const
{
return d->fifo;
}
void AbstractRemoteLinuxRunSupport::prepare()
{
if (d->usesFifo)
createRemoteFifo();
else
startPortsGathering();
}
void AbstractRemoteLinuxRunSupport::startPortsGathering()
{
appendMessage(tr("Checking available ports...") + '\n', NormalMessageFormat);
connect(&d->portsGatherer, &DeviceUsedPortsGatherer::error, this, [&](const QString &msg) {
reportFailure(msg);
});
connect(&d->portsGatherer, &DeviceUsedPortsGatherer::portListReady, this, [&] {
d->portList = device()->freePorts();
//appendMessage(tr("Found %1 free ports").arg(d->portList.count()), NormalMessageFormat);
reportSuccess();
});
d->portsGatherer.start(device());
}
void AbstractRemoteLinuxRunSupport::createRemoteFifo()
{ {
appendMessage(tr("Creating remote socket...") + '\n', NormalMessageFormat); appendMessage(tr("Creating remote socket...") + '\n', NormalMessageFormat);
@@ -120,77 +65,35 @@ void AbstractRemoteLinuxRunSupport::createRemoteFifo()
QSharedPointer<QByteArray> output(new QByteArray); QSharedPointer<QByteArray> output(new QByteArray);
QSharedPointer<QByteArray> errors(new QByteArray); QSharedPointer<QByteArray> errors(new QByteArray);
connect(&d->fifoCreator, &ApplicationLauncher::finished, connect(&m_fifoCreator, &ApplicationLauncher::finished,
this, [this, output, errors](bool success) { this, [this, output, errors](bool success) {
if (!success) { if (!success) {
reportFailure(QString("Failed to create fifo: %1").arg(QLatin1String(*errors))); reportFailure(QString("Failed to create fifo: %1").arg(QLatin1String(*errors)));
} else { } else {
d->fifo = QString::fromLatin1(*output); m_fifo = QString::fromLatin1(*output);
//appendMessage(tr("Created fifo").arg(d->fifo), NormalMessageFormat); appendMessage(tr("Created fifo: %1").arg(m_fifo), NormalMessageFormat);
reportSuccess(); reportStarted();
} }
}); });
connect(&d->fifoCreator, &ApplicationLauncher::remoteStdout, connect(&m_fifoCreator, &ApplicationLauncher::remoteStdout,
this, [output](const QByteArray &data) { this, [output](const QByteArray &data) {
output->append(data); output->append(data);
}); });
connect(&d->fifoCreator, &ApplicationLauncher::remoteStderr, connect(&m_fifoCreator, &ApplicationLauncher::remoteStderr,
this, [errors](const QByteArray &data) { this, [this, errors](const QByteArray &) {
errors->append(data); reportFailure();
// errors->append(data);
}); });
d->fifoCreator.start(r, device()); m_fifoCreator.start(r, device());
} }
void AbstractRemoteLinuxRunSupport::start() void FifoGatherer::onFinished()
{ {
connect(&d->launcher, &ApplicationLauncher::remoteStderr, m_fifoCreator.stop();
this, &AbstractRemoteLinuxRunSupport::handleRemoteErrorOutput);
connect(&d->launcher, &ApplicationLauncher::remoteStdout,
this, &AbstractRemoteLinuxRunSupport::handleRemoteOutput);
connect(&d->launcher, &ApplicationLauncher::finished,
this, &AbstractRemoteLinuxRunSupport::handleAppRunnerFinished);
connect(&d->launcher, &ApplicationLauncher::reportProgress,
this, &AbstractRemoteLinuxRunSupport::handleProgressReport);
connect(&d->launcher, &ApplicationLauncher::reportError,
this, &AbstractRemoteLinuxRunSupport::handleAppRunnerError);
connect(&d->launcher, &ApplicationLauncher::remoteProcessStarted,
this, &TargetRunner::reportSuccess);
d->launcher.start(runControl()->runnable(), device());
} }
void AbstractRemoteLinuxRunSupport::onFinished()
{
d->launcher.disconnect(this);
d->launcher.stop();
d->portsGatherer.disconnect(this);
}
void AbstractRemoteLinuxRunSupport::handleAppRunnerFinished(bool success)
{
success ? reportStopped() : reportFailure();
}
void AbstractRemoteLinuxRunSupport::handleAppRunnerError(const QString &error)
{
reportFailure(error);
}
void AbstractRemoteLinuxRunSupport::handleRemoteOutput(const QByteArray &output)
{
appendMessage(QString::fromUtf8(output), StdOutFormat);
}
void AbstractRemoteLinuxRunSupport::handleRemoteErrorOutput(const QByteArray &output)
{
appendMessage(QString::fromUtf8(output), StdErrFormat);
}
void AbstractRemoteLinuxRunSupport::handleProgressReport(const QString &progressOutput)
{
appendMessage(progressOutput + '\n', LogMessageFormat);
}
} // namespace RemoteLinux } // namespace RemoteLinux

View File

@@ -27,46 +27,28 @@
#include "remotelinux_export.h" #include "remotelinux_export.h"
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/runconfiguration.h> #include <projectexplorer/runconfiguration.h>
#include <utils/port.h>
namespace RemoteLinux { namespace RemoteLinux {
namespace Internal { class AbstractRemoteLinuxRunSupportPrivate; } class REMOTELINUX_EXPORT FifoGatherer : public ProjectExplorer::RunWorker
class REMOTELINUX_EXPORT AbstractRemoteLinuxRunSupport : public ProjectExplorer::TargetRunner
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AbstractRemoteLinuxRunSupport(ProjectExplorer::RunControl *runControl); explicit FifoGatherer(ProjectExplorer::RunControl *runControl);
~AbstractRemoteLinuxRunSupport(); ~FifoGatherer();
ProjectExplorer::ApplicationLauncher *applicationLauncher(); QString fifo() const { return m_fifo; }
void setUsesFifo(bool on);
Utils::Port findPort() const;
QString fifo() const;
private: private:
void prepare() override;
void start() override; void start() override;
void onFinished() override; void onFinished() override;
void createRemoteFifo(); void createRemoteFifo();
void startPortsGathering();
void handleAppRunnerError(const QString &error); ProjectExplorer::ApplicationLauncher m_fifoCreator;
void handleRemoteOutput(const QByteArray &output); QString m_fifo;
void handleRemoteErrorOutput(const QByteArray &output);
void handleAppRunnerFinished(bool success);
void handleProgressReport(const QString &progressOutput);
void handleAdapterSetupDone();
Internal::AbstractRemoteLinuxRunSupportPrivate * const d;
}; };
} // namespace RemoteLinux } // namespace RemoteLinux

View File

@@ -1,210 +1,172 @@
/**************************************************************************** ///****************************************************************************
** //**
** Copyright (C) 2016 The Qt Company Ltd. //** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ //** Contact: https://www.qt.io/licensing/
** //**
** This file is part of Qt Creator. //** This file is part of Qt Creator.
** //**
** Commercial License Usage //** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in //** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the //** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in //** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms //** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further //** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us. //** information use the contact form at https://www.qt.io/contact-us.
** //**
** GNU General Public License Usage //** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU //** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software //** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT //** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following //** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will //** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html. //** be met: https://www.gnu.org/licenses/gpl-3.0.html.
** //**
****************************************************************************/ //****************************************************************************/
#include "remotelinuxanalyzesupport.h" //#include "remotelinuxanalyzesupport.h"
#include "remotelinuxrunconfiguration.h" //#include "remotelinuxrunconfiguration.h"
#include <projectexplorer/buildconfiguration.h> //#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h> //#include <projectexplorer/project.h>
#include <projectexplorer/target.h> //#include <projectexplorer/target.h>
#include <projectexplorer/toolchain.h> //#include <projectexplorer/toolchain.h>
#include <projectexplorer/kitinformation.h> //#include <projectexplorer/kitinformation.h>
#include <projectexplorer/runnables.h> //#include <projectexplorer/runnables.h>
#include <utils/qtcassert.h> //#include <utils/qtcassert.h>
#include <utils/qtcprocess.h> //#include <utils/qtcprocess.h>
#include <qmldebug/qmloutputparser.h> //#include <qmldebug/qmloutputparser.h>
#include <qmldebug/qmldebugcommandlinearguments.h> //#include <qmldebug/qmldebugcommandlinearguments.h>
#include <QPointer> //#include <QPointer>
using namespace QSsh; //using namespace QSsh;
using namespace ProjectExplorer; //using namespace ProjectExplorer;
using namespace Utils; //using namespace Utils;
namespace RemoteLinux { //namespace RemoteLinux {
namespace Internal { //namespace Internal {
class RemoteLinuxAnalyzeSupportPrivate //const char RemoteLinuxAnalyzeSupportWorkerId[] = "RemoteLinux.AnalyzeSupportWorker";
{
public:
RemoteLinuxAnalyzeSupportPrivate(RunControl *runControl)
{
if (runControl->runMode() == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) {
usesFifo = true;
RunConfiguration *runConfiguration = runControl->runConfiguration();
QTC_ASSERT(runConfiguration, return);
IRunConfigurationAspect *perfAspect =
runConfiguration->extraAspect("Analyzer.Perf.Settings");
QTC_ASSERT(perfAspect, return);
perfRecordArguments =
perfAspect->currentSettings()->property("perfRecordArguments").toStringList()
.join(' ');
}
}
Utils::Port qmlPort; //class RemoteLinuxAnalyzeSupportPrivate
QString remoteFifo; //{
QString perfRecordArguments; //public:
// RemoteLinuxAnalyzeSupportPrivate(RunControl *runControl)
// {
// bool isPerf = runControl->runMode() == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE;
// needFifo = isPerf;
// if (needFifo) {
// RunConfiguration *runConfiguration = runControl->runConfiguration();
// QTC_ASSERT(runConfiguration, return);
// IRunConfigurationAspect *perfAspect =
// runConfiguration->extraAspect("Analyzer.Perf.Settings");
// QTC_ASSERT(perfAspect, return);
// perfRecordArguments =
// perfAspect->currentSettings()->property("perfRecordArguments").toStringList()
// .join(' ');
// }
// }
ApplicationLauncher outputGatherer; // Utils::Port qmlPort;
QmlDebug::QmlOutputParser outputParser; // QString remoteFifo;
bool usesFifo = false; // QString perfRecordArguments;
};
} // namespace Internal // ApplicationLauncher outputGatherer;
// QmlDebug::QmlOutputParser outputParser;
// bool needFifo = false;
// bool needPort = false;
//};
using namespace Internal; //} // namespace Internal
RemoteLinuxAnalyzeSupport::RemoteLinuxAnalyzeSupport(RunControl *runControl) //using namespace Internal;
: ToolRunner(runControl),
d(new RemoteLinuxAnalyzeSupportPrivate(runControl))
{
connect(&d->outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort,
this, &RemoteLinuxAnalyzeSupport::remoteIsRunning);
targetRunner()->setUsesFifo(runControl->runMode() == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE);
}
RemoteLinuxAnalyzeSupport::~RemoteLinuxAnalyzeSupport() //RemoteLinuxAnalyzeSupport::RemoteLinuxAnalyzeSupport(RunControl *runControl)
{ // : ToolRunner(runControl),
delete d; // d(new RemoteLinuxAnalyzeSupportPrivate(runControl))
} //{
// setId(RemoteLinuxAnalyzeSupportWorkerId);
void RemoteLinuxAnalyzeSupport::showMessage(const QString &msg, Utils::OutputFormat format) // connect(&d->outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort,
{ // this, &RemoteLinuxAnalyzeSupport::remoteIsRunning);
appendMessage(msg, format);
d->outputParser.processOutput(msg);
}
void RemoteLinuxAnalyzeSupport::start() // if (d->needFifo)
{ // addDependency(FifoCreatorWorkerId);
const Core::Id runMode = runControl()->runMode(); // if (d->needPort)
if (runMode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { // addDependency(PortsGathererWorkerId);
d->qmlPort = targetRunner()->findPort(); //}
if (!d->qmlPort.isValid()) {
reportFailure(tr("Not enough free ports on device for profiling."));
return;
}
} else if (runMode == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) {
d->remoteFifo = targetRunner()->fifo();
if (d->remoteFifo.isEmpty()) {
reportFailure(tr("FIFO for profiling data could not be created."));
return;
}
}
ApplicationLauncher *runner = targetRunner()->applicationLauncher(); //RemoteLinuxAnalyzeSupport::~RemoteLinuxAnalyzeSupport()
connect(runner, &ApplicationLauncher::remoteStderr, //{
this, &RemoteLinuxAnalyzeSupport::handleRemoteErrorOutput); // delete d;
connect(runner, &ApplicationLauncher::remoteStdout, //}
this, &RemoteLinuxAnalyzeSupport::handleRemoteOutput);
connect(runner, &ApplicationLauncher::remoteProcessStarted,
this, &RemoteLinuxAnalyzeSupport::handleRemoteProcessStarted);
connect(runner, &ApplicationLauncher::finished,
this, &RemoteLinuxAnalyzeSupport::handleAppRunnerFinished);
connect(runner, &ApplicationLauncher::reportProgress,
this, &RemoteLinuxAnalyzeSupport::handleProgressReport);
connect(runner, &ApplicationLauncher::reportError,
this, &RemoteLinuxAnalyzeSupport::handleAppRunnerError);
auto r = runControl()->runnable().as<StandardRunnable>(); ////void RemoteLinuxAnalyzeSupport::showMessage(const QString &msg, Utils::OutputFormat format)
////{
//// appendMessage(msg, format);
//// d->outputParser.processOutput(msg);
////}
if (runMode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { //void RemoteLinuxAnalyzeSupport::start()
if (!r.commandLineArguments.isEmpty()) //{
r.commandLineArguments.append(QLatin1Char(' ')); // if (d->needPort) {
r.commandLineArguments += QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlProfilerServices, // RunWorker *worker = qobject_cast<PortsGatherer>();
d->qmlPort); // QTC_ASSERT(worker, reportFailure(); return);
} else if (runMode == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) { // runControl()->worker(PortsGathererWorkerId)->result();
r.commandLineArguments = QLatin1String("-c 'perf record -o - ") + d->perfRecordArguments // d->qmlPort = targetRunner()->findPort();
+ QLatin1String(" -- ") + r.executable + QLatin1String(" ") // if (!d->qmlPort.isValid()) {
+ r.commandLineArguments + QLatin1String(" > ") + d->remoteFifo // reportFailure(tr("Not enough free ports on device for profiling."));
+ QLatin1String("'"); // return;
r.executable = QLatin1String("sh"); // }
// } else if (runMode == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) {
// d->remoteFifo = targetRunner()->fifo();
// if (d->remoteFifo.isEmpty()) {
// reportFailure(tr("FIFO for profiling data could not be created."));
// return;
// }
// }
connect(&d->outputGatherer, SIGNAL(remoteStdout(QByteArray)), // ApplicationLauncher *runner = targetRunner()->applicationLauncher();
runControl(), SIGNAL(analyzePerfOutput(QByteArray)));
connect(&d->outputGatherer, SIGNAL(finished(bool)),
runControl(), SIGNAL(perfFinished()));
StandardRunnable outputRunner; // auto r = runControl()->runnable().as<StandardRunnable>();
outputRunner.executable = QLatin1String("sh");
outputRunner.commandLineArguments =
QString::fromLatin1("-c 'cat %1 && rm -r `dirname %1`'").arg(d->remoteFifo);
d->outputGatherer.start(outputRunner, device());
remoteIsRunning();
}
runner->start(r, device());
}
void RemoteLinuxAnalyzeSupport::handleAppRunnerError(const QString &error) // if (runMode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) {
{ // if (!r.commandLineArguments.isEmpty())
showMessage(error, Utils::ErrorMessageFormat); // r.commandLineArguments.append(QLatin1Char(' '));
reportFailure(error); // r.commandLineArguments += QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlProfilerServices,
} // d->qmlPort);
// } else if (runMode == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) {
// r.commandLineArguments = QLatin1String("-c 'perf record -o - ") + d->perfRecordArguments
// + QLatin1String(" -- ") + r.executable + QLatin1String(" ")
// + r.commandLineArguments + QLatin1String(" > ") + d->remoteFifo
// + QLatin1String("'");
// r.executable = QLatin1String("sh");
void RemoteLinuxAnalyzeSupport::handleAppRunnerFinished(bool success) // connect(&d->outputGatherer, SIGNAL(remoteStdout(QByteArray)),
{ // runControl(), SIGNAL(analyzePerfOutput(QByteArray)));
// reset needs to be called first to ensure that the correct state is set. // connect(&d->outputGatherer, SIGNAL(finished(bool)),
if (!success) // runControl(), SIGNAL(perfFinished()));
showMessage(tr("Failure running remote process."), Utils::NormalMessageFormat);
runControl()->notifyRemoteFinished();
}
void RemoteLinuxAnalyzeSupport::remoteIsRunning() // StandardRunnable outputRunner;
{ // outputRunner.executable = QLatin1String("sh");
runControl()->notifyRemoteSetupDone(d->qmlPort); // outputRunner.commandLineArguments =
} // QString::fromLatin1("-c 'cat %1 && rm -r `dirname %1`'").arg(d->remoteFifo);
// d->outputGatherer.start(outputRunner, device());
// remoteIsRunning();
// }
// runner->start(r, device());
//}
AbstractRemoteLinuxRunSupport *RemoteLinuxAnalyzeSupport::targetRunner() const //void RemoteLinuxAnalyzeSupport::remoteIsRunning()
{ //{
return qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl()->targetRunner()); // runControl()->notifyRemoteSetupDone(d->qmlPort);
} //}
void RemoteLinuxAnalyzeSupport::handleRemoteOutput(const QByteArray &output) //AbstractRemoteLinuxRunSupport *RemoteLinuxAnalyzeSupport::targetRunner() const
{ //{
showMessage(QString::fromUtf8(output), Utils::StdOutFormat); // return qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl()->targetRunner());
} //}
void RemoteLinuxAnalyzeSupport::handleRemoteErrorOutput(const QByteArray &output) //} // namespace RemoteLinux
{
showMessage(QString::fromUtf8(output), Utils::StdErrFormat);
}
void RemoteLinuxAnalyzeSupport::handleProgressReport(const QString &progressOutput)
{
showMessage(progressOutput + QLatin1Char('\n'), Utils::NormalMessageFormat);
}
void RemoteLinuxAnalyzeSupport::handleAdapterSetupFailed(const QString &error)
{
showMessage(tr("Initial setup failed: %1").arg(error), Utils::NormalMessageFormat);
}
void RemoteLinuxAnalyzeSupport::handleRemoteProcessStarted()
{
}
} // namespace RemoteLinux

View File

@@ -1,67 +1,54 @@
/**************************************************************************** ///****************************************************************************
** //**
** Copyright (C) 2016 The Qt Company Ltd. //** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ //** Contact: https://www.qt.io/licensing/
** //**
** This file is part of Qt Creator. //** This file is part of Qt Creator.
** //**
** Commercial License Usage //** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in //** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the //** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in //** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms //** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further //** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us. //** information use the contact form at https://www.qt.io/contact-us.
** //**
** GNU General Public License Usage //** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU //** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software //** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT //** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following //** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will //** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html. //** be met: https://www.gnu.org/licenses/gpl-3.0.html.
** //**
****************************************************************************/ //****************************************************************************/
#pragma once //#pragma once
#include "abstractremotelinuxrunsupport.h" //#include "abstractremotelinuxrunsupport.h"
#include <projectexplorer/projectexplorerconstants.h> //#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfiguration.h> //#include <projectexplorer/runconfiguration.h>
#include <utils/outputformat.h> //#include <utils/outputformat.h>
namespace RemoteLinux { //namespace RemoteLinux {
namespace Internal { class RemoteLinuxAnalyzeSupportPrivate; } //namespace Internal { class RemoteLinuxAnalyzeSupportPrivate; }
class REMOTELINUX_EXPORT RemoteLinuxAnalyzeSupport : public ProjectExplorer::ToolRunner //class REMOTELINUX_EXPORT RemoteLinuxAnalyzeSupport : public ProjectExplorer::RunWorker
{ //{
Q_OBJECT // Q_OBJECT
public: //public:
RemoteLinuxAnalyzeSupport(ProjectExplorer::RunControl *runControl); // RemoteLinuxAnalyzeSupport(ProjectExplorer::RunControl *runControl);
~RemoteLinuxAnalyzeSupport() override; // ~RemoteLinuxAnalyzeSupport() override;
private: //private:
void start() override; // void start() override;
void handleAdapterSetupFailed(const QString &error);
void handleRemoteSetupRequested(); // void remoteIsRunning();
void handleAppRunnerError(const QString &error);
void handleRemoteOutput(const QByteArray &output);
void handleRemoteErrorOutput(const QByteArray &output);
void handleAppRunnerFinished(bool success);
void handleProgressReport(const QString &progressOutput);
void handleRemoteProcessStarted(); // Internal::RemoteLinuxAnalyzeSupportPrivate * const d;
//};
void remoteIsRunning(); //} // namespace RemoteLinux
AbstractRemoteLinuxRunSupport *targetRunner() const;
void showMessage(const QString &, Utils::OutputFormat);
Internal::RemoteLinuxAnalyzeSupportPrivate * const d;
};
} // namespace RemoteLinux

View File

@@ -47,10 +47,35 @@ using namespace Utils;
namespace RemoteLinux { namespace RemoteLinux {
LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl, QString *errorMessage) LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl)
: DebuggerRunTool(runControl) : DebuggerRunTool(runControl)
{ {
RunConfiguration *runConfig = runControl->runConfiguration(); setDisplayName("DebugSupport");
auto portsGatherer = new GdbServerPortsGatherer(runControl);
portsGatherer->setUseGdbServer(isCppDebugging());
portsGatherer->setUseQmlServer(isQmlDebugging());
auto gdbServer = new GdbServerRunner(runControl);
gdbServer->addDependency(portsGatherer);
addDependency(gdbServer);
}
LinuxDeviceDebugSupport::~LinuxDeviceDebugSupport()
{
}
void LinuxDeviceDebugSupport::start()
{
auto portsGatherer = runControl()->worker<GdbServerPortsGatherer>();
QTC_ASSERT(portsGatherer, reportFailure(); return);
const QString host = device()->sshParameters().host;
const Port gdbServerPort = portsGatherer->gdbServerPort();
const Port qmlServerPort = portsGatherer->qmlServerPort();
RunConfiguration *runConfig = runControl()->runConfiguration();
QString symbolFile; QString symbolFile;
if (auto rlrc = qobject_cast<RemoteLinuxRunConfiguration *>(runConfig)) if (auto rlrc = qobject_cast<RemoteLinuxRunConfiguration *>(runConfig))
@@ -58,7 +83,7 @@ LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl, QString
if (auto rlrc = qobject_cast<Internal::RemoteLinuxCustomRunConfiguration *>(runConfig)) if (auto rlrc = qobject_cast<Internal::RemoteLinuxCustomRunConfiguration *>(runConfig))
symbolFile = rlrc->localExecutableFilePath(); symbolFile = rlrc->localExecutableFilePath();
if (symbolFile.isEmpty()) { if (symbolFile.isEmpty()) {
*errorMessage = tr("Cannot debug: Local executable is not set."); // *errorMessage = tr("Cannot debug: Local executable is not set.");
return; return;
} }
@@ -68,8 +93,10 @@ LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl, QString
params.remoteSetupNeeded = false; params.remoteSetupNeeded = false;
if (isQmlDebugging()) { if (isQmlDebugging()) {
params.qmlServer.host = device()->sshParameters().host; params.qmlServer.host = host;
params.qmlServer.port = Utils::Port(); // port is selected later on params.qmlServer.port = qmlServerPort;
params.inferior.commandLineArguments.replace("%qml_port%",
QString::number(qmlServerPort.number()));
} }
if (isCppDebugging()) { if (isCppDebugging()) {
Runnable r = runnable(); Runnable r = runnable();
@@ -83,69 +110,14 @@ LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl, QString
params.inferior.commandLineArguments.prepend( params.inferior.commandLineArguments.prepend(
QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices)); QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices));
} }
params.remoteChannel = device()->sshParameters().host + ":-1";
params.remoteChannel = QString("%1:%2").arg(host).arg(gdbServerPort.number());
params.symbolFile = symbolFile; params.symbolFile = symbolFile;
} }
setStartParameters(params); setStartParameters(params);
}
LinuxDeviceDebugSupport::~LinuxDeviceDebugSupport() DebuggerRunTool::start();
{
}
void LinuxDeviceDebugSupport::prepare()
{
auto targetRunner = qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl()->targetRunner());
if (isCppDebugging()) {
m_gdbServerPort = targetRunner->findPort();
if (!m_gdbServerPort.isValid()) {
reportFailure(tr("Not enough free ports on device for C++ debugging."));
return;
}
}
if (isQmlDebugging()) {
m_qmlPort = targetRunner->findPort();
if (!m_qmlPort.isValid()) {
reportFailure(tr("Not enough free ports on device for QML debugging."));
return;
}
}
runControl()->setRunnable(realRunnable());
RemoteSetupResult result;
result.success = true;
result.gdbServerPort = m_gdbServerPort;
result.qmlServerPort = m_qmlPort;
setRemoteParameters(result);
DebuggerRunTool::prepare();
}
Runnable LinuxDeviceDebugSupport::realRunnable() const
{
StandardRunnable r = runControl()->runnable().as<StandardRunnable>();
QStringList args = QtcProcess::splitArgs(r.commandLineArguments, OsTypeLinux);
QString command;
if (isQmlDebugging())
args.prepend(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices, m_qmlPort));
if (isQmlDebugging() && !isCppDebugging()) {
command = r.executable;
} else {
command = device()->debugServerPath();
if (command.isEmpty())
command = QLatin1String("gdbserver");
args.clear();
args.append(QString::fromLatin1("--multi"));
args.append(QString::fromLatin1(":%1").arg(m_gdbServerPort.number()));
}
r.executable = command;
r.commandLineArguments = QtcProcess::joinArgs(args, OsTypeLinux);
return r;
} }
} // namespace RemoteLinux } // namespace RemoteLinux

View File

@@ -36,18 +36,11 @@ class REMOTELINUX_EXPORT LinuxDeviceDebugSupport : public Debugger::DebuggerRunT
Q_OBJECT Q_OBJECT
public: public:
LinuxDeviceDebugSupport(ProjectExplorer::RunControl *runControl, LinuxDeviceDebugSupport(ProjectExplorer::RunControl *runControl);
QString *errorMessage = nullptr);
~LinuxDeviceDebugSupport() override; ~LinuxDeviceDebugSupport() override;
protected:
virtual ProjectExplorer::Runnable realRunnable() const;
private: private:
void prepare() override; void start() override;
Utils::Port m_gdbServerPort;
Utils::Port m_qmlPort;
}; };
} // namespace RemoteLinux } // namespace RemoteLinux

View File

@@ -30,18 +30,12 @@
#include "remotelinuxcustomrunconfiguration.h" #include "remotelinuxcustomrunconfiguration.h"
#include "remotelinuxrunconfiguration.h" #include "remotelinuxrunconfiguration.h"
#include <debugger/analyzer/analyzermanager.h>
#include <debugger/analyzer/analyzerstartparameters.h>
#include <debugger/debuggerruncontrol.h> #include <debugger/debuggerruncontrol.h>
#include <debugger/debuggerrunconfigurationaspect.h>
#include <debugger/debuggerstartparameters.h>
#include <projectexplorer/kitinformation.h> #include <projectexplorer/kitinformation.h>
#include <projectexplorer/runnables.h> #include <projectexplorer/runnables.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <utils/portlist.h> #include <utils/portlist.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -62,7 +56,8 @@ bool RemoteLinuxRunControlFactory::canRun(RunConfiguration *runConfiguration, Co
&& mode != ProjectExplorer::Constants::DEBUG_RUN_MODE && mode != ProjectExplorer::Constants::DEBUG_RUN_MODE
&& mode != ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN && mode != ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN
&& mode != ProjectExplorer::Constants::QML_PROFILER_RUN_MODE && mode != ProjectExplorer::Constants::QML_PROFILER_RUN_MODE
&& mode != ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) { // && mode != ProjectExplorer::Constants::PERFPROFILER_RUN_MODE
) {
return false; return false;
} }
@@ -73,34 +68,37 @@ bool RemoteLinuxRunControlFactory::canRun(RunConfiguration *runConfiguration, Co
} }
RunControl *RemoteLinuxRunControlFactory::create(RunConfiguration *runConfig, Core::Id mode, RunControl *RemoteLinuxRunControlFactory::create(RunConfiguration *runConfig, Core::Id mode,
QString *errorMessage) QString *)
{ {
QTC_ASSERT(canRun(runConfig, mode), return 0); QTC_ASSERT(canRun(runConfig, mode), return 0);
if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE) { if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE) {
auto runControl = new RunControl(runConfig, mode); auto runControl = new RunControl(runConfig, mode);
(void) new AbstractRemoteLinuxRunSupport(runControl); (void) new SimpleTargetRunner(runControl);
return runControl; return runControl;
} }
if (mode == ProjectExplorer::Constants::DEBUG_RUN_MODE if (mode == ProjectExplorer::Constants::DEBUG_RUN_MODE
|| mode == ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN) { || mode == ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN) {
auto runControl = new RunControl(runConfig, mode); auto runControl = new RunControl(runConfig, mode);
(void) new AbstractRemoteLinuxRunSupport(runControl); (void) new LinuxDeviceDebugSupport(runControl);
(void) new LinuxDeviceDebugSupport(runControl, errorMessage);
return runControl; return runControl;
} }
if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE || if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE
mode == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) { // || mode == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE
auto runControl = Debugger::createAnalyzerRunControl(runConfig, mode); ) {
AnalyzerConnection connection; auto runControl = new RunControl(runConfig, mode);
connection.connParams = runControl->createWorker(mode);
DeviceKitInformation::device(runConfig->target()->kit())->sshParameters(); // AnalyzerConnection connection;
connection.analyzerHost = connection.connParams.host; // connection.connParams =
runControl->setConnection(connection); // DeviceKitInformation::device(runConfig->target()->kit())->sshParameters();
(void) new AbstractRemoteLinuxRunSupport(runControl); // connection.analyzerHost = connection.connParams.host;
(void) new RemoteLinuxAnalyzeSupport(runControl); // runControl->setConnection(connection);
// (void) new SimpleTargetRunner(runControl);
// (void) new PortsGatherer(runControl);
// (void) new FifoGatherer(runControl);
// (void) new RemoteLinuxAnalyzeSupport(runControl);
return runControl; return runControl;
} }

View File

@@ -255,14 +255,11 @@ CallgrindTool::CallgrindTool(QObject *parent)
QString toolTip = tr("Valgrind Function Profiler uses the " QString toolTip = tr("Valgrind Function Profiler uses the "
"Callgrind tool to record function calls when a program runs."); "Callgrind tool to record function calls when a program runs.");
auto rcc = [this](RunConfiguration *runConfiguration, Id mode) { RunControl::registerWorkerCreator(CALLGRIND_RUN_MODE, [this](RunControl *runControl) {
auto runControl = new RunControl(runConfiguration, mode); return createRunTool(runControl);
(void) createRunTool(runControl); });
return runControl;
};
if (!Utils::HostOsInfo::isWindowsHost()) { if (!Utils::HostOsInfo::isWindowsHost()) {
Debugger::registerAction(CALLGRIND_RUN_MODE, rcc);
auto action = new QAction(tr("Valgrind Function Profiler"), this); auto action = new QAction(tr("Valgrind Function Profiler"), this);
action->setToolTip(toolTip); action->setToolTip(toolTip);
menu->addAction(ActionManager::registerAction(action, CallgrindLocalActionId), menu->addAction(ActionManager::registerAction(action, CallgrindLocalActionId),
@@ -279,7 +276,6 @@ CallgrindTool::CallgrindTool(QObject *parent)
}); });
} }
Debugger::registerAction(CALLGRIND_RUN_MODE, rcc);
auto action = new QAction(tr("Valgrind Function Profiler (External Application)"), this); auto action = new QAction(tr("Valgrind Function Profiler (External Application)"), this);
action->setToolTip(toolTip); action->setToolTip(toolTip);
menu->addAction(ActionManager::registerAction(action, CallgrindRemoteActionId), menu->addAction(ActionManager::registerAction(action, CallgrindRemoteActionId),

View File

@@ -244,7 +244,7 @@ class MemcheckTool : public QObject
public: public:
MemcheckTool(QObject *parent); MemcheckTool(QObject *parent);
RunControl *createRunControl(RunConfiguration *runConfiguration, Core::Id runMode); RunWorker *createRunWorker(RunControl *runControl);
private: private:
void updateRunActions(); void updateRunActions();
@@ -395,8 +395,10 @@ MemcheckTool::MemcheckTool(QObject *parent)
ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER); ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
QString toolTip = tr("Valgrind Analyze Memory uses the Memcheck tool to find memory leaks."); QString toolTip = tr("Valgrind Analyze Memory uses the Memcheck tool to find memory leaks.");
RunControl::registerWorkerCreator(MEMCHECK_RUN_MODE, std::bind(&MemcheckTool::createRunWorker, this, _1));
RunControl::registerWorkerCreator(MEMCHECK_WITH_GDB_RUN_MODE, std::bind(&MemcheckTool::createRunWorker, this, _1));
if (!Utils::HostOsInfo::isWindowsHost()) { if (!Utils::HostOsInfo::isWindowsHost()) {
Debugger::registerAction(MEMCHECK_RUN_MODE, std::bind(&MemcheckTool::createRunControl, this, _1, _2));
action = new QAction(this); action = new QAction(this);
action->setText(tr("Valgrind Memory Analyzer")); action->setText(tr("Valgrind Memory Analyzer"));
action->setToolTip(toolTip); action->setToolTip(toolTip);
@@ -414,7 +416,6 @@ MemcheckTool::MemcheckTool(QObject *parent)
action->setEnabled(m_startAction->isEnabled()); action->setEnabled(m_startAction->isEnabled());
}); });
Debugger::registerAction(MEMCHECK_WITH_GDB_RUN_MODE, std::bind(&MemcheckTool::createRunControl, this, _1, _2));
action = new QAction(this); action = new QAction(this);
action->setText(tr("Valgrind Memory Analyzer with GDB")); action->setText(tr("Valgrind Memory Analyzer with GDB"));
action->setToolTip(tr("Valgrind Analyze Memory with GDB uses the " action->setToolTip(tr("Valgrind Analyze Memory with GDB uses the "
@@ -435,7 +436,6 @@ MemcheckTool::MemcheckTool(QObject *parent)
}); });
} }
Debugger::registerAction(MEMCHECK_RUN_MODE, std::bind(&MemcheckTool::createRunControl, this, _1, _2));
action = new QAction(this); action = new QAction(this);
action->setText(tr("Valgrind Memory Analyzer (External Application)")); action->setText(tr("Valgrind Memory Analyzer (External Application)"));
action->setToolTip(toolTip); action->setToolTip(toolTip);
@@ -452,8 +452,8 @@ MemcheckTool::MemcheckTool(QObject *parent)
return; return;
TaskHub::clearTasks(Debugger::Constants::ANALYZERTASK_ID); TaskHub::clearTasks(Debugger::Constants::ANALYZERTASK_ID);
Debugger::selectPerspective(MemcheckPerspectiveId); Debugger::selectPerspective(MemcheckPerspectiveId);
RunControl *rc = createRunControl(runConfig, MEMCHECK_RUN_MODE); RunControl *rc = new RunControl(runConfig, MEMCHECK_RUN_MODE);
QTC_ASSERT(rc, return); rc->createWorker(MEMCHECK_RUN_MODE);
const auto runnable = dlg.runnable(); const auto runnable = dlg.runnable();
rc->setRunnable(runnable); rc->setRunnable(runnable);
AnalyzerConnection connection; AnalyzerConnection connection;
@@ -560,14 +560,14 @@ void MemcheckTool::maybeActiveRunConfigurationChanged()
updateFromSettings(); updateFromSettings();
} }
RunControl *MemcheckTool::createRunControl(RunConfiguration *runConfiguration, Core::Id runMode) RunWorker *MemcheckTool::createRunWorker(RunControl *runControl)
{ {
m_errorModel.setRelevantFrameFinder(makeFrameFinder(runConfiguration RunConfiguration *runConfig = runControl->runConfiguration();
? runConfiguration->target()->project()->files(Project::AllFiles) : QStringList())); m_errorModel.setRelevantFrameFinder(makeFrameFinder(runConfig
? runConfig->target()->project()->files(Project::AllFiles) : QStringList()));
auto runControl = new RunControl(runConfiguration, runMode);
MemcheckToolRunner *runTool = 0; MemcheckToolRunner *runTool = 0;
if (runMode == MEMCHECK_RUN_MODE) if (runControl->runMode() == MEMCHECK_RUN_MODE)
runTool = new MemcheckToolRunner(runControl); runTool = new MemcheckToolRunner(runControl);
else else
runTool = new MemcheckWithGdbToolRunner(runControl); runTool = new MemcheckWithGdbToolRunner(runControl);
@@ -583,7 +583,7 @@ RunControl *MemcheckTool::createRunControl(RunConfiguration *runConfiguration, C
m_toolBusy = true; m_toolBusy = true;
updateRunActions(); updateRunActions();
return runControl; return runTool;
} }
void MemcheckTool::engineStarting(const MemcheckToolRunner *runTool) void MemcheckTool::engineStarting(const MemcheckToolRunner *runTool)
@@ -739,7 +739,9 @@ public:
RunControl *create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage) override RunControl *create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage) override
{ {
Q_UNUSED(errorMessage); Q_UNUSED(errorMessage);
return m_tool->createRunControl(runConfiguration, mode); auto runControl = new RunControl(runConfiguration, mode);
runControl->createWorker(mode);
return runControl;
} }
// Do not create an aspect, let the Callgrind tool create one and use that, too. // Do not create an aspect, let the Callgrind tool create one and use that, too.

View File

@@ -54,7 +54,7 @@ namespace Valgrind {
namespace Internal { namespace Internal {
ValgrindToolRunner::ValgrindToolRunner(RunControl *runControl) ValgrindToolRunner::ValgrindToolRunner(RunControl *runControl)
: ToolRunner(runControl) : RunWorker(runControl)
{ {
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR); runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
runControl->setSupportsReRunning(false); runControl->setSupportsReRunning(false);
@@ -102,7 +102,7 @@ void ValgrindToolRunner::start()
return; return;
} }
reportSuccess(); reportStarted();
} }
void ValgrindToolRunner::stop() void ValgrindToolRunner::stop()
@@ -160,7 +160,7 @@ void ValgrindToolRunner::runnerFinished()
disconnect(runner(), &ValgrindRunner::finished, disconnect(runner(), &ValgrindRunner::finished,
this, &ValgrindToolRunner::runnerFinished); this, &ValgrindToolRunner::runnerFinished);
reportSuccess(); reportStarted();
} }
void ValgrindToolRunner::receiveProcessOutput(const QString &output, OutputFormat format) void ValgrindToolRunner::receiveProcessOutput(const QString &output, OutputFormat format)

View File

@@ -37,7 +37,7 @@
namespace Valgrind { namespace Valgrind {
namespace Internal { namespace Internal {
class ValgrindToolRunner : public ProjectExplorer::ToolRunner class ValgrindToolRunner : public ProjectExplorer::RunWorker
{ {
Q_OBJECT Q_OBJECT

View File

@@ -49,7 +49,7 @@ namespace Internal {
using namespace ProjectExplorer; using namespace ProjectExplorer;
WinRtDebugSupport::WinRtDebugSupport(RunControl *runControl, WinRtRunnerHelper *runner) WinRtDebugSupport::WinRtDebugSupport(RunControl *runControl, WinRtRunnerHelper *runner)
: ToolRunner(runControl) : RunWorker(runControl)
, m_runner(runner) , m_runner(runner)
{ {
connect(runControl, &RunControl::finished, this, &WinRtDebugSupport::finish); connect(runControl, &RunControl::finished, this, &WinRtDebugSupport::finish);

View File

@@ -35,7 +35,7 @@ namespace Internal {
class WinRtRunConfiguration; class WinRtRunConfiguration;
class WinRtRunnerHelper; class WinRtRunnerHelper;
class WinRtDebugSupport : public ProjectExplorer::ToolRunner class WinRtDebugSupport : public ProjectExplorer::RunWorker
{ {
Q_OBJECT Q_OBJECT
public: public: