Skip to content

Commit e0a0fba

Browse files
authored
Fix lldb-dap path on Darwin (#1008)
* Fix lldb-dap path on Darwin The `lldb-dap` binary is not in the toolchain directory on Darwin like it is on Linux and Windows. Use `xcrun -find lldb-dap` on Darwin to find the correct `lldb-dap` location.
1 parent 4488c31 commit e0a0fba

File tree

4 files changed

+78
-44
lines changed

4 files changed

+78
-44
lines changed

Diff for: src/configuration.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export interface DebuggerConfiguration {
5050
/** Are we using debug adapter provided with Toolchain */
5151
readonly useDebugAdapterFromToolchain: boolean;
5252
/** Return path to debug adapter */
53-
readonly debugAdapterPath: string;
53+
readonly customDebugAdapterPath: string;
5454
}
5555

5656
/** workspace folder configuration */
@@ -149,7 +149,7 @@ const configuration = {
149149
.getConfiguration("swift.debugger")
150150
.get<boolean>("useDebugAdapterFromToolchain", false);
151151
},
152-
get debugAdapterPath(): string {
152+
get customDebugAdapterPath(): string {
153153
return vscode.workspace.getConfiguration("swift.debugger").get<string>("path", "");
154154
},
155155
};

Diff for: src/debugger/debugAdapter.ts

+22-9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import contextKeys from "../contextKeys";
1818
import { fileExists } from "../utilities/filesystem";
1919
import { Version } from "../utilities/version";
2020
import { WorkspaceContext } from "../WorkspaceContext";
21+
import { SwiftToolchain } from "../toolchain/toolchain";
2122

2223
/**
2324
* Class managing which debug adapter we are using. Will only setup lldb-vscode/lldb-dap if it is available.
@@ -33,10 +34,25 @@ export class DebugAdapter {
3334
}
3435

3536
/** Return debug adapter for toolchain */
36-
public static getDebugAdapter(swiftVersion: Version): string {
37+
public static getDebugAdapter(swiftVersion: Version): "lldb-vscode" | "lldb-dap" {
3738
return swiftVersion.isLessThan(new Version(6, 0, 0)) ? "lldb-vscode" : "lldb-dap";
3839
}
3940

41+
/** Return the path to the debug adapter */
42+
public static async debugAdapterPath(toolchain: SwiftToolchain): Promise<string> {
43+
const customDebugAdapterPath = configuration.debugger.customDebugAdapterPath;
44+
if (customDebugAdapterPath.length > 0) {
45+
return customDebugAdapterPath;
46+
}
47+
48+
const debugAdapter = this.getDebugAdapter(toolchain.swiftVersion);
49+
if (process.platform === "darwin" && debugAdapter === "lldb-dap") {
50+
return await toolchain.getLLDBDebugAdapter();
51+
} else {
52+
return toolchain.getToolchainExecutable(debugAdapter);
53+
}
54+
}
55+
4056
/**
4157
* Verify that the toolchain debug adapter exists
4258
* @param workspace WorkspaceContext
@@ -47,18 +63,15 @@ export class DebugAdapter {
4763
workspace: WorkspaceContext,
4864
quiet = false
4965
): Promise<boolean> {
50-
const useCustom = configuration.debugger.debugAdapterPath.length > 0;
51-
const debugAdapter = DebugAdapter.getDebugAdapter(workspace.toolchain.swiftVersion);
52-
const lldbDebugAdapterPath = useCustom
53-
? configuration.debugger.debugAdapterPath
54-
: workspace.toolchain.getToolchainExecutable(debugAdapter);
66+
const lldbDebugAdapterPath = await this.debugAdapterPath(workspace.toolchain);
5567

5668
if (!(await fileExists(lldbDebugAdapterPath))) {
5769
if (!quiet) {
70+
const debugAdapterName = this.getDebugAdapter(workspace.toolchain.swiftVersion);
5871
vscode.window.showErrorMessage(
59-
useCustom
60-
? `Cannot find ${debugAdapter} debug adapter specified in setting Swift.Debugger.Path.`
61-
: `Cannot find ${debugAdapter} debug adapter in your Swift toolchain.`
72+
configuration.debugger.customDebugAdapterPath.length > 0
73+
? `Cannot find ${debugAdapterName} debug adapter specified in setting Swift.Debugger.Path.`
74+
: `Cannot find ${debugAdapterName} debug adapter in your Swift toolchain.`
6275
);
6376
}
6477
workspace.outputChannel.log(`Failed to find ${lldbDebugAdapterPath}`);

Diff for: src/debugger/debugAdapterFactory.ts

+8-16
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
import * as vscode from "vscode";
1616
import { WorkspaceContext } from "../WorkspaceContext";
17-
import configuration from "../configuration";
1817
import { DebugAdapter } from "./debugAdapter";
1918

2019
export function registerLLDBDebugAdapter(workspaceContext: WorkspaceContext): vscode.Disposable {
@@ -23,23 +22,16 @@ export function registerLLDBDebugAdapter(workspaceContext: WorkspaceContext): vs
2322
_session: vscode.DebugSession,
2423
executable: vscode.DebugAdapterExecutable | undefined
2524
): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
26-
// use the executable specified in the settings or use version in toolchain
27-
const debugAdapter = DebugAdapter.getDebugAdapter(
28-
workspaceContext.toolchain.swiftVersion
29-
);
30-
if (!executable) {
31-
const lldbDebugAdapterPath =
32-
configuration.debugger.debugAdapterPath.length > 0
33-
? configuration.debugger.debugAdapterPath
34-
: workspaceContext.toolchain.getToolchainExecutable(debugAdapter);
35-
DebugAdapter.verifyDebugAdapterExists(workspaceContext).then(() => {
36-
/** Ignore */
37-
});
38-
executable = new vscode.DebugAdapterExecutable(lldbDebugAdapterPath, [], {});
25+
if (executable) {
26+
// make VS Code launch the debug adapter executable
27+
return executable;
3928
}
4029

41-
// make VS Code launch the debug adapter executable
42-
return executable;
30+
return DebugAdapter.debugAdapterPath(workspaceContext.toolchain)
31+
.then(path =>
32+
DebugAdapter.verifyDebugAdapterExists(workspaceContext).then(() => path)
33+
)
34+
.then(path => new vscode.DebugAdapterExecutable(path, [], {}));
4335
}
4436
}
4537

Diff for: src/toolchain/toolchain.ts

+46-17
Original file line numberDiff line numberDiff line change
@@ -354,28 +354,57 @@ export class SwiftToolchain {
354354
}
355355

356356
/**
357-
* Cannot use `getToolchainExecutable` to get the LLDB executable as LLDB
358-
* is not in macOS toolchain path
357+
* Returns the path to the LLDB executable inside the selected toolchain.
358+
* If the user is on macOS and has no OSS toolchain selected, also search
359+
* inside Xcode.
360+
* @returns The path to the `lldb` executable
361+
* @throws Throws an error if the executable cannot be found
359362
*/
360363
public async getLLDB(): Promise<string> {
361-
let lldbPath = path.join(
364+
return this.findToolchainOrXcodeExecutable("lldb");
365+
}
366+
367+
/**
368+
* Returns the path to the LLDB debug adapter executable inside the selected
369+
* toolchain. If the user is on macOS and has no OSS toolchain selected, also
370+
* search inside Xcode.
371+
* @returns The path to the `lldb-dap` executable
372+
* @throws Throws an error if the executable cannot be found
373+
*/
374+
public async getLLDBDebugAdapter(): Promise<string> {
375+
return this.findToolchainOrXcodeExecutable("lldb-dap");
376+
}
377+
378+
/**
379+
* Search for the supplied executable in the toolchain.
380+
* If the user is on macOS and has no OSS toolchain selected, also
381+
* search inside Xcode.
382+
*/
383+
private async findToolchainOrXcodeExecutable(executable: string): Promise<string> {
384+
const toolchainExecutablePath = path.join(
362385
this.swiftFolderPath,
363-
process.platform === "win32" ? "lldb.exe" : "lldb"
386+
process.platform === "win32" ? `${executable}.exe` : executable
364387
);
365-
if (!(await pathExists(lldbPath))) {
366-
if (process.platform !== "darwin") {
367-
throw new Error("Failed to find LLDB in swift toolchain");
368-
}
369-
const xcodeDirectory = SwiftToolchain.getXcodeDirectory(this.swiftFolderPath);
370-
if (!xcodeDirectory) {
371-
throw new Error("Failed to find LLDB in swift toolchain");
372-
}
373-
const { stdout } = await execFile("xcrun", ["-find", "lldb"], {
374-
env: { ...process.env, DEVELOPER_DIR: xcodeDirectory },
375-
});
376-
lldbPath = stdout.trimEnd();
388+
389+
if (await pathExists(toolchainExecutablePath)) {
390+
return toolchainExecutablePath;
377391
}
378-
return lldbPath;
392+
393+
if (process.platform !== "darwin") {
394+
throw new Error(`Failed to find ${executable} in swift toolchain`);
395+
}
396+
return this.findXcodeExecutable(executable);
397+
}
398+
399+
private async findXcodeExecutable(executable: string): Promise<string> {
400+
const xcodeDirectory = SwiftToolchain.getXcodeDirectory(this.toolchainPath);
401+
if (!xcodeDirectory) {
402+
throw new Error(`Failed to find ${executable} in Swift toolchain`);
403+
}
404+
const { stdout } = await execFile("xcrun", ["-find", executable], {
405+
env: { ...process.env, DEVELOPER_DIR: xcodeDirectory },
406+
});
407+
return stdout.trimEnd();
379408
}
380409

381410
private basePlatformDeveloperPath(): string | undefined {

0 commit comments

Comments
 (0)