diff --git a/src/plugins/cxx/cmake/cmakegenerator.cpp b/src/plugins/cxx/cmake/cmakegenerator.cpp index 9742075b1..c90c7b6de 100644 --- a/src/plugins/cxx/cmake/cmakegenerator.cpp +++ b/src/plugins/cxx/cmake/cmakegenerator.cpp @@ -91,7 +91,14 @@ QMap CMakeGenerator::getDebugArguments(const dpfservice::Proj QMap param; param.insert("workspace", projectInfo.runWorkspaceDir()); param.insert("targetPath", projectInfo.runProgram()); - param.insert("arguments", projectInfo.runCustomArgs()); + QStringList debugArgs; + if (!projectInfo.runCustomArgs().isEmpty()) { + debugArgs.append("--args"); + debugArgs.append(projectInfo.runProgram()); // gdb -i --args program arg + debugArgs.append(projectInfo.runCustomArgs()); + } + + param.insert("arguments", debugArgs); return param; } diff --git a/src/plugins/debugger/dap/dapdebugger.cpp b/src/plugins/debugger/dap/dapdebugger.cpp index 1ddaf04de..c929f6dae 100644 --- a/src/plugins/debugger/dap/dapdebugger.cpp +++ b/src/plugins/debugger/dap/dapdebugger.cpp @@ -279,6 +279,34 @@ void DAPDebugger::startDebugRemote(const RemoteInfo &info) updateRunState(kPreparing); } +void DAPDebugger::connectToGdbServer(const GdbserverInfo &info) +{ + d->isRemote = false; // local dapDebugger -> gdbserver + d->currentSession = d->localSession; + + QMap param; + param.insert("workspace", ""); + param.insert("targetPath", info.executablePath); + QStringList commands; + if (!info.executablePath.isEmpty()) + commands.append(QString("--se=%1").arg(info.executablePath)); + commands.append(QString("--ex=target remote %1:%2").arg(info.ip, QString::number(info.port))); + for (auto command : info.initCommands) { + if (!command.isEmpty()) + commands.append(QString("--iex=%1").arg(command)); + } + if (!info.debugInfo.isEmpty()) + commands.append(QString("--iex=set debug-file-directory %1").arg(info.debugInfo)); + if (!info.arg.isEmpty()) { + commands.append("--args"); + commands.append(info.arg); + } + param.insert("arguments", commands); + + requestDebugPort(param, "cmake", false); + updateRunState(kPreparing); +} + void DAPDebugger::attachDebug(const QString &processId) { if (d->runState != kNoRun) { diff --git a/src/plugins/debugger/dap/dapdebugger.h b/src/plugins/debugger/dap/dapdebugger.h index 14a0ba57e..edb4faa92 100644 --- a/src/plugins/debugger/dap/dapdebugger.h +++ b/src/plugins/debugger/dap/dapdebugger.h @@ -58,6 +58,7 @@ class DAPDebugger : public AbstractDebugger void startDebug() override; void startDebugRemote(const RemoteInfo &info) override; + void connectToGdbServer(const GdbserverInfo &info); void startRerverseDebug(const QString &target); void attachDebug(const QString &processId) override; void detachDebug() override; diff --git a/src/plugins/debugger/debuggerglobals.h b/src/plugins/debugger/debuggerglobals.h index 7b3a9de3f..16cc365ee 100644 --- a/src/plugins/debugger/debuggerglobals.h +++ b/src/plugins/debugger/debuggerglobals.h @@ -5,6 +5,8 @@ #ifndef DEBUGGERGLOBALS_H #define DEBUGGERGLOBALS_H +#include "services/debugger/debuggerservice.h" + #include #include #include @@ -13,6 +15,7 @@ * define AppOutPutPane`s toolbar name */ const QString debugToolBarName = "debugTool"; +typedef dpfservice::GDBServerPreParam GdbserverInfo; /* * Redefine global instance diff --git a/src/plugins/debugger/debugmanager.cpp b/src/plugins/debugger/debugmanager.cpp index 3ce1f3db3..c1b0140ba 100644 --- a/src/plugins/debugger/debugmanager.cpp +++ b/src/plugins/debugger/debugmanager.cpp @@ -9,6 +9,7 @@ #include "interface/menumanager.h" #include "interface/attachinfodialog.h" #include "reversedebug/reversedebugger.h" +#include "remotedebug/connecttoserverdlg.h" #include "services/debugger/debuggerservice.h" #include "services/window/windowservice.h" @@ -54,6 +55,15 @@ bool DebugManager::initialize(dpfservice::WindowService *windowService, debuggerService->getDebugState = std::bind(&DebugManager::getRunState, this); } + if (!debuggerService->requestConnectToGdbServer) { + debuggerService->requestConnectToGdbServer = std::bind([=](const GDBServerPreParam ¶m){ + auto dialog = new ConnectToServerDlg(); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->setParam(param); + dialog->exec(); + }, _1); + } + return true; } @@ -129,7 +139,7 @@ void DebugManager::run() } } -void DebugManager::remoteDebug(RemoteInfo info) +void DebugManager::remoteDebug(const RemoteInfo &info) { if (!currentDebugger) { LanguageService *service = dpfGetService(LanguageService); @@ -149,6 +159,14 @@ void DebugManager::remoteDebug(RemoteInfo info) AsynInvokeWithParam(currentDebugger->startDebugRemote, info); } +void DebugManager::connectToGdbServer(const GdbserverInfo &info) +{ + // only support gdb. + auto dapDebuger = qobject_cast(currentDebugger); + QtConcurrent::run([dapDebuger, &info]() { + dapDebuger->connectToGdbServer(info); + });} + void DebugManager::attachDebug() { AttachInfoDialog dialog; diff --git a/src/plugins/debugger/debugmanager.h b/src/plugins/debugger/debugmanager.h index d68191d5b..5f6352b17 100644 --- a/src/plugins/debugger/debugmanager.h +++ b/src/plugins/debugger/debugmanager.h @@ -49,7 +49,8 @@ public slots: /** * UI triggered. */ - void remoteDebug(RemoteInfo info); + void remoteDebug(const RemoteInfo &info); + void connectToGdbServer(const GdbserverInfo &info); void run(); void attachDebug(); void detachDebug(); diff --git a/src/plugins/debugger/interface/menumanager.cpp b/src/plugins/debugger/interface/menumanager.cpp index 0ea515cbb..834edb63e 100644 --- a/src/plugins/debugger/interface/menumanager.cpp +++ b/src/plugins/debugger/interface/menumanager.cpp @@ -12,6 +12,7 @@ #include "common/widget/appoutputpane.h" #include "services/window/windowservice.h" #include "remotedebug/remotedebugdlg.h" +#include "remotedebug/connecttoserverdlg.h" #include @@ -147,6 +148,17 @@ void MenuManager::initialize(WindowService *windowService) "debugger_remotedebug"); mDebug->addAction(actionImpl); + conenctToServerDebug.reset(new QAction(MWMDA_SERVER_DEBUG)); + connect(conenctToServerDebug.get(), &QAction::triggered, debugManager, [=]() { + auto dialog = new ConnectToServerDlg(); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->exec(); + }); + actionImpl = initAction(conenctToServerDebug.get(), "Debug.Server.Debug", + MWMDA_SERVER_DEBUG, QKeySequence(), + "debugger_connecttoserver"); + mDebug->addAction(actionImpl); + attachDebugging.reset(new QAction(MWMDA_ATTACH_DEBUG)); connect(attachDebugging.get(), &QAction::triggered, debugManager, &DebugManager::attachDebug); actionImpl = initAction(attachDebugging.get(), "Debug.Attach.Debugging", diff --git a/src/plugins/debugger/interface/menumanager.h b/src/plugins/debugger/interface/menumanager.h index 4680d9018..06a20dd24 100644 --- a/src/plugins/debugger/interface/menumanager.h +++ b/src/plugins/debugger/interface/menumanager.h @@ -43,6 +43,7 @@ public slots: QSharedPointer stepOut; QSharedPointer stepBack; QSharedPointer remoteDebug; + QSharedPointer conenctToServerDebug; }; #endif // MENUMANAGER_H diff --git a/src/plugins/debugger/interface/stackframemodel.cpp b/src/plugins/debugger/interface/stackframemodel.cpp index 13b1b2a80..1bf1ff718 100644 --- a/src/plugins/debugger/interface/stackframemodel.cpp +++ b/src/plugins/debugger/interface/stackframemodel.cpp @@ -125,7 +125,7 @@ void StackFrameModel::removeAll() StackFrameData StackFrameModel::currentFrame() const { - if (currentIndex == -1 || stackFrames.size() == 0) + if (currentIndex == -1 || stackFrames.size() == 0 || (stackFrames.size() < currentIndex)) return StackFrameData(); return stackFrames.at(currentIndex); diff --git a/src/plugins/debugger/remotedebug/connecttoserverdlg.cpp b/src/plugins/debugger/remotedebug/connecttoserverdlg.cpp new file mode 100644 index 000000000..21274b016 --- /dev/null +++ b/src/plugins/debugger/remotedebug/connecttoserverdlg.cpp @@ -0,0 +1,177 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "connecttoserverdlg.h" +#include "debugmanager.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +DWIDGET_USE_NAMESPACE +ConnectToServerDlg::ConnectToServerDlg(QWidget *parent) + : DDialog(parent) +{ + setupUi(); + + connect(selDebugEE, &DSuggestButton::clicked, this, [=]() { setFileByFileDialog(leDebugee); }); + connect(selProject, &DSuggestButton::clicked, this, [=]() { setDirByFileDialog(leProjectPath); }); + connect(selDebugInfo, &DSuggestButton::clicked, this, [=]() { setDirByFileDialog(leDebugInfo); }); +} + +void ConnectToServerDlg::on_pbtnOK_clicked() +{ + GdbserverInfo info; + + info.executablePath = leDebugee->text(); + info.initCommands = leCommands->toPlainText().split('\n'); + info.ip = leIP->text(); + bool ok; + info.port = lePort->text().toInt(&ok); + info.projectPath = leProjectPath->text(); + info.arg = leParam->text(); + info.debugInfo = leDebugInfo->text(); + if (!ok) { + lePort->clear(); + lePort->setPlaceholderText(tr("Port must be number")); + return; + } + + debugManager->connectToGdbServer(info); + accept(); +} + +void ConnectToServerDlg::on_pbtnCancel_clicked() +{ + reject(); +} + +void ConnectToServerDlg::setupUi() +{ + setWindowTitle(tr("Connect To GdbServer")); + setIcon(QIcon::fromTheme("ide")); + auto verticalLayout = static_cast(this->layout()); + verticalLayout->setContentsMargins(20, 11, 20, 11); + auto gridLayout = new QGridLayout(); + gridLayout->setSpacing(6); + gridLayout->setContentsMargins(0, 0, 10, 0); + + auto lbIP = new DLabel(this); + lbIP->setText(tr("IP:")); + leIP = new DLineEdit(this); + gridLayout->addWidget(lbIP, 1, 0); + gridLayout->addWidget(leIP, 1, 1, 1, 2); + + lePort = new DLineEdit(this); + auto lbPort = new DLabel(this); + lbPort->setText(tr("Port:")); + gridLayout->addWidget(lbPort, 2, 0); + gridLayout->addWidget(lePort, 2, 1, 1, 2); + + auto lbDebuggee = new DLabel(this); + lbDebuggee->setText(tr("Debuggee:")); + leDebugee = new DLineEdit(this); + selDebugEE = new DSuggestButton(this); + selDebugEE->setIcon(DStyle::standardIcon(style(), DStyle::SP_SelectElement)); + gridLayout->addWidget(lbDebuggee, 3, 0); + gridLayout->addWidget(leDebugee, 3, 1); + gridLayout->addWidget(selDebugEE, 3, 2); + + auto lbParam = new DLabel(this); + lbParam->setText(tr("Param:")); + leParam = new DLineEdit(this); + gridLayout->addWidget(lbParam, 4, 0); + gridLayout->addWidget(leParam, 4, 1, 1, 2); + + leCommands = new DTextEdit(this); + auto lbCommands = new DLabel(this); + lbCommands->setText(tr("Init Commands:")); + gridLayout->addWidget(lbCommands, 5, 0); + gridLayout->addWidget(leCommands, 5, 1, 1, 2); + + leProjectPath = new DLineEdit(this); + auto lbProjectPath = new DLabel(this); + lbProjectPath->setText(tr("Local Project Path:")); + selProject = new DSuggestButton(this); + selProject->setIcon(DStyle::standardIcon(style(), DStyle::SP_SelectElement)); + gridLayout->addWidget(lbProjectPath, 6, 0); + gridLayout->addWidget(leProjectPath, 6, 1); + gridLayout->addWidget(selProject, 6, 2); + + leDebugInfo = new DLineEdit(this); + auto lbDebugInfo = new DLabel(this); + lbDebugInfo->setText(tr("Debug Info:")); + selDebugInfo = new DSuggestButton(this); + selDebugInfo->setIcon(DStyle::standardIcon(style(), DStyle::SP_SelectElement)); + gridLayout->addWidget(lbDebugInfo, 7, 0); + gridLayout->addWidget(leDebugInfo, 7, 1); + gridLayout->addWidget(selDebugInfo, 7, 2); + + verticalLayout->addLayout(gridLayout); + + auto horizontalLayout = new QHBoxLayout(); + horizontalLayout->setSpacing(6); + auto pbtnCancel = new DPushButton(this); + pbtnCancel->setFixedWidth(173); + pbtnCancel->setText("Cancel"); + pbtnCancel->setObjectName(QStringLiteral("pbtnCancel")); + horizontalLayout->addWidget(pbtnCancel); + + DVerticalLine *vLine = new DVerticalLine; + vLine->setObjectName("VLine"); + vLine->setFixedHeight(30); + horizontalLayout->addWidget(vLine); + + auto pbtnOK = new DSuggestButton(this); + pbtnOK->setFixedWidth(173); + pbtnOK->setText(tr("OK")); + pbtnOK->setObjectName(QStringLiteral("pbtnOK")); + horizontalLayout->addWidget(pbtnOK); + + verticalLayout->addLayout(horizontalLayout); + QMetaObject::connectSlotsByName(this); +} + +void ConnectToServerDlg::setParam(const GdbserverInfo &info) +{ + leIP->setText(info.ip); + lePort->setText(QString::number(info.port)); + leDebugee->setText(info.executablePath); + leParam->setText(info.arg); + leCommands->setText(info.initCommands.join('\n')); + leProjectPath->setText(info.projectPath); + leDebugInfo->setText(info.debugInfo); +} + +void ConnectToServerDlg::setDirByFileDialog(DLineEdit *edit) +{ + if (!edit) + return; + + QString dir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); + QString filePath = DFileDialog::getExistingDirectory(this, "", dir); + if (filePath.isEmpty() && !QFileInfo(filePath).exists()) + return; + + edit->setText(filePath); +} + +void ConnectToServerDlg::setFileByFileDialog(DLineEdit *edit) +{ + if (!edit) + return; + + QString dir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); + QString filePath = DFileDialog::getOpenFileName(this, "", dir); + if (filePath.isEmpty() && !QFileInfo(filePath).exists()) + return; + + edit->setText(filePath); +} diff --git a/src/plugins/debugger/remotedebug/connecttoserverdlg.h b/src/plugins/debugger/remotedebug/connecttoserverdlg.h new file mode 100644 index 000000000..f231f5e85 --- /dev/null +++ b/src/plugins/debugger/remotedebug/connecttoserverdlg.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef CONNECTTOSERVERDLG_H +#define CONNECTTOSERVERDLG_H + +#include "services/debugger/debuggerservice.h" +#include "debuggerglobals.h" + +#include +#include +#include +#include + +class ConnectToServerDlg : public DTK_WIDGET_NAMESPACE::DDialog +{ + Q_OBJECT +public: + explicit ConnectToServerDlg(QWidget *parent = nullptr); + void setParam(const GdbserverInfo &info); + +private slots: + void on_pbtnOK_clicked(); + void on_pbtnCancel_clicked(); + +private: + void setupUi(); + + void setDirByFileDialog(Dtk::Widget::DLineEdit *edit); + void setFileByFileDialog(Dtk::Widget::DLineEdit *edit); + + Dtk::Widget::DLineEdit *lePort = nullptr; + Dtk::Widget::DLineEdit *leIP = nullptr; + Dtk::Widget::DLineEdit *leDebugee = nullptr; + Dtk::Widget::DLineEdit *leParam = nullptr; + Dtk::Widget::DLineEdit *leProjectPath = nullptr; + Dtk::Widget::DLineEdit *leDebugInfo = nullptr; + Dtk::Widget::DTextEdit *leCommands = nullptr; + + Dtk::Widget::DSuggestButton *selDebugEE = nullptr; + Dtk::Widget::DSuggestButton *selProject = nullptr; + Dtk::Widget::DSuggestButton *selDebugInfo = nullptr; +}; + +#endif // CONNECTTOSERVERDLG_H diff --git a/src/plugins/debugger/remotedebug/remotedebugdlg.cpp b/src/plugins/debugger/remotedebug/remotedebugdlg.cpp index afa6f2328..7c3fdb77c 100644 --- a/src/plugins/debugger/remotedebug/remotedebugdlg.cpp +++ b/src/plugins/debugger/remotedebug/remotedebugdlg.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -44,11 +45,13 @@ void RemoteDebugDlg::on_pbtnCancel_clicked() void RemoteDebugDlg::setupUi() { setWindowTitle(tr("Remote Debug")); + setIcon(QIcon::fromTheme("ide")); resize(400, 196); auto verticalLayout = static_cast(this->layout()); verticalLayout->setSpacing(6); verticalLayout->setContentsMargins(11, 11, 11, 11); auto gridLayout = new QGridLayout(); + gridLayout->setContentsMargins(0, 0, 10, 0); gridLayout->setSpacing(6); auto lbDebuggee = new DLabel(this); lbDebuggee->setText(tr("Debuggee:")); @@ -94,24 +97,24 @@ void RemoteDebugDlg::setupUi() verticalLayout->addLayout(gridLayout); - auto horizontalLayout = new QHBoxLayout(); - horizontalLayout->setSpacing(6); - auto horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + auto horizontalLayout = new QHBoxLayout; + auto pbtnCancel = new DPushButton(this); + pbtnCancel->setFixedWidth(173); + pbtnCancel->setText("Cancel"); + pbtnCancel->setObjectName(QStringLiteral("pbtnCancel")); + horizontalLayout->addWidget(pbtnCancel); - horizontalLayout->addItem(horizontalSpacer); + DVerticalLine *vLine = new DVerticalLine; + vLine->setObjectName("VLine"); + vLine->setFixedHeight(30); + horizontalLayout->addWidget(vLine); - auto pbtnOK = new DPushButton(this); + auto pbtnOK = new DSuggestButton(this); + pbtnOK->setFixedWidth(173); pbtnOK->setText(tr("OK")); pbtnOK->setObjectName(QStringLiteral("pbtnOK")); - horizontalLayout->addWidget(pbtnOK); - auto pbtnCancel = new DPushButton(this); - pbtnCancel->setText("Cancel"); - pbtnCancel->setObjectName(QStringLiteral("pbtnCancel")); - - horizontalLayout->addWidget(pbtnCancel); - verticalLayout->addLayout(horizontalLayout); QMetaObject::connectSlotsByName(this); diff --git a/src/plugins/linglong/gui/generatedialog.cpp b/src/plugins/linglong/gui/generatedialog.cpp index 6855a17be..a97fc82c5 100644 --- a/src/plugins/linglong/gui/generatedialog.cpp +++ b/src/plugins/linglong/gui/generatedialog.cpp @@ -81,7 +81,7 @@ void GenerateDialog::initUi() d->versionEdit = new DLineEdit(this); d->versionEdit->setPlaceholderText(tr("0.0.0.1")); d->kindCbBox = new DComboBox(this); - d->kindCbBox->addItem("App"); + d->kindCbBox->addItem("app"); d->dependsCbBox = new DComboBox(this); d->dependsCbBox->addItems({ Depends_Version_V20, Depends_Version_V23 }); d->descriptionEdit = new DLineEdit(this); @@ -161,8 +161,8 @@ void GenerateDialog::generate() base["base"] = "org.deepin.foundation/20.0.0"; runtime["runtime"] = "org.deepin.Runtime/20.0.0"; } else { - base["base"] = "org.deepin.foundation/23.0.0"; - runtime["runtime"] = "org.deepin.Runtime/23.0.1"; + base["base"] = "org.deepin.base/23.1.0"; + runtime["runtime"] = "org.deepin.runtime.dtk/23.1.1"; } YAML::Node command; for (auto cmd : d->commandEdit->text().split(",")) diff --git a/src/plugins/linglong/llgenerator.cpp b/src/plugins/linglong/llgenerator.cpp index 9c3417018..a6cb9deb7 100644 --- a/src/plugins/linglong/llgenerator.cpp +++ b/src/plugins/linglong/llgenerator.cpp @@ -4,11 +4,69 @@ #include "llgenerator.h" #include "common/widget/outputpane.h" +#include "services/window/windowservice.h" + +#include using namespace dpfservice; +struct PackageInfo { + QString id; + QString name; +}; + +PackageInfo readPackageFromYaml(const QString &filePath) +{ + YAML::Node config = YAML::LoadFile(filePath.toStdString()); + + PackageInfo ret; + if (config["package"]) { + YAML::Node package = config["package"]; + + if (package["id"]) { + QString id = QString::fromStdString(package["id"].as()); + ret.id = id; + } + + if (package["name"]) { + QString name = QString::fromStdString(package["name"].as()); + ret.name = name; + } + } + return ret; +} + +int getValidPort() +{ + auto checkPortFree = [](int port) { + QProcess process; + QString cmd = QString("fuser %1/tcp").arg(port); + process.start(cmd); + process.waitForFinished(); + QString ret = process.readAll(); + if (ret.isEmpty()) + return true; + return false; + }; + + int port = 12345; + int kPort = port; + int maxTryNum = 100; + + while (port - kPort < maxTryNum) { + if (checkPortFree(port)) { + return port; + } + port++; + } + + return 0; +} + LLGenerator::LLGenerator() { + terminalSrv = dpfGetService(TerminalService); + debuggerSrv = dpfGetService(DebuggerService); } LLGenerator::~LLGenerator() @@ -24,12 +82,51 @@ bool LLGenerator::prepareDebug(const QMap ¶m, QString &re { Q_UNUSED(param) Q_UNUSED(retMsg) + return true; } bool LLGenerator::requestDAPPort(const QString &ppid, const QMap ¶m, QString &retMsg) { - retMsg = tr("debug of Linglong project is not supported"); + auto workspacePath = param.value("workspace").toString(); + auto executableDir = workspacePath + "/linglong/output/binary/files/bin/"; + if (!QFileInfo(executableDir).exists()) { + retMsg = tr("This Linglong Project has no executable program"); + return false; + } + + QMetaObject::invokeMethod(this, [=, workspacePath](){ + auto yamlFile = workspacePath + "/linglong.yaml"; + auto packageInfo = readPackageFromYaml(yamlFile); + + QUuid newConsole = terminalSrv->createConsole("LLDebug", true); + QProcess startEnv; + startEnv.setProgram("ll-builder"); + startEnv.setWorkingDirectory(param.value("workspace").toString()); + startEnv.setArguments({ "run", "--debug", "--exec", "/bin/bash" }); + terminalSrv->run2Console(newConsole, startEnv); + + QProcess gdbserver; + gdbserver.setProgram("gdbserver"); + QString port = QString::number(getValidPort()); + QString binPath = QString("/opt/apps/%1/files/bin/%2").arg(packageInfo.id, packageInfo.name); + gdbserver.setArguments({ QString(":%1").arg(port), binPath}); + terminalSrv->run2Console(newConsole, gdbserver); + + GDBServerPreParam preParam; + preParam.ip = "127.0.0.1"; + preParam.port = port.toInt(); + preParam.projectPath = workspacePath; + preParam.initCommands.append(QString("set substitute-path /project %1").arg(workspacePath)); + QString debugFilePath = workspacePath + "/linglong/output/develop/files/lib/debug"; + if (QFileInfo(debugFilePath).exists()) + preParam.debugInfo = debugFilePath; + QString executablePath = workspacePath + "/linglong/output/binary/files/bin/" + packageInfo.name; + if (QFileInfo(executablePath).exists()) + preParam.executablePath = executablePath; + debuggerSrv->requestConnectToGdbServer(preParam); + }); + return false; } @@ -72,7 +169,7 @@ QMap LLGenerator::getDebugArguments(const dpfservice::Project Q_UNUSED(currentFile) QMap param; - //param.insert("workspace", projectInfo.workspaceFolder()); + param.insert("workspace", projectInfo.workspaceFolder()); return param; } diff --git a/src/plugins/linglong/llgenerator.h b/src/plugins/linglong/llgenerator.h index 3f420f67a..ea6be6501 100644 --- a/src/plugins/linglong/llgenerator.h +++ b/src/plugins/linglong/llgenerator.h @@ -7,6 +7,8 @@ #include "llglobal.h" #include "services/language/languagegenerator.h" +#include "services/terminal/terminalservice.h" +#include "services/debugger/debuggerservice.h" class LLGenerator : public dpfservice::LanguageGenerator { @@ -32,6 +34,9 @@ class LLGenerator : public dpfservice::LanguageGenerator dpfservice::RunCommandInfo getRunArguments(const dpfservice::ProjectInfo &projectInfo, const QString ¤tFile) override; +private: + dpfservice::TerminalService *terminalSrv { nullptr }; + dpfservice::DebuggerService *debuggerSrv { nullptr }; }; #endif // LLGENERATOR_H diff --git a/src/services/debugger/debuggerservice.h b/src/services/debugger/debuggerservice.h index 5ff27df2d..94fd891fa 100644 --- a/src/services/debugger/debuggerservice.h +++ b/src/services/debugger/debuggerservice.h @@ -11,6 +11,18 @@ namespace dpfservice { +struct GDBServerPreParam +{ + QString ip = ""; + int port = 0; + + QString executablePath = ""; + QString projectPath = ""; + QString arg = ""; + QStringList initCommands = {}; + QString debugInfo = ""; +}; + class SERVICE_EXPORT DebuggerService final : public dpf::PluginService, dpf::AutoServiceRegister { @@ -44,6 +56,12 @@ class SERVICE_EXPORT DebuggerService final : public dpf::PluginService, */ DPF_INTERFACE(void, registerDebugger, const QString &kit, AbstractDebugger *debugger); + /** + * @brief requestConnectToGdbServer, open dialog and set preparam + * @param preParam + */ + DPF_INTERFACE(void, requestConnectToGdbServer, const GDBServerPreParam &preParam); + DPF_INTERFACE(AbstractDebugger::RunState, getDebugState); }; diff --git a/src/services/project/directoryasynparse.cpp b/src/services/project/directoryasynparse.cpp index 347a2ac8b..4d9ab96b9 100644 --- a/src/services/project/directoryasynparse.cpp +++ b/src/services/project/directoryasynparse.cpp @@ -35,6 +35,7 @@ void DirectoryAsynParse::parseProject(const dpfservice::ProjectInfo &info) { createRows(info.workspaceFolder()); emit itemsModified(d->rows); + emit parseDone(); } QSet DirectoryAsynParse::getFilelist() diff --git a/src/services/project/directoryasynparse.h b/src/services/project/directoryasynparse.h index 91d0bbcdd..7e3e0e276 100644 --- a/src/services/project/directoryasynparse.h +++ b/src/services/project/directoryasynparse.h @@ -34,6 +34,7 @@ class DirectoryAsynParse : public QFileSystemWatcher signals: void itemsModified(const QList &info); void parsedError(const ParseInfo &info); + void parseDone(); public slots: void parseProject(const dpfservice::ProjectInfo &info); diff --git a/src/services/project/directorygenerator.cpp b/src/services/project/directorygenerator.cpp index f58246afe..76437ee22 100644 --- a/src/services/project/directorygenerator.cpp +++ b/src/services/project/directorygenerator.cpp @@ -14,6 +14,7 @@ class DirectoryGeneratorPrivate friend class dpfservice::DirectoryGenerator; QStandardItem *configureRootItem { nullptr }; QHash projectParses {}; + QMap allProjectInfo; dpfservice::ProjectInfo prjInfo; }; @@ -54,6 +55,8 @@ bool DirectoryGenerator::configure(const dpfservice::ProjectInfo &projectInfo) dpfservice::ProjectGenerator::configure(projectInfo); auto root = createRootItem(projectInfo); + d->allProjectInfo.insert(root, projectInfo); + ProjectInfo::set(root, projectInfo); ProjectService *projectService = dpfGetService(ProjectService); if (projectService && root) { projectService->addRootItem(root); @@ -74,7 +77,13 @@ QStandardItem *DirectoryGenerator::createRootItem(const dpfservice::ProjectInfo QObject::connect(d->projectParses[rootItem], &DirectoryAsynParse::itemsModified, this, &DirectoryGenerator::doProjectChildsModified, - Qt::ConnectionType::UniqueConnection); + Qt::UniqueConnection); + QObject::connect(d->projectParses[rootItem], + &DirectoryAsynParse::parseDone, + this, [&info](){ + project.activeProject(info.kitName(), info.language(), info.workspaceFolder()); + }, + Qt::UniqueConnection); QtConcurrent::run(parser, &DirectoryAsynParse::parseProject, info); return rootItem; @@ -99,11 +108,16 @@ void DirectoryGenerator::removeRootItem(QStandardItem *root) void DirectoryGenerator::doProjectChildsModified(const QList &info) { - auto sourceFiles = d->projectParses[d->configureRootItem]->getFilelist(); - ProjectInfo tempInfo = prjInfo; + auto modifiedItem = d->configureRootItem; + if (sender() && (d->projectParses[d->configureRootItem] != sender())) { + auto parser = qobject_cast(sender()); + modifiedItem = d->projectParses.key(parser); + } + auto sourceFiles = d->projectParses[modifiedItem]->getFilelist(); + auto modifiedProjectInfo = ProjectInfo::get(modifiedItem); + ProjectInfo tempInfo = modifiedProjectInfo; tempInfo.setSourceFiles(sourceFiles); - ProjectInfo::set(d->configureRootItem, tempInfo); - project.activeProject(tempInfo.kitName(), tempInfo.language(), tempInfo.workspaceFolder()); + ProjectInfo::set(modifiedItem, tempInfo); auto rootItem = d->projectParses.key(qobject_cast(sender())); if (rootItem) { diff --git a/src/services/window/windowelement.h b/src/services/window/windowelement.h index b87902265..a2013335b 100644 --- a/src/services/window/windowelement.h +++ b/src/services/window/windowelement.h @@ -70,6 +70,7 @@ inline const QString MWMDA_STEP_IN { QAction::tr("Step In") }; inline const QString MWMDA_STEP_OUT { QAction::tr("Step Out") }; inline const QString MWMDA_STEP_BACK { QAction::tr("Step Back") }; inline const QString MWMDA_REMOTE_DEBUG { QAction::tr("Remote Debug") }; +inline const QString MWMDA_SERVER_DEBUG { QAction::tr("Connect To GDB Server") }; // MWMTA = MWM Tool Action inline const QString MWM_TOOLS { QMenu::tr("&Tools") }; diff --git a/src/tools/debugadapter/dapsession.cpp b/src/tools/debugadapter/dapsession.cpp index f0f080105..a9390377a 100644 --- a/src/tools/debugadapter/dapsession.cpp +++ b/src/tools/debugadapter/dapsession.cpp @@ -347,10 +347,6 @@ void DapSession::registerHanlder() foreach (auto arg, request.args.value()) { arguments.push_back(arg.c_str()); } - // --args : add arguments for gdb. except : rr, runcoredump - if (request.name.value() != "rr" && arguments.size() >= 2 && !(arguments.size() == 2 && arguments.last().endsWith(".core"))) - arguments.insert(0, "--args"); - arguments.removeAll(""); } d->debugger->initDebugger(request.name.value().c_str(), arguments); if (request.environment.has_value()) { diff --git a/src/tools/debugadapter/debugger/gdbmi/gdbdebugger.cpp b/src/tools/debugadapter/debugger/gdbmi/gdbdebugger.cpp index c1379d1f3..fb86bd140 100644 --- a/src/tools/debugadapter/debugger/gdbmi/gdbdebugger.cpp +++ b/src/tools/debugadapter/debugger/gdbmi/gdbdebugger.cpp @@ -8,7 +8,6 @@ #include "common/util/custompaths.h" #include -#include #include class GDBDebuggerPrivate { @@ -68,8 +67,8 @@ GDBDebugger::~GDBDebugger() void GDBDebugger::init() { //use to debugging adapter -// DebugManager::instance()->command("set logging file /tmp/log.txt"); -// DebugManager::instance()->command("set logging on"); + // DebugManager::instance()->command("set logging file /tmp/log.txt"); + // DebugManager::instance()->command("set logging on"); QString prettyPrintersPath = CustomPaths::CustomPaths::global(CustomPaths::Scripts) + "/prettyprinters"; DebugManager::instance()->command(QString("python sys.path.insert(0, \"%1\")").arg(prettyPrintersPath)); @@ -651,7 +650,16 @@ void GDBDebugger::parseResultData(gdbmi::Record &record) } else if (record.message == "connected") { emit targetRemoteConnected(); } else if (record.message == "error") { - emit gdbError(gdbmi::escapedText(record.payload.toMap().value("msg").toString())); + QString msg = gdbmi::escapedText(record.payload.toMap().value("msg").toString()); + if (msg.contains("Try \"help target\" or \"continue\"")) { + dap::StoppedEvent stoppedEvent; + stoppedEvent.reason = "step"; + stoppedEvent.threadId = 1; + stoppedEvent.allThreadsStopped = true; + stoppedEvent.description = record.payload.toMap().value("msg").toString().toStdString(); + emit asyncStopped(stoppedEvent); + } + emit gdbError(msg); emit updateExceptResponse(record.token, record.payload); } else if (record.message == "exit") { d->firstPromt.store(false); diff --git a/src/tools/debugadapter/debugmanager.cpp b/src/tools/debugadapter/debugmanager.cpp index 45491288c..50a5d75b9 100644 --- a/src/tools/debugadapter/debugmanager.cpp +++ b/src/tools/debugadapter/debugmanager.cpp @@ -168,6 +168,7 @@ void DebugManager::execute() foreach (auto arg, d->debugger->preArguments()) { d->arguments.prepend(arg); } + d->arguments.removeAll(""); d->process->setArguments(d->arguments); d->process->setProgram(d->debugger->program()); d->process->setEnvironment(d->environment);