Skip to content

Commit

Permalink
Support debug portfile (#9)
Browse files Browse the repository at this point in the history
* Add new component vcpkg portfile debugger

* improve code

* improve & fix

* get debugPoints

* improve code, clean commands when no valid breakpoints

* add missing option

* update version

* imrpove code, adapt nonWindows

* add doc

* Rename code file

* More logs

* Adapt to nonWindows

* Remove same ports

* fix pipe name is null in Launch.json

* only allow to set breakpoints in one port

---------

Co-authored-by: jyu49 <[email protected]>
  • Loading branch information
JackBoosY and jyu49 authored Feb 27, 2024
1 parent 2fb23ec commit de8b5dc
Show file tree
Hide file tree
Showing 4 changed files with 339 additions and 2 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,9 @@ Note: please only enable/disable in `workspace`!

1. Enable vcpkg integration.
2. Set vcpkg path.
3. Autocompletion will be enabled automatically when typing `"`.
3. Autocompletion will be enabled automatically when typing `"`.

### Debug portfile or other vcpkg provided cmake code

1. Set debug point in the portfile.cmake (required) or other cmake file.
2. Open `Run and Debug` in left side bar, select `Debug portfile(s)`, click the green triangle to run debugging.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"icon": "images/vcpkg-logo.png",
"publisher": "JackBoosY",
"license": "MIT",
"version": "2.0.9",
"version": "2.1.0",
"engines": {
"vscode": "^1.76.0"
},
Expand Down
9 changes: 9 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import { ConfigurationManager } from './configuration';
import {SettingsDocument} from './settingsDocument';
import { VersionManager } from './versionManager';
import {VcpkgLogMgr} from './log';
import {VcpkgDebugger} from './vcpkgDebugger';

let logMgr : VcpkgLogMgr;
let configMgr : ConfigurationManager;
let verMgr : VersionManager;
let vcpkgDebugger : VcpkgDebugger;
let disposables: vscode.Disposable[];

// This method is called when your extension is activated
Expand All @@ -20,6 +22,7 @@ export function activate(context: vscode.ExtensionContext) {
logMgr = new VcpkgLogMgr();
verMgr = new VersionManager();
configMgr = new ConfigurationManager(/*context, */verMgr, logMgr);
vcpkgDebugger = new VcpkgDebugger(logMgr);

configMgr.logInfo('Trying to active vcpkg plugin...');

Expand Down Expand Up @@ -68,6 +71,12 @@ export function activate(context: vscode.ExtensionContext) {
vscode.commands.executeCommand('workbench.action.openWalkthrough', 'JackBoosY.vcpkg-cmake-tools#start', false);
})
);

context.subscriptions.push(vscode.debug.onDidChangeBreakpoints(
session => {
vcpkgDebugger.updateConfigurations();
}
))

configMgr.logInfo('All the event are registered.');
}
Expand Down
323 changes: 323 additions & 0 deletions src/vcpkgDebugger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,323 @@
import * as vscode from 'vscode';
import {VcpkgLogMgr} from './log';
import { debug } from 'vscode';

export class VcpkgDebugger {
private tasksJsonFileName = "tasks";
private launchJsonFileName = "launch";

private _logMgr : VcpkgLogMgr;

constructor(logMgr: VcpkgLogMgr)
{
this._logMgr = logMgr;

this.updateConfigurations();
}

private getTasksJsonContent()
{
this._logMgr.logInfo("Loading tasks json content.");
return this.readFromFile(this.tasksJsonFileName);
}

private getModifiedPorts()
{
let ports = new Array;
let breakPoints = debug.breakpoints;
for (let index = 0; index < breakPoints.length; index++) {
const element = breakPoints[index];
if (!element.enabled)
{
continue;
}
// @ts-ignore
if (element.location.uri.toString().search("portfile.cmake") !== -1) {
// @ts-ignore
let valid = element.location.uri.toString().substring(element.location.uri.toString().search("ports/") + "ports/".length, element.location.uri.toString().search("/portfile.cmake"));
if (ports.indexOf(valid) === -1)
{
ports.push(valid);
}
}
}

if (!ports.length)
{
this._logMgr.logInfo("No valid breakpoint.");
return "";
}

if (ports.length !== 1)
{
this._logMgr.logInfo("Detected multiple ports. Not supported.");
vscode.window.showErrorMessage("Only supports to set breakpoint in one port!");
return;
}

this._logMgr.logInfo("Breakpoints are from ports:");
let portNames = "";
for (let index = 0; index < ports.length; index++) {
this._logMgr.logInfo(ports[index]);
portNames += ports[index];
portNames += " ";
}

return portNames;
}

private getDebuggerPipe()
{
if (process.platform === 'win32')
{
return "\\\\.\\pipe\\vcpkg_ext_portfile_dbg";
}
else
{
return "/tmp/vcpkg_ext_portfile_dbg";
}
}

private generateCommand()
{
this._logMgr.logInfo("Genereating commands.");
let modifiedPorts = this.getModifiedPorts();
if (modifiedPorts === "") {
return "";
}

let exeSuffix = "";
if (process.platform === "win32")
{
exeSuffix = ".exe";
}

return "\"${workspaceFolder}/vcpkg" + exeSuffix + "\" remove " + modifiedPorts + " --recurse; & \"${workspaceFolder}/vcpkg" + exeSuffix + "\" install " + modifiedPorts + " --no-binarycaching --x-cmake-debug " + this.getDebuggerPipe();
}

private async cleanConfigurations()
{
this._logMgr.logInfo("Cleanning debugging configurations");
// clean launch json
let fullContent = this.getLaunchJsonContent();
if (JSON.stringify(fullContent) !== "{}")
{
if (fullContent.has("configurations"))
{
let newConfigs = new Array;
for (let index = 0; index < fullContent["configurations"].length; index++)
{
const element = fullContent["configurations"][index];
if (element["name"] !== "Debug portfile(s)")
{
newConfigs.push(element);
}
}
await this.writeToFile(this.launchJsonFileName, "configurations", newConfigs);
}
}

// clean tasks json
fullContent = this.getTasksJsonContent();
if (JSON.stringify(fullContent) !== "{}")
{
if (fullContent.has("tasks"))
{
let newConfigs = new Array;
for (let index = 0; index < fullContent["tasks"].length; index++)
{
const element = fullContent["tasks"][index];
if (element["label"] !== "Debug vcpkg commands")
{
newConfigs.push(element);
}
}
await this.writeToFile(this.tasksJsonFileName, "tasks", newConfigs);
}
}
}

public async updateConfigurations()
{
this._logMgr.logInfo("Updating debugging configurations.");
// update tasks json first since we may need to clean all configurations in update launch json
this.updateTasksJson();
this.updateLaunchJson();
}

private async updateTasksJson()
{
this._logMgr.logInfo("Updating tasks.json");

let modifiedConfig = new Array;
let staticConfiguration = {
"label": "Debug vcpkg commands",
"type": "shell",
"isBackground": true,
"command": "",
"problemMatcher": [
{
"pattern": [
{
"regexp": "",
"file": 1,
"location": 2,
"message": 3
}
],
"background": {
"activeOnStart": true,
"beginsPattern": ".",
"endsPattern": "Waiting for debugger client to connect"
}
}
]
};

let fullContent = this.getTasksJsonContent();

if (JSON.stringify(fullContent) === "{}")
{
this._logMgr.logInfo("No tasks.json file found, creating.");
staticConfiguration["command"] = this.generateCommand();
if (!staticConfiguration["command"].length)
{
this.cleanConfigurations();
return;
}
//fullContent.update("version", "2.0.0");
modifiedConfig.push(staticConfiguration);
}
else
{
if (fullContent.has("tasks"))
{
let found = false;
for (let index = 0; index < fullContent["tasks"].length; index++)
{
const element = fullContent["tasks"][index];
if (element["label"] === "Debug vcpkg commands")
{
this._logMgr.logInfo("Found exists task, update now.");

let newData = staticConfiguration;
newData["command"] = this.generateCommand();
if (!newData["command"].length)
{
this.cleanConfigurations();
return;
}

// update new command
modifiedConfig.push(newData);
found = true;

continue;
}
modifiedConfig.push(element);
}
if (!found)
{
this._logMgr.logInfo("Matched tasks not found, new one now.");

staticConfiguration["command"] = this.generateCommand();
if (!staticConfiguration["command"].length)
{
this.cleanConfigurations();
return;
}
modifiedConfig.push(staticConfiguration);
}
}
else
{
this._logMgr.logInfo("Tasks item not found, new one now.");

staticConfiguration["command"] = this.generateCommand();
if (!staticConfiguration["command"].length)
{
this.cleanConfigurations();
return;
}
modifiedConfig.push(staticConfiguration);
}
}

await this.writeToFile(this.tasksJsonFileName, "tasks", modifiedConfig);
}

private getLaunchJsonContent()
{
this._logMgr.logInfo("Loading launch json content.");
return this.readFromFile(this.launchJsonFileName);
}

private async updateLaunchJson()
{
this._logMgr.logInfo("Updating launch.json");

let modifiedConfig = new Array;
let staticConfiguration = {
"type": "cmake",
"request": "launch",
"name": "Debug portfile(s)",
"cmakeDebugType": "external",
"pipeName": this.getDebuggerPipe(),
"preLaunchTask": "Debug vcpkg commands"};

let fullContent = this.getLaunchJsonContent();
if (JSON.stringify(fullContent) === "{}")
{
this._logMgr.logInfo("No launch.json file found, creating.");
// only needs to be updated since it's fixed.
modifiedConfig.push(staticConfiguration);
//fullContent.update("version", "0.2.0");
}
else
{
if (fullContent.has("configurations"))
{
let found = false;
for (let index = 0; index < fullContent["configurations"].length; index++)
{
const element = fullContent["configurations"][index];
if (element["name"] === "Debug portfile(s)")
{
this._logMgr.logInfo("Found exists configurations, update now.");
//fullContent["configurations"][index] = staticConfiguration;
modifiedConfig.push(staticConfiguration);

found = true;
}
else
{
modifiedConfig.push(element);
}

}
if (!found)
{
this._logMgr.logInfo("Matched configurations items not found, new one now.");
modifiedConfig.push(staticConfiguration);
}
}
else
{
this._logMgr.logInfo("Configurations itme not found, noew one now.");
modifiedConfig.push(staticConfiguration);
}
}
await this.writeToFile(this.launchJsonFileName, "configurations", modifiedConfig);
}

private readFromFile(fileName: string)
{
return vscode.workspace.getConfiguration(fileName);
}

private async writeToFile(fileName: string, scope: string, content: object)
{
this._logMgr.logInfo("Updating " + fileName + " - " + scope);
await vscode.workspace.getConfiguration(fileName).update(scope, content, null);
}
}

0 comments on commit de8b5dc

Please sign in to comment.