Skip to content

Commit dfaa7e2

Browse files
Merge branch 'topic/gdb_target' into 'master'
Prepend target to GDB for non-native projects See merge request eng/ide/ada_language_server!1902
2 parents 68fc8d7 + b3912fa commit dfaa7e2

File tree

4 files changed

+99
-73
lines changed

4 files changed

+99
-73
lines changed

integration/vscode/ada/src/ExtensionState.ts

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ import { AdaCodeLensProvider } from './AdaCodeLensProvider';
99
import { createClient } from './clients';
1010
import { AdaInitialDebugConfigProvider, initializeDebugging } from './debugConfigProvider';
1111
import { logger } from './extension';
12+
import { existsSync } from 'fs';
13+
import path from 'path';
1214
import { GnatTaskProvider } from './gnatTaskProvider';
1315
import { initializeTesting } from './gnattest';
1416
import { GprTaskProvider } from './gprTaskProvider';
15-
import { getArgValue, TERMINAL_ENV_SETTING_NAME } from './helpers';
17+
import { getArgValue, TERMINAL_ENV_SETTING_NAME, exe, getEvaluatedTerminalEnv } from './helpers';
1618
import {
1719
SimpleTaskDef,
1820
SimpleTaskProvider,
@@ -54,19 +56,23 @@ export class ExtensionState {
5456
*/
5557
cachedProjectUri: vscode.Uri | undefined;
5658
cachedObjectDir: string | undefined;
59+
cachedTargetPrefix: string | undefined;
5760
cachedMains: string[] | undefined;
5861
cachedExecutables: string[] | undefined;
5962
cachedAlireTomls: vscode.Uri[] | undefined;
63+
cachedGdb: string | undefined | null = undefined;
6064

6165
private adaTaskProvider?: SimpleTaskProvider;
6266
private sparkTaskProvider?: SimpleTaskProvider;
6367

6468
private clearALSCache() {
6569
this.cachedProjectUri = undefined;
6670
this.cachedObjectDir = undefined;
71+
this.cachedTargetPrefix = undefined;
6772
this.cachedMains = undefined;
6873
this.cachedExecutables = undefined;
6974
this.cachedAlireTomls = undefined;
75+
this.cachedGdb = undefined;
7076
}
7177

7278
constructor(context: vscode.ExtensionContext) {
@@ -237,6 +243,58 @@ export class ExtensionState {
237243
return attrValue;
238244
}
239245

246+
/**
247+
*
248+
* @returns the full path to the `gdb` executable, taking into consideration the
249+
* `PATH` variable in the `terminal.integrated.env.*` setting if set. Otherwise,
250+
* the `PATH` variable of the current process environment is considered. When
251+
* a non-native target is specified, it will be prepeneded to the `gdb` executable
252+
* before looking in the `PATH` (e.g: `arm-eabi-gdb` for `arm-eabi` target).
253+
*
254+
* The current process environment is unlikely to change during the lifetime of
255+
* the extension, and we already prompt the User to reload the window in case
256+
* the `terminal.integrated.env.*` variables change. For this reason, we compute
257+
* the value only on the first call, and cache it for subsequent calls to return
258+
* it efficiently.
259+
*
260+
* @param target - The target for which gdb should be looked for.
261+
*/
262+
public getOrFindGdb(target: string = ''): string | undefined {
263+
if (this.cachedGdb === undefined) {
264+
/**
265+
* If undefined yet, try to compute it.
266+
*/
267+
const env = getEvaluatedTerminalEnv();
268+
let pathVal: string;
269+
if (env && 'PATH' in env) {
270+
pathVal = env.PATH ?? '';
271+
} else if ('PATH' in process.env) {
272+
pathVal = process.env.PATH ?? '';
273+
} else {
274+
pathVal = '';
275+
}
276+
277+
const gdbExeBasename = target != '' ? `${target}-gdb${exe}` : `gdb${exe}`;
278+
const gdb = pathVal
279+
.split(path.delimiter)
280+
.map<string>((v) => path.join(v, gdbExeBasename))
281+
.find(existsSync);
282+
283+
if (gdb) {
284+
// Found
285+
this.cachedGdb = gdb;
286+
return this.cachedGdb;
287+
} else {
288+
// Not found. Assign null to cache to avoid recomputing at every call.
289+
this.cachedGdb = null;
290+
}
291+
}
292+
293+
// When returning, coerce null to undefined because the distinction doesn't
294+
// matter on the caller side.
295+
return this.cachedGdb ?? undefined;
296+
}
297+
240298
/**
241299
* @returns the URI of the main project file from the ALS
242300
*/
@@ -253,6 +311,31 @@ export class ExtensionState {
253311
return this.cachedProjectUri;
254312
}
255313

314+
/**
315+
* Returns the target prefix that should be used when spawning tools
316+
* like gnat, gcc or gdb.
317+
* For instance if the project has an 'arm-eabi' target, this
318+
* function will return 'arm-eabi'. For native projects, this
319+
* will return an empty string.
320+
*
321+
* @returns the target prefix
322+
*/
323+
public async getTargetPrefix(): Promise<string> {
324+
if (!this.cachedTargetPrefix) {
325+
// Get the compiler driver's path from the Compiler.Driver project
326+
// attribute, and delete the last bit to get the prefix
327+
const driverPath = (await this.getProjectAttributeValue(
328+
'driver',
329+
'compiler',
330+
'ada',
331+
)) as string;
332+
const driver = path.basename(driverPath);
333+
this.cachedTargetPrefix = driver.substring(0, driver.lastIndexOf('-'));
334+
}
335+
336+
return this.cachedTargetPrefix;
337+
}
338+
256339
/**
257340
* @returns the full path of the main project file from the ALS
258341
*/

integration/vscode/ada/src/commands.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ async function buildAndDebugSpecifiedMain(main: vscode.Uri): Promise<void> {
593593

594594
const wsFolder = vscode.workspace.getWorkspaceFolder(main);
595595
const adaMain = await findAdaMain(main.fsPath);
596+
const target = await adaExtState.getTargetPrefix();
596597
if (adaMain) {
597598
/**
598599
* The vscode API doesn't provide a way to list both automatically
@@ -602,7 +603,7 @@ async function buildAndDebugSpecifiedMain(main: vscode.Uri): Promise<void> {
602603
* the given main URI.
603604
*/
604605
// Create a launch config for this main to help with matching
605-
const configToMatch = initializeConfig(adaMain);
606+
const configToMatch = initializeConfig(adaMain, target);
606607
logger.debug('Debug config to match:\n' + JSON.stringify(configToMatch, null, 2));
607608

608609
let matchingConfig = undefined;

integration/vscode/ada/src/debugConfigProvider.ts

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,7 @@
11
import assert from 'assert';
2-
import { existsSync } from 'fs';
3-
import path from 'path';
42
import * as vscode from 'vscode';
53
import { adaExtState } from './extension';
6-
import {
7-
AdaMain,
8-
exe,
9-
getAdaMains,
10-
getEvaluatedTerminalEnv,
11-
getProjectFile,
12-
getProjectFileRelPath,
13-
} from './helpers';
4+
import { AdaMain, getAdaMains, getProjectFile, getProjectFileRelPath } from './helpers';
145
import { BUILD_PROJECT_TASK_NAME, getBuildTaskName } from './taskProviders';
156

167
export const ADA_DEBUG_BACKEND_TYPE = 'cppdbg';
@@ -40,8 +31,9 @@ export const adaDynamicDebugConfigProvider = {
4031
_folder?: vscode.WorkspaceFolder,
4132
): Promise<AdaConfig[]> {
4233
const mains = await getAdaMains();
34+
const target = await adaExtState.getTargetPrefix();
4335
const configs: AdaConfig[] = mains.flatMap((m) => {
44-
return [initializeConfig(m), createAttachConfig(m)];
36+
return [initializeConfig(m, target), createAttachConfig(m, target)];
4537
});
4638
if (configs.length == 0) {
4739
/**
@@ -112,55 +104,6 @@ export function initializeDebugging(ctx: vscode.ExtensionContext): {
112104
return { providerInitial: providerInitial, providerDynamic: adaDynamicDebugConfigProvider };
113105
}
114106

115-
let cachedGdb: string | undefined | null = undefined;
116-
117-
/**
118-
*
119-
* @returns the full path to the `gdb` executable, taking into consideration the
120-
* `PATH` variable in the `terminal.integrated.env.*` setting if set. Otherwise,
121-
* the `PATH` variable of the current process environment is considered.
122-
*
123-
* The current process environment is unlikely to change during the lifetime of
124-
* the extension, and we already prompt the User to reload the window in case
125-
* the `terminal.integrated.env.*` variables change. For this reason, we compute
126-
* the value only on the first call, and cache it for subsequent calls to return
127-
* it efficiently.
128-
*/
129-
export function getOrFindGdb(): string | undefined {
130-
if (cachedGdb == undefined) {
131-
/**
132-
* If undefined yet, try to compute it.
133-
*/
134-
const env = getEvaluatedTerminalEnv();
135-
let pathVal: string;
136-
if (env && 'PATH' in env) {
137-
pathVal = env.PATH ?? '';
138-
} else if ('PATH' in process.env) {
139-
pathVal = process.env.PATH ?? '';
140-
} else {
141-
pathVal = '';
142-
}
143-
144-
const gdb = pathVal
145-
.split(path.delimiter)
146-
.map<string>((v) => path.join(v, 'gdb' + exe))
147-
.find(existsSync);
148-
149-
if (gdb) {
150-
// Found
151-
cachedGdb = gdb;
152-
return cachedGdb;
153-
} else {
154-
// Not found. Assign null to cache to avoid recomputing at every call.
155-
cachedGdb = null;
156-
}
157-
}
158-
159-
// When returning, coerce null to undefined because the distinction doesn't
160-
// matter on the caller side.
161-
return cachedGdb ?? undefined;
162-
}
163-
164107
/**
165108
* Initialize a debug configuration based on 'cppdbg' for the given executable
166109
* if specified. Otherwise the program field includes
@@ -175,7 +118,7 @@ export function getOrFindGdb(): string | undefined {
175118
* 'program' parameter.
176119
* @returns an AdaConfig
177120
*/
178-
export function initializeConfig(main: AdaMain, name?: string): AdaConfig {
121+
export function initializeConfig(main: AdaMain, target: string, name?: string): AdaConfig {
179122
// TODO it would be nice if this and the package.json configuration snippet
180123
// were the same.
181124
const config: AdaConfig = {
@@ -192,7 +135,7 @@ export function initializeConfig(main: AdaMain, name?: string): AdaConfig {
192135
MIMode: 'gdb',
193136
preLaunchTask: main ? getBuildTaskName(main) : BUILD_PROJECT_TASK_NAME,
194137
setupCommands: setupCmd,
195-
miDebuggerPath: getOrFindGdb(),
138+
miDebuggerPath: adaExtState.getOrFindGdb(target),
196139
};
197140

198141
return config;
@@ -283,9 +226,9 @@ export class AdaInitialDebugConfigProvider implements vscode.DebugConfigurationP
283226
return debugConfiguration;
284227
} else {
285228
const main = await getOrAskForProgram();
286-
229+
const target = await adaExtState.getTargetPrefix();
287230
if (main) {
288-
return initializeConfig(main);
231+
return initializeConfig(main, target);
289232
}
290233
}
291234

@@ -449,7 +392,7 @@ async function getAdaMainForSourceFile(
449392
return mains.find((val) => srcPath == val.mainFullPath);
450393
}
451394

452-
function createAttachConfig(adaMain: AdaMain): AdaConfig {
395+
function createAttachConfig(adaMain: AdaMain, target: string): AdaConfig {
453396
return {
454397
name: `Ada: Attach debugger to running process - ${adaMain.mainRelPath()}`,
455398
type: ADA_DEBUG_BACKEND_TYPE,
@@ -463,7 +406,7 @@ function createAttachConfig(adaMain: AdaMain): AdaConfig {
463406
* to trigger an unwanted rebuild, so we don't set a preLaunchTask.
464407
*/
465408
// preLaunchTask: adaMain ? getBuildTaskName(adaMain) : BUILD_PROJECT_TASK_NAME,
466-
miDebuggerPath: getOrFindGdb(),
409+
miDebuggerPath: adaExtState.getOrFindGdb(target),
467410
setupCommands: setupCmd,
468411
};
469412
}

integration/vscode/ada/test/general/debug.test.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
AdaConfig,
44
adaDynamicDebugConfigProvider,
55
createQuickPicksInitialLaunch,
6-
getOrFindGdb,
76
} from '../../src/debugConfigProvider';
87
import { exe } from '../../src/helpers';
98
import { activate } from '../utils';
@@ -38,7 +37,7 @@ suite('Dbg Cfgs', function () {
3837
text: 'set multiple-symbols cancel',
3938
},
4039
],
41-
miDebuggerPath: getOrFindGdb() ?? '<undefined>',
40+
miDebuggerPath: adaExtState.getOrFindGdb() ?? '<undefined>',
4241
},
4342
{
4443
name: 'Ada: Attach debugger to running process - src/main1.adb',
@@ -59,7 +58,7 @@ suite('Dbg Cfgs', function () {
5958
text: 'set multiple-symbols cancel',
6059
},
6160
],
62-
miDebuggerPath: getOrFindGdb() ?? '<undefined>',
61+
miDebuggerPath: adaExtState.getOrFindGdb() ?? '<undefined>',
6362
},
6463
{
6564
type: 'cppdbg',
@@ -84,7 +83,7 @@ suite('Dbg Cfgs', function () {
8483
text: 'set multiple-symbols cancel',
8584
},
8685
],
87-
miDebuggerPath: getOrFindGdb() ?? '<undefined>',
86+
miDebuggerPath: adaExtState.getOrFindGdb() ?? '<undefined>',
8887
},
8988
{
9089
name: 'Ada: Attach debugger to running process - src/test.adb',
@@ -105,7 +104,7 @@ suite('Dbg Cfgs', function () {
105104
text: 'set multiple-symbols cancel',
106105
},
107106
],
108-
miDebuggerPath: getOrFindGdb() ?? '<undefined>',
107+
miDebuggerPath: adaExtState.getOrFindGdb() ?? '<undefined>',
109108
},
110109
];
111110
});

0 commit comments

Comments
 (0)