forked from qt-creator/qt-creator
DAP: Separate CMake and Gdb logic in DAP engine
This commit refactors the Debug Adapter Protocol (DAP) engine to separate the logic for CMake-based projects and Gdb-based debugging. - Moved CMake-specific code to a new CMakeDAPEngine class - Moved Gdb-specific code to a new GdbDAPEngine class Change-Id: Ia616e7b7ea2ff2071bcadd26b28b620f9aca6ac4 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -27,7 +27,9 @@ add_qtc_plugin(Debugger
|
|||||||
console/consoleitemmodel.cpp console/consoleitemmodel.h
|
console/consoleitemmodel.cpp console/consoleitemmodel.h
|
||||||
console/consoleproxymodel.cpp console/consoleproxymodel.h
|
console/consoleproxymodel.cpp console/consoleproxymodel.h
|
||||||
console/consoleview.cpp console/consoleview.h
|
console/consoleview.cpp console/consoleview.h
|
||||||
|
dap/cmakedapengine.cpp dap/cmakedapengine.h
|
||||||
dap/dapengine.cpp dap/dapengine.h
|
dap/dapengine.cpp dap/dapengine.h
|
||||||
|
dap/gdbdapengine.cpp dap/gdbdapengine.h
|
||||||
debugger.qrc
|
debugger.qrc
|
||||||
debugger_global.h
|
debugger_global.h
|
||||||
debuggeractions.cpp debuggeractions.h
|
debuggeractions.cpp debuggeractions.h
|
||||||
|
118
src/plugins/debugger/dap/cmakedapengine.cpp
Normal file
118
src/plugins/debugger/dap/cmakedapengine.cpp
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
// Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "cmakedapengine.h"
|
||||||
|
|
||||||
|
#include <debugger/debuggermainwindow.h>
|
||||||
|
|
||||||
|
#include <utils/temporarydirectory.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
#include <projectexplorer/buildsystem.h>
|
||||||
|
#include <projectexplorer/projecttree.h>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
|
using namespace Core;
|
||||||
|
using namespace Utils;
|
||||||
|
static Q_LOGGING_CATEGORY(dapEngineLog, "qtc.dbg.dapengine", QtWarningMsg)
|
||||||
|
|
||||||
|
namespace Debugger::Internal {
|
||||||
|
|
||||||
|
class LocalSocketDataProvider : public IDataProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LocalSocketDataProvider(const QString &socketName)
|
||||||
|
: m_socketName(socketName)
|
||||||
|
{
|
||||||
|
connect(&m_socket, &QLocalSocket::connected, this, &IDataProvider::started);
|
||||||
|
connect(&m_socket, &QLocalSocket::disconnected, this, &IDataProvider::done);
|
||||||
|
connect(&m_socket, &QLocalSocket::readyRead, this, &IDataProvider::readyReadStandardOutput);
|
||||||
|
connect(&m_socket,
|
||||||
|
&QLocalSocket::errorOccurred,
|
||||||
|
this,
|
||||||
|
&IDataProvider::readyReadStandardError);
|
||||||
|
}
|
||||||
|
|
||||||
|
~LocalSocketDataProvider() { m_socket.disconnectFromServer(); }
|
||||||
|
|
||||||
|
void start() override { m_socket.connectToServer(m_socketName, QIODevice::ReadWrite); }
|
||||||
|
|
||||||
|
bool isRunning() const override { return m_socket.isOpen(); }
|
||||||
|
void writeRaw(const QByteArray &data) override { m_socket.write(data); }
|
||||||
|
void kill() override
|
||||||
|
{
|
||||||
|
if (m_socket.isOpen())
|
||||||
|
m_socket.disconnectFromServer();
|
||||||
|
else {
|
||||||
|
m_socket.abort();
|
||||||
|
emit done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QByteArray readAllStandardOutput() override { return m_socket.readAll(); }
|
||||||
|
QString readAllStandardError() override { return QString(); }
|
||||||
|
int exitCode() const override { return 0; }
|
||||||
|
QString executable() const override { return m_socket.serverName(); }
|
||||||
|
|
||||||
|
QProcess::ExitStatus exitStatus() const override { return QProcess::NormalExit; }
|
||||||
|
QProcess::ProcessError error() const override { return QProcess::UnknownError; }
|
||||||
|
Utils::ProcessResult result() const override { return ProcessResult::FinishedWithSuccess; }
|
||||||
|
QString exitMessage() const override { return QString(); };
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLocalSocket m_socket;
|
||||||
|
const QString m_socketName;
|
||||||
|
};
|
||||||
|
|
||||||
|
CMakeDapEngine::CMakeDapEngine()
|
||||||
|
: DapEngine()
|
||||||
|
{
|
||||||
|
setObjectName("CmakeDapEngine");
|
||||||
|
setDebuggerName("CmakeDAP");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeDapEngine::handleDapStarted()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(state() == EngineRunRequested, qCDebug(dapEngineLog) << state());
|
||||||
|
|
||||||
|
postDirectCommand({
|
||||||
|
{"command", "initialize"},
|
||||||
|
{"type", "request"},
|
||||||
|
{"arguments", QJsonObject {
|
||||||
|
{"clientID", "QtCreator"}, // The ID of the client using this adapter.
|
||||||
|
{"clientName", "QtCreator"}, // The human-readable name of the client using this adapter.
|
||||||
|
{"adapterID", "cmake"},
|
||||||
|
{"pathFormat", "path"}
|
||||||
|
}}
|
||||||
|
});
|
||||||
|
|
||||||
|
qCDebug(dapEngineLog) << "handleDapStarted";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeDapEngine::setupEngine()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(state() == EngineSetupRequested, qCDebug(dapEngineLog) << state());
|
||||||
|
|
||||||
|
qCDebug(dapEngineLog) << "build system name"
|
||||||
|
<< ProjectExplorer::ProjectTree::currentBuildSystem()->name();
|
||||||
|
|
||||||
|
if (TemporaryDirectory::masterDirectoryFilePath().osType() == Utils::OsType::OsTypeWindows) {
|
||||||
|
m_dataGenerator = std::make_unique<LocalSocketDataProvider>("\\\\.\\pipe\\cmake-dap");
|
||||||
|
} else {
|
||||||
|
m_dataGenerator = std::make_unique<LocalSocketDataProvider>(
|
||||||
|
TemporaryDirectory::masterDirectoryPath() + "/cmake-dap.sock");
|
||||||
|
}
|
||||||
|
connectDataGeneratorSignals();
|
||||||
|
|
||||||
|
connect(ProjectExplorer::ProjectTree::currentBuildSystem(),
|
||||||
|
&ProjectExplorer::BuildSystem::debuggingStarted,
|
||||||
|
this,
|
||||||
|
[this] { m_dataGenerator->start(); });
|
||||||
|
|
||||||
|
ProjectExplorer::ProjectTree::currentBuildSystem()->requestDebugging();
|
||||||
|
notifyEngineSetupOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Debugger::Internal
|
20
src/plugins/debugger/dap/cmakedapengine.h
Normal file
20
src/plugins/debugger/dap/cmakedapengine.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dapengine.h"
|
||||||
|
|
||||||
|
namespace Debugger::Internal {
|
||||||
|
|
||||||
|
class CMakeDapEngine : public DapEngine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMakeDapEngine();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void handleDapStarted() override;
|
||||||
|
void setupEngine() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Debugger::Internal
|
@@ -2,6 +2,8 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "dapengine.h"
|
#include "dapengine.h"
|
||||||
|
#include "cmakedapengine.h"
|
||||||
|
#include "gdbdapengine.h"
|
||||||
|
|
||||||
#include <debugger/breakhandler.h>
|
#include <debugger/breakhandler.h>
|
||||||
#include <debugger/debuggeractions.h>
|
#include <debugger/debuggeractions.h>
|
||||||
@@ -40,6 +42,7 @@
|
|||||||
#include <projectexplorer/buildconfiguration.h>
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
#include <projectexplorer/buildsystem.h>
|
#include <projectexplorer/buildsystem.h>
|
||||||
#include <projectexplorer/projecttree.h>
|
#include <projectexplorer/projecttree.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -59,106 +62,8 @@ static Q_LOGGING_CATEGORY(dapEngineLog, "qtc.dbg.dapengine", QtWarningMsg)
|
|||||||
|
|
||||||
namespace Debugger::Internal {
|
namespace Debugger::Internal {
|
||||||
|
|
||||||
class ProcessDataProvider : public IDataProvider
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ProcessDataProvider(const DebuggerRunParameters &rp, const CommandLine &cmd)
|
|
||||||
: m_runParameters(rp)
|
|
||||||
, m_cmd(cmd)
|
|
||||||
{
|
|
||||||
connect(&m_proc, &Process::started, this, &IDataProvider::started);
|
|
||||||
connect(&m_proc, &Process::done, this, &IDataProvider::done);
|
|
||||||
connect(&m_proc,
|
|
||||||
&Process::readyReadStandardOutput,
|
|
||||||
this,
|
|
||||||
&IDataProvider::readyReadStandardOutput);
|
|
||||||
connect(&m_proc,
|
|
||||||
&Process::readyReadStandardError,
|
|
||||||
this,
|
|
||||||
&IDataProvider::readyReadStandardError);
|
|
||||||
}
|
|
||||||
|
|
||||||
~ProcessDataProvider()
|
|
||||||
{
|
|
||||||
m_proc.kill();
|
|
||||||
m_proc.waitForFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() override
|
|
||||||
{
|
|
||||||
m_proc.setProcessMode(ProcessMode::Writer);
|
|
||||||
m_proc.setEnvironment(m_runParameters.debugger.environment);
|
|
||||||
m_proc.setCommand(m_cmd);
|
|
||||||
m_proc.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isRunning() const override { return m_proc.isRunning(); }
|
|
||||||
void writeRaw(const QByteArray &data) override { m_proc.writeRaw(data); }
|
|
||||||
void kill() override { m_proc.kill(); }
|
|
||||||
QByteArray readAllStandardOutput() override { return m_proc.readAllStandardOutput().toUtf8(); }
|
|
||||||
QString readAllStandardError() override { return m_proc.readAllStandardError(); }
|
|
||||||
int exitCode() const override { return m_proc.exitCode(); }
|
|
||||||
QString executable() const override { return m_proc.commandLine().executable().toUserOutput(); }
|
|
||||||
|
|
||||||
QProcess::ExitStatus exitStatus() const override { return m_proc.exitStatus(); }
|
|
||||||
QProcess::ProcessError error() const override { return m_proc.error(); }
|
|
||||||
Utils::ProcessResult result() const override { return m_proc.result(); }
|
|
||||||
QString exitMessage() const override { return m_proc.exitMessage(); };
|
|
||||||
|
|
||||||
private:
|
|
||||||
Utils::Process m_proc;
|
|
||||||
const DebuggerRunParameters m_runParameters;
|
|
||||||
const CommandLine m_cmd;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LocalSocketDataProvider : public IDataProvider
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LocalSocketDataProvider(const QString &socketName)
|
|
||||||
: m_socketName(socketName)
|
|
||||||
{
|
|
||||||
connect(&m_socket, &QLocalSocket::connected, this, &IDataProvider::started);
|
|
||||||
connect(&m_socket, &QLocalSocket::disconnected, this, &IDataProvider::done);
|
|
||||||
connect(&m_socket, &QLocalSocket::readyRead, this, &IDataProvider::readyReadStandardOutput);
|
|
||||||
connect(&m_socket,
|
|
||||||
&QLocalSocket::errorOccurred,
|
|
||||||
this,
|
|
||||||
&IDataProvider::readyReadStandardError);
|
|
||||||
}
|
|
||||||
|
|
||||||
~LocalSocketDataProvider() { m_socket.disconnectFromServer(); }
|
|
||||||
|
|
||||||
void start() override { m_socket.connectToServer(m_socketName, QIODevice::ReadWrite); }
|
|
||||||
|
|
||||||
bool isRunning() const override { return m_socket.isOpen(); }
|
|
||||||
void writeRaw(const QByteArray &data) override { m_socket.write(data); }
|
|
||||||
void kill() override {
|
|
||||||
if (m_socket.isOpen())
|
|
||||||
m_socket.disconnectFromServer();
|
|
||||||
else {
|
|
||||||
m_socket.abort();
|
|
||||||
emit done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QByteArray readAllStandardOutput() override { return m_socket.readAll(); }
|
|
||||||
QString readAllStandardError() override { return QString(); }
|
|
||||||
int exitCode() const override { return 0; }
|
|
||||||
QString executable() const override { return m_socket.serverName(); }
|
|
||||||
|
|
||||||
QProcess::ExitStatus exitStatus() const override { return QProcess::NormalExit; }
|
|
||||||
QProcess::ProcessError error() const override { return QProcess::UnknownError; }
|
|
||||||
Utils::ProcessResult result() const override { return ProcessResult::FinishedWithSuccess; }
|
|
||||||
QString exitMessage() const override { return QString(); };
|
|
||||||
|
|
||||||
private:
|
|
||||||
QLocalSocket m_socket;
|
|
||||||
const QString m_socketName;
|
|
||||||
};
|
|
||||||
|
|
||||||
DapEngine::DapEngine()
|
DapEngine::DapEngine()
|
||||||
{
|
{
|
||||||
setObjectName("DapEngine");
|
|
||||||
setDebuggerName("DAP");
|
|
||||||
m_rootWatchItem = new WatchItem();
|
m_rootWatchItem = new WatchItem();
|
||||||
m_currentWatchItem = m_rootWatchItem;
|
m_currentWatchItem = m_rootWatchItem;
|
||||||
}
|
}
|
||||||
@@ -236,58 +141,6 @@ void DapEngine::shutdownEngine()
|
|||||||
m_dataGenerator->kill();
|
m_dataGenerator->kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DapEngine::setupEngine()
|
|
||||||
{
|
|
||||||
QTC_ASSERT(state() == EngineSetupRequested, qCDebug(dapEngineLog) << state());
|
|
||||||
|
|
||||||
const auto connectDataGeneratorSignals = [this] {
|
|
||||||
if (!m_dataGenerator)
|
|
||||||
return;
|
|
||||||
|
|
||||||
connect(m_dataGenerator.get(), &IDataProvider::started, this, &DapEngine::handleDapStarted);
|
|
||||||
connect(m_dataGenerator.get(), &IDataProvider::done, this, &DapEngine::handleDapDone);
|
|
||||||
connect(m_dataGenerator.get(),
|
|
||||||
&IDataProvider::readyReadStandardOutput,
|
|
||||||
this,
|
|
||||||
&DapEngine::readDapStandardOutput);
|
|
||||||
connect(m_dataGenerator.get(),
|
|
||||||
&IDataProvider::readyReadStandardError,
|
|
||||||
this,
|
|
||||||
&DapEngine::readDapStandardError);
|
|
||||||
};
|
|
||||||
|
|
||||||
Perspective *currentPerspective = DebuggerMainWindow::instance()->currentPerspective();
|
|
||||||
if (currentPerspective->parentPerspectiveId() == Constants::CMAKE_PERSPECTIVE_ID) {
|
|
||||||
qCDebug(dapEngineLog) << "build system name" << ProjectExplorer::ProjectTree::currentBuildSystem()->name();
|
|
||||||
|
|
||||||
if (TemporaryDirectory::masterDirectoryFilePath().osType() == Utils::OsType::OsTypeWindows) {
|
|
||||||
m_dataGenerator = std::make_unique<LocalSocketDataProvider>("\\\\.\\pipe\\cmake-dap");
|
|
||||||
} else {
|
|
||||||
m_dataGenerator = std::make_unique<LocalSocketDataProvider>(
|
|
||||||
TemporaryDirectory::masterDirectoryPath() + "/cmake-dap.sock");
|
|
||||||
}
|
|
||||||
connectDataGeneratorSignals();
|
|
||||||
|
|
||||||
connect(ProjectExplorer::ProjectTree::currentBuildSystem(),
|
|
||||||
&ProjectExplorer::BuildSystem::debuggingStarted,
|
|
||||||
this,
|
|
||||||
[this] {
|
|
||||||
m_dataGenerator->start();
|
|
||||||
});
|
|
||||||
|
|
||||||
ProjectExplorer::ProjectTree::currentBuildSystem()->requestDebugging();
|
|
||||||
} else {
|
|
||||||
const DebuggerRunParameters &rp = runParameters();
|
|
||||||
const CommandLine cmd{rp.debugger.command.executable(), {"-i", "dap"}};
|
|
||||||
|
|
||||||
m_dataGenerator = std::make_unique<ProcessDataProvider>(rp, cmd);
|
|
||||||
connectDataGeneratorSignals();
|
|
||||||
m_dataGenerator->start();
|
|
||||||
|
|
||||||
}
|
|
||||||
notifyEngineSetupOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
// From the docs:
|
// From the docs:
|
||||||
// The sequence of events/requests is as follows:
|
// The sequence of events/requests is as follows:
|
||||||
// * adapters sends initialized event (after the initialize request has returned)
|
// * adapters sends initialized event (after the initialize request has returned)
|
||||||
@@ -310,9 +163,7 @@ void DapEngine::handleDapStarted()
|
|||||||
{"type", "request"},
|
{"type", "request"},
|
||||||
{"arguments", QJsonObject {
|
{"arguments", QJsonObject {
|
||||||
{"clientID", "QtCreator"}, // The ID of the client using this adapter.
|
{"clientID", "QtCreator"}, // The ID of the client using this adapter.
|
||||||
{"clientName", "QtCreator"}, // The human-readable name of the client using this adapter.
|
{"clientName", "QtCreator"} // The human-readable name of the client using this adapter.
|
||||||
{"adapterID", "cmake"},
|
|
||||||
{"pathFormat", "path"}
|
|
||||||
}}
|
}}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1083,9 +934,29 @@ void DapEngine::claimInitialBreakpoints()
|
|||||||
qCDebug(dapEngineLog) << "claimInitialBreakpoints";
|
qCDebug(dapEngineLog) << "claimInitialBreakpoints";
|
||||||
}
|
}
|
||||||
|
|
||||||
DebuggerEngine *createDapEngine()
|
void DapEngine::connectDataGeneratorSignals()
|
||||||
{
|
{
|
||||||
return new DapEngine;
|
if (!m_dataGenerator)
|
||||||
|
return;
|
||||||
|
|
||||||
|
connect(m_dataGenerator.get(), &IDataProvider::started, this, &DapEngine::handleDapStarted);
|
||||||
|
connect(m_dataGenerator.get(), &IDataProvider::done, this, &DapEngine::handleDapDone);
|
||||||
|
connect(m_dataGenerator.get(),
|
||||||
|
&IDataProvider::readyReadStandardOutput,
|
||||||
|
this,
|
||||||
|
&DapEngine::readDapStandardOutput);
|
||||||
|
connect(m_dataGenerator.get(),
|
||||||
|
&IDataProvider::readyReadStandardError,
|
||||||
|
this,
|
||||||
|
&DapEngine::readDapStandardError);
|
||||||
|
}
|
||||||
|
|
||||||
|
DebuggerEngine *createDapEngine(Utils::Id runMode)
|
||||||
|
{
|
||||||
|
if (runMode == ProjectExplorer::Constants::CMAKE_DEBUG_RUN_MODE)
|
||||||
|
return new CMakeDapEngine;
|
||||||
|
|
||||||
|
return new GdbDapEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Debugger::Internal
|
} // Debugger::Internal
|
||||||
|
@@ -50,12 +50,11 @@ class DapEngine : public DebuggerEngine
|
|||||||
public:
|
public:
|
||||||
DapEngine();
|
DapEngine();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void executeStepIn(bool) override;
|
void executeStepIn(bool) override;
|
||||||
void executeStepOut() override;
|
void executeStepOut() override;
|
||||||
void executeStepOver(bool) override;
|
void executeStepOver(bool) override;
|
||||||
|
|
||||||
void setupEngine() override;
|
|
||||||
void shutdownInferior() override;
|
void shutdownInferior() override;
|
||||||
void shutdownEngine() override;
|
void shutdownEngine() override;
|
||||||
|
|
||||||
@@ -106,7 +105,7 @@ private:
|
|||||||
|
|
||||||
void claimInitialBreakpoints();
|
void claimInitialBreakpoints();
|
||||||
|
|
||||||
void handleDapStarted();
|
virtual void handleDapStarted();
|
||||||
void handleDapLaunch();
|
void handleDapLaunch();
|
||||||
void handleDapConfigurationDone();
|
void handleDapConfigurationDone();
|
||||||
|
|
||||||
@@ -122,6 +121,7 @@ private:
|
|||||||
void handleResponse(const QString &ba);
|
void handleResponse(const QString &ba);
|
||||||
void updateAll() override;
|
void updateAll() override;
|
||||||
void updateLocals() override;
|
void updateLocals() override;
|
||||||
|
void connectDataGeneratorSignals();
|
||||||
|
|
||||||
QByteArray m_inbuffer;
|
QByteArray m_inbuffer;
|
||||||
std::unique_ptr<IDataProvider> m_dataGenerator = nullptr;
|
std::unique_ptr<IDataProvider> m_dataGenerator = nullptr;
|
||||||
|
97
src/plugins/debugger/dap/gdbdapengine.cpp
Normal file
97
src/plugins/debugger/dap/gdbdapengine.cpp
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "gdbdapengine.h"
|
||||||
|
|
||||||
|
#include <debugger/debuggermainwindow.h>
|
||||||
|
|
||||||
|
#include <utils/temporarydirectory.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
#include <projectexplorer/buildsystem.h>
|
||||||
|
#include <projectexplorer/projecttree.h>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
|
using namespace Core;
|
||||||
|
using namespace Utils;
|
||||||
|
static Q_LOGGING_CATEGORY(dapEngineLog, "qtc.dbg.dapengine", QtWarningMsg)
|
||||||
|
|
||||||
|
namespace Debugger::Internal {
|
||||||
|
|
||||||
|
class ProcessDataProvider : public IDataProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProcessDataProvider(const DebuggerRunParameters &rp, const CommandLine &cmd)
|
||||||
|
: m_runParameters(rp)
|
||||||
|
, m_cmd(cmd)
|
||||||
|
{
|
||||||
|
connect(&m_proc, &Process::started, this, &IDataProvider::started);
|
||||||
|
connect(&m_proc, &Process::done, this, &IDataProvider::done);
|
||||||
|
connect(&m_proc,
|
||||||
|
&Process::readyReadStandardOutput,
|
||||||
|
this,
|
||||||
|
&IDataProvider::readyReadStandardOutput);
|
||||||
|
connect(&m_proc,
|
||||||
|
&Process::readyReadStandardError,
|
||||||
|
this,
|
||||||
|
&IDataProvider::readyReadStandardError);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ProcessDataProvider()
|
||||||
|
{
|
||||||
|
m_proc.kill();
|
||||||
|
m_proc.waitForFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() override
|
||||||
|
{
|
||||||
|
m_proc.setProcessMode(ProcessMode::Writer);
|
||||||
|
m_proc.setEnvironment(m_runParameters.debugger.environment);
|
||||||
|
m_proc.setCommand(m_cmd);
|
||||||
|
m_proc.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isRunning() const override { return m_proc.isRunning(); }
|
||||||
|
void writeRaw(const QByteArray &data) override { m_proc.writeRaw(data); }
|
||||||
|
void kill() override { m_proc.kill(); }
|
||||||
|
QByteArray readAllStandardOutput() override { return m_proc.readAllStandardOutput().toUtf8(); }
|
||||||
|
QString readAllStandardError() override { return m_proc.readAllStandardError(); }
|
||||||
|
int exitCode() const override { return m_proc.exitCode(); }
|
||||||
|
QString executable() const override { return m_proc.commandLine().executable().toUserOutput(); }
|
||||||
|
|
||||||
|
QProcess::ExitStatus exitStatus() const override { return m_proc.exitStatus(); }
|
||||||
|
QProcess::ProcessError error() const override { return m_proc.error(); }
|
||||||
|
Utils::ProcessResult result() const override { return m_proc.result(); }
|
||||||
|
QString exitMessage() const override { return m_proc.exitMessage(); };
|
||||||
|
|
||||||
|
private:
|
||||||
|
Utils::Process m_proc;
|
||||||
|
const DebuggerRunParameters m_runParameters;
|
||||||
|
const CommandLine m_cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
GdbDapEngine::GdbDapEngine()
|
||||||
|
: DapEngine()
|
||||||
|
{
|
||||||
|
setObjectName("GdbDapEngine");
|
||||||
|
setDebuggerName("GdbDAP");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbDapEngine::setupEngine()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(state() == EngineSetupRequested, qCDebug(dapEngineLog) << state());
|
||||||
|
|
||||||
|
const DebuggerRunParameters &rp = runParameters();
|
||||||
|
const CommandLine cmd{rp.debugger.command.executable(), {"-i", "dap"}};
|
||||||
|
|
||||||
|
m_dataGenerator = std::make_unique<ProcessDataProvider>(rp, cmd);
|
||||||
|
connectDataGeneratorSignals();
|
||||||
|
m_dataGenerator->start();
|
||||||
|
|
||||||
|
notifyEngineSetupOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Debugger::Internal
|
19
src/plugins/debugger/dap/gdbdapengine.h
Normal file
19
src/plugins/debugger/dap/gdbdapengine.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dapengine.h"
|
||||||
|
|
||||||
|
namespace Debugger::Internal {
|
||||||
|
|
||||||
|
class GdbDapEngine : public DapEngine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GdbDapEngine();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupEngine() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Debugger::Internal
|
@@ -70,7 +70,7 @@ DebuggerEngine *createPdbEngine();
|
|||||||
DebuggerEngine *createQmlEngine();
|
DebuggerEngine *createQmlEngine();
|
||||||
DebuggerEngine *createLldbEngine();
|
DebuggerEngine *createLldbEngine();
|
||||||
DebuggerEngine *createUvscEngine();
|
DebuggerEngine *createUvscEngine();
|
||||||
DebuggerEngine *createDapEngine();
|
DebuggerEngine *createDapEngine(Utils::Id runMode = ProjectExplorer::Constants::NO_RUN_MODE);
|
||||||
|
|
||||||
static QString noEngineMessage()
|
static QString noEngineMessage()
|
||||||
{
|
{
|
||||||
@@ -483,7 +483,7 @@ void DebuggerRunTool::start()
|
|||||||
|
|
||||||
if (!m_engine) {
|
if (!m_engine) {
|
||||||
if (runControl()->runMode() == ProjectExplorer::Constants::CMAKE_DEBUG_RUN_MODE)
|
if (runControl()->runMode() == ProjectExplorer::Constants::CMAKE_DEBUG_RUN_MODE)
|
||||||
m_engine = createDapEngine();
|
m_engine = createDapEngine(runControl()->runMode());
|
||||||
else if (m_runParameters.isCppDebugging()) {
|
else if (m_runParameters.isCppDebugging()) {
|
||||||
switch (m_runParameters.cppEngineType) {
|
switch (m_runParameters.cppEngineType) {
|
||||||
case GdbEngineType:
|
case GdbEngineType:
|
||||||
|
Reference in New Issue
Block a user