Skip to content

Commit 3b37f6b

Browse files
CopilotOmotola
andauthored
Allow custom debug adapter type in cmake.debugConfig (#4818)
* Initial plan * feat: allow custom debug adapter type in cmake.debugConfig When `type` is specified in `cmake.debugConfig`, automatic debugger detection from the CMake cache is skipped. Instead, a minimal base configuration is built from the target (program, cwd, name) and the user's full configuration is overlaid. This enables using any debug adapter (e.g., codelldb, lldb) with arbitrary properties. The `CppDebugConfiguration` interface now accepts `type` and arbitrary additional properties. The `cmake.debugConfig` JSON schema adds `type` and `additionalProperties: true`. Fixes #4050 Co-authored-by: Omotola <[email protected]> * refactor: exclude program from userConfig before Object.assign Address code review feedback by destructuring program out of userConfig before overlay, preventing the fragile double-assignment pattern. Co-authored-by: Omotola <[email protected]> * Re-add debug property and update documentation --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: Omotola <[email protected]> Co-authored-by: Omotola <[email protected]>
1 parent f9b1a80 commit 3b37f6b

7 files changed

Lines changed: 117 additions & 57 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## 1.23
44

55
Features:
6+
- Allow specifying a custom debug adapter type in `cmake.debugConfig` via the `type` property. When set, automatic debugger detection is skipped and any debug adapter (e.g., `codelldb`, `lldb`) can be used with arbitrary configuration properties. [#4818](https://github.com/microsoft/vscode-cmake-tools/pull/4818)
67
- Add `${cmake.testEnvironment}` placeholder for launch.json that resolves to the CTest `ENVIRONMENT` test property, and automatically include CTest environment variables when debugging tests without a launch configuration. [#4572](https://github.com/microsoft/vscode-cmake-tools/issues/4572) [#4821](https://github.com/microsoft/vscode-cmake-tools/pull/4821)
78
- Add "Delete Build Directory and Reconfigure" command that removes the entire build directory before reconfiguring, ensuring a completely clean state. [#4826](https://github.com/microsoft/vscode-cmake-tools/pull/4826)
89
- Add `cmake.shell` setting to route CMake/CTest/CPack subprocess invocations through a custom shell (e.g., Git Bash, MSYS2), enabling embedded toolchains that require POSIX path translation on Windows. [#1750](https://github.com/microsoft/vscode-cmake-tools/issues/1750)

docs/cmake-settings.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Options that support substitution, in the table below, allow variable references
4242
| `cmake.ctestArgs` | An array of additional arguments to pass to CTest. | `[]` | yes |
4343
| `cmake.ctestDefaultArgs` | Default arguments to pass to CTest. | `["-T", "test", "--output-on-failure"]` | no |
4444
| `cmake.ctestPath` | Path to CTest executable. | `null` | no |
45-
| `cmake.debugConfig`| The debug configuration to use when debugging a target | `null` (no values) | yes |
45+
| `cmake.debugConfig`| The debug configuration to use when debugging a target. When `type` is specified, automatic debugger detection is skipped and a custom debug adapter can be used. Additional properties required by the debug adapter can be added freely. | `null` (no values) | yes |
4646
| `cmake.defaultActiveFolder`| The name of active folder, which be used as default (Only works when `cmake.autoSelectActiveFolder` is disabled). | `""` | no |
4747
| `cmake.defaultVariants` | Override the default set of variants that will be supplied when no variants file is present. See [CMake variants](variants.md). | See package.json | no |
4848
| `cmake.deleteBuildDirOnCleanConfigure` | If `true`, delete build directory during clean configure. | `false` | no |

docs/debug-launch.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ From there, you can press the play button by the `Launch` node to run it in term
3030
CMake Tools lets you start a debugger on a target without creating a `launch.json`.
3131

3232
> **Note:**
33-
> Only the debugger from Microsoft's `vscode-ms-vscode.cpptools` extension supports quick-debugging. See [Debug using a launch.json file](#debug-using-a-launchjson-file), below, for information about `launch.json` and using other debuggers.
33+
> By default, quick-debugging auto-detects the debugger from the CMake cache and uses Microsoft's `vscode-ms-vscode.cpptools` debug adapters (`cppdbg` / `cppvsdbg`). To use a different debug adapter, see [Customize the debug adapter](#customize-the-debug-adapter) below.
3434
3535
Start a debugging session on the active target by running the *CMake: Debug* command from the VS Code command palette, by selecting the Debug button in the status bar or CMake Tools sidebar Project Status View, or by pressing the keyboard shortcut (the default is **Shift+F5**).
3636

@@ -39,6 +39,26 @@ Start a debugging session on the active target by running the *CMake: Debug* com
3939
> **Note:**
4040
> Quick-debugging does not let you specify program arguments or other debugging options. See the next section for more options.
4141
42+
## Customize the debug adapter
43+
44+
You can use any debug adapter with CMake Tools quick-debugging by setting the `type` property in the `cmake.debugConfig` setting. When `type` is specified, CMake Tools skips automatic debugger detection and builds a minimal launch configuration from the selected target, then merges in all properties from `cmake.debugConfig`. This lets you use adapters like `lldb`, `codelldb`, or any other installed debug extension without creating a `launch.json`.
45+
46+
Add the following to your `.vscode/settings.json`:
47+
48+
```jsonc
49+
{
50+
"cmake.debugConfig": {
51+
"type": "lldb", // any installed debug adapter type
52+
"request": "launch",
53+
"stopOnEntry": false
54+
}
55+
}
56+
```
57+
58+
Then run **CMake: Debug Target** from the command palette. CMake Tools will automatically fill in `program`, `cwd`, and `name` from the selected target, and apply your settings on top. Any property recognized by the debug adapter can be added to `cmake.debugConfig`.
59+
60+
If you omit `type`, CMake Tools falls back to the original behavior: auto-detecting `cppdbg` or `cppvsdbg` from the CMake cache.
61+
4262
## Debug using a launch.json file
4363

4464
You can specify the working directory or command line arguments for debugging, or use another debugger than the one included with Microsoft's `vscode-ms-vscode.cpptools`, by creating a `launch.json` file.

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,7 +2753,12 @@
27532753
"cmake.debugConfig": {
27542754
"type": "object",
27552755
"description": "%cmake-tools.configuration.cmake.debugConfig.description%",
2756+
"additionalProperties": true,
27562757
"properties": {
2758+
"type": {
2759+
"type": "string",
2760+
"markdownDescription": "%cmake-tools.configuration.cmake.debugConfig.type.description%"
2761+
},
27572762
"symbolSearchPath": {
27582763
"type": "string",
27592764
"description": "%cmake-tools.configuration.cmake.debugConfig.symbolSearchPath.description%"

package.nls.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,8 @@
217217
]
218218
},
219219
"cmake-tools.configuration.cmake.additionalBuildProblemMatchers.code": "The capture group index for an optional diagnostic code.",
220-
"cmake-tools.configuration.cmake.debugConfig.description": "The debug configuration to use when debugging a target.",
220+
"cmake-tools.configuration.cmake.debugConfig.description": "The debug configuration to use when debugging a target. When `type` is specified, the auto-detected debugger configuration is skipped and only a minimal base configuration (program, cwd, name) is generated from the target. All other properties are applied from this setting, allowing full control over the debug launch configuration for any debug adapter.",
221+
"cmake-tools.configuration.cmake.debugConfig.type.description": "The debug adapter type to use (e.g., `cppdbg`, `cppvsdbg`, `lldb`, `codelldb`). When set, skips the automatic debugger detection from the CMake cache and uses this type directly. Any additional properties required by the debug adapter can be added to `#cmake.debugConfig#`.",
221222
"cmake-tools.configuration.cmake.debugConfig.symbolSearchPath.description": "Visual Studio debugger symbol search paths.",
222223
"cmake-tools.configuration.cmake.debugConfig.additionalSOLibSearchPath.description": "Paths for GDB or LLDB to search for .so files.",
223224
"cmake-tools.configuration.cmake.debugConfig.externalConsole.description": "Launch an external console for the program.",

src/cmakeProject.ts

Lines changed: 85 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2611,29 +2611,48 @@ export class CMakeProject {
26112611
};
26122612

26132613
let debugConfig;
2614-
try {
2615-
const cache = await CMakeCache.fromPath(drv.cachePath);
2616-
debugConfig = await debuggerModule.getDebugConfigurationFromCache(cache, target, process.platform,
2617-
this.workspaceContext.config.debugConfig?.MIMode,
2618-
this.workspaceContext.config.debugConfig?.miDebuggerPath);
2619-
} catch (error: any) {
2620-
void vscode.window
2621-
.showErrorMessage(error.message, {
2622-
title: localize('debugging.documentation.button', 'Debugging documentation'),
2623-
isLearnMore: true
2624-
})
2625-
.then(item => {
2626-
if (item && item.isLearnMore) {
2627-
open('https://vector-of-bool.github.io/docs/vscode-cmake-tools/debugging.html');
2628-
}
2629-
});
2630-
return null;
2631-
}
2614+
const userConfig = this.workspaceContext.config.debugConfig;
2615+
if (userConfig?.type) {
2616+
// User specified a custom debug adapter type — skip auto-detection
2617+
// and build a minimal base config from the target. Properties from
2618+
// userConfig are merged on top, so any base property can be overridden.
2619+
debugConfig = {
2620+
type: userConfig.type,
2621+
name: `Debug ${testName}`,
2622+
request: 'launch',
2623+
program: testInfo.program,
2624+
cwd: path.dirname(testInfo.program),
2625+
args: [] as string[]
2626+
};
2627+
Object.assign(debugConfig, userConfig);
2628+
} else {
2629+
try {
2630+
const cache = await CMakeCache.fromPath(drv.cachePath);
2631+
debugConfig = await debuggerModule.getDebugConfigurationFromCache(cache, target, process.platform,
2632+
userConfig?.MIMode,
2633+
userConfig?.miDebuggerPath);
2634+
} catch (error: any) {
2635+
void vscode.window
2636+
.showErrorMessage(error.message, {
2637+
title: localize('debugging.documentation.button', 'Debugging documentation'),
2638+
isLearnMore: true
2639+
})
2640+
.then(item => {
2641+
if (item && item.isLearnMore) {
2642+
open('https://vector-of-bool.github.io/docs/vscode-cmake-tools/debugging.html');
2643+
}
2644+
});
2645+
return null;
2646+
}
26322647

2633-
if (debugConfig === null) {
2634-
log.error(localize('failed.to.generate.debugger.configuration', 'Failed to generate debugger configuration'));
2635-
void vscode.window.showErrorMessage(localize('unable.to.generate.debugging.configuration', 'Unable to generate a debugging configuration.'));
2636-
return null;
2648+
if (debugConfig === null) {
2649+
log.error(localize('failed.to.generate.debugger.configuration', 'Failed to generate debugger configuration'));
2650+
void vscode.window.showErrorMessage(localize('unable.to.generate.debugging.configuration', 'Unable to generate a debugging configuration.'));
2651+
return null;
2652+
}
2653+
2654+
// Add debug configuration from settings
2655+
Object.assign(debugConfig, userConfig);
26372656
}
26382657

26392658
// Add test arguments and working directory
@@ -2642,10 +2661,6 @@ export class CMakeProject {
26422661
debugConfig.cwd = testInfo.workingDirectory;
26432662
}
26442663

2645-
// Add debug configuration from settings
2646-
const userConfig = this.workspaceContext.config.debugConfig;
2647-
Object.assign(debugConfig, userConfig);
2648-
26492664
// Merge CTest ENVIRONMENT properties into the debug environment
26502665
const testEnvVars = util.makeDebuggerEnvironmentVars(testInfo.environment);
26512666
const combinedEnvVars = [...testEnvVars, ...(debugConfig.environment ?? [])];
@@ -3209,36 +3224,52 @@ export class CMakeProject {
32093224
}
32103225

32113226
let debugConfig;
3212-
try {
3213-
const cache = await CMakeCache.fromPath(drv.cachePath);
3214-
debugConfig = await debuggerModule.getDebugConfigurationFromCache(cache, targetExecutable, process.platform,
3215-
this.workspaceContext.config.debugConfig?.MIMode,
3216-
this.workspaceContext.config.debugConfig?.miDebuggerPath);
3217-
log.debug(localize('debug.configuration.from.cache', 'Debug configuration from cache: {0}', JSON.stringify(debugConfig)));
3218-
} catch (error: any) {
3219-
void vscode.window
3220-
.showErrorMessage(error.message, {
3221-
title: localize('debugging.documentation.button', 'Debugging documentation'),
3222-
isLearnMore: true
3223-
})
3224-
.then(item => {
3225-
if (item && item.isLearnMore) {
3226-
open('https://vector-of-bool.github.io/docs/vscode-cmake-tools/debugging.html');
3227-
}
3228-
});
3229-
log.debug(localize('problem.getting.debug', 'Problem getting debug configuration from cache.'), error);
3230-
return null;
3231-
}
3227+
const userConfig = this.workspaceContext.config.debugConfig;
3228+
if (userConfig?.type) {
3229+
// User specified a custom debug adapter type — skip auto-detection
3230+
// and build a minimal base config from the target. Properties from
3231+
// userConfig are merged on top, so any base property can be overridden.
3232+
debugConfig = {
3233+
type: userConfig.type,
3234+
name: `Debug ${targetExecutable.name}`,
3235+
request: 'launch',
3236+
program: targetExecutable.path,
3237+
cwd: targetExecutable.debuggerWorkingDirectory || path.dirname(targetExecutable.path),
3238+
args: [] as string[]
3239+
};
3240+
Object.assign(debugConfig, userConfig);
3241+
log.debug(localize('debug.configuration.from.settings', 'Debug configuration from user settings: {0}', JSON.stringify(debugConfig)));
3242+
} else {
3243+
try {
3244+
const cache = await CMakeCache.fromPath(drv.cachePath);
3245+
debugConfig = await debuggerModule.getDebugConfigurationFromCache(cache, targetExecutable, process.platform,
3246+
userConfig?.MIMode,
3247+
userConfig?.miDebuggerPath);
3248+
log.debug(localize('debug.configuration.from.cache', 'Debug configuration from cache: {0}', JSON.stringify(debugConfig)));
3249+
} catch (error: any) {
3250+
void vscode.window
3251+
.showErrorMessage(error.message, {
3252+
title: localize('debugging.documentation.button', 'Debugging documentation'),
3253+
isLearnMore: true
3254+
})
3255+
.then(item => {
3256+
if (item && item.isLearnMore) {
3257+
open('https://vector-of-bool.github.io/docs/vscode-cmake-tools/debugging.html');
3258+
}
3259+
});
3260+
log.debug(localize('problem.getting.debug', 'Problem getting debug configuration from cache.'), error);
3261+
return null;
3262+
}
32323263

3233-
if (debugConfig === null) {
3234-
log.error(localize('failed.to.generate.debugger.configuration', 'Failed to generate debugger configuration'));
3235-
void vscode.window.showErrorMessage(localize('unable.to.generate.debugging.configuration', 'Unable to generate a debugging configuration.'));
3236-
return null;
3237-
}
3264+
if (debugConfig === null) {
3265+
log.error(localize('failed.to.generate.debugger.configuration', 'Failed to generate debugger configuration'));
3266+
void vscode.window.showErrorMessage(localize('unable.to.generate.debugging.configuration', 'Unable to generate a debugging configuration.'));
3267+
return null;
3268+
}
32383269

3239-
// Add debug configuration from settings.
3240-
const userConfig = this.workspaceContext.config.debugConfig;
3241-
Object.assign(debugConfig, userConfig);
3270+
// Add debug configuration from settings.
3271+
Object.assign(debugConfig, userConfig);
3272+
}
32423273

32433274
const launchEnv = await this.getTargetLaunchEnvironment(drv, debugConfig.environment);
32443275
debugConfig.environment = util.makeDebuggerEnvironmentVars(launchEnv);

src/debug/debugger.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export interface VSCodeDebugConfiguration extends CppDebugConfiguration {
2929
* interface that maps to cmake.debugConfig.
3030
*/
3131
export interface CppDebugConfiguration {
32+
type?: string;
3233
symbolSearchPath?: string;
3334
additionalSOLibSearchPath?: string;
3435
externalConsole?: boolean;
@@ -46,6 +47,7 @@ export interface CppDebugConfiguration {
4647
launchCompleteCommand?: string;
4748
dumpPath?: string;
4849
coreDumpPath?: string;
50+
[key: string]: any;
4951
}
5052

5153
export interface DebuggerLogging {

0 commit comments

Comments
 (0)