Skip to content

Fix lldb-dap path on Darwin #1008

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export interface DebuggerConfiguration {
/** Are we using debug adapter provided with Toolchain */
readonly useDebugAdapterFromToolchain: boolean;
/** Return path to debug adapter */
readonly debugAdapterPath: string;
readonly customDebugAdapterPath: string;
}

/** workspace folder configuration */
Expand Down Expand Up @@ -149,7 +149,7 @@ const configuration = {
.getConfiguration("swift.debugger")
.get<boolean>("useDebugAdapterFromToolchain", false);
},
get debugAdapterPath(): string {
get customDebugAdapterPath(): string {
return vscode.workspace.getConfiguration("swift.debugger").get<string>("path", "");
},
};
Expand Down
31 changes: 22 additions & 9 deletions src/debugger/debugAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import contextKeys from "../contextKeys";
import { fileExists } from "../utilities/filesystem";
import { Version } from "../utilities/version";
import { WorkspaceContext } from "../WorkspaceContext";
import { SwiftToolchain } from "../toolchain/toolchain";

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

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

/** Return the path to the debug adapter */
public static async debugAdapterPath(toolchain: SwiftToolchain): Promise<string> {
const customDebugAdapterPath = configuration.debugger.customDebugAdapterPath;
if (customDebugAdapterPath.length > 0) {
return customDebugAdapterPath;
}

const debugAdapter = this.getDebugAdapter(toolchain.swiftVersion);
if (process.platform === "darwin" && debugAdapter === "lldb-dap") {
return await toolchain.getLLDBDebugAdapter();
} else {
return toolchain.getToolchainExecutable(debugAdapter);
}
}

/**
* Verify that the toolchain debug adapter exists
* @param workspace WorkspaceContext
Expand All @@ -47,18 +63,15 @@ export class DebugAdapter {
workspace: WorkspaceContext,
quiet = false
): Promise<boolean> {
const useCustom = configuration.debugger.debugAdapterPath.length > 0;
const debugAdapter = DebugAdapter.getDebugAdapter(workspace.toolchain.swiftVersion);
const lldbDebugAdapterPath = useCustom
? configuration.debugger.debugAdapterPath
: workspace.toolchain.getToolchainExecutable(debugAdapter);
const lldbDebugAdapterPath = await this.debugAdapterPath(workspace.toolchain);

if (!(await fileExists(lldbDebugAdapterPath))) {
if (!quiet) {
const debugAdapterName = this.getDebugAdapter(workspace.toolchain.swiftVersion);
vscode.window.showErrorMessage(
useCustom
? `Cannot find ${debugAdapter} debug adapter specified in setting Swift.Debugger.Path.`
: `Cannot find ${debugAdapter} debug adapter in your Swift toolchain.`
configuration.debugger.customDebugAdapterPath.length > 0
? `Cannot find ${debugAdapterName} debug adapter specified in setting Swift.Debugger.Path.`
: `Cannot find ${debugAdapterName} debug adapter in your Swift toolchain.`
);
}
workspace.outputChannel.log(`Failed to find ${lldbDebugAdapterPath}`);
Expand Down
24 changes: 8 additions & 16 deletions src/debugger/debugAdapterFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

import * as vscode from "vscode";
import { WorkspaceContext } from "../WorkspaceContext";
import configuration from "../configuration";
import { DebugAdapter } from "./debugAdapter";

export function registerLLDBDebugAdapter(workspaceContext: WorkspaceContext): vscode.Disposable {
Expand All @@ -23,23 +22,16 @@ export function registerLLDBDebugAdapter(workspaceContext: WorkspaceContext): vs
_session: vscode.DebugSession,
executable: vscode.DebugAdapterExecutable | undefined
): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
// use the executable specified in the settings or use version in toolchain
const debugAdapter = DebugAdapter.getDebugAdapter(
workspaceContext.toolchain.swiftVersion
);
if (!executable) {
const lldbDebugAdapterPath =
configuration.debugger.debugAdapterPath.length > 0
? configuration.debugger.debugAdapterPath
: workspaceContext.toolchain.getToolchainExecutable(debugAdapter);
DebugAdapter.verifyDebugAdapterExists(workspaceContext).then(() => {
/** Ignore */
});
executable = new vscode.DebugAdapterExecutable(lldbDebugAdapterPath, [], {});
if (executable) {
// make VS Code launch the debug adapter executable
return executable;
}

// make VS Code launch the debug adapter executable
return executable;
return DebugAdapter.debugAdapterPath(workspaceContext.toolchain)
.then(path =>
DebugAdapter.verifyDebugAdapterExists(workspaceContext).then(() => path)
)
.then(path => new vscode.DebugAdapterExecutable(path, [], {}));
}
}

Expand Down
63 changes: 46 additions & 17 deletions src/toolchain/toolchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,28 +354,57 @@ export class SwiftToolchain {
}

/**
* Cannot use `getToolchainExecutable` to get the LLDB executable as LLDB
* is not in macOS toolchain path
* Returns the path to the LLDB executable inside the selected toolchain.
* If the user is on macOS and has no OSS toolchain selected, also search
* inside Xcode.
* @returns The path to the `lldb` executable
* @throws Throws an error if the executable cannot be found
*/
public async getLLDB(): Promise<string> {
let lldbPath = path.join(
return this.findToolchainOrXcodeExecutable("lldb");
}

/**
* Returns the path to the LLDB debug adapter executable inside the selected
* toolchain. If the user is on macOS and has no OSS toolchain selected, also
* search inside Xcode.
* @returns The path to the `lldb-dap` executable
* @throws Throws an error if the executable cannot be found
*/
public async getLLDBDebugAdapter(): Promise<string> {
return this.findToolchainOrXcodeExecutable("lldb-dap");
}

/**
* Search for the supplied executable in the toolchain.
* If the user is on macOS and has no OSS toolchain selected, also
* search inside Xcode.
*/
private async findToolchainOrXcodeExecutable(executable: string): Promise<string> {
const toolchainExecutablePath = path.join(
this.swiftFolderPath,
process.platform === "win32" ? "lldb.exe" : "lldb"
process.platform === "win32" ? `${executable}.exe` : executable
);
if (!(await pathExists(lldbPath))) {
if (process.platform !== "darwin") {
throw new Error("Failed to find LLDB in swift toolchain");
}
const xcodeDirectory = SwiftToolchain.getXcodeDirectory(this.swiftFolderPath);
if (!xcodeDirectory) {
throw new Error("Failed to find LLDB in swift toolchain");
}
const { stdout } = await execFile("xcrun", ["-find", "lldb"], {
env: { ...process.env, DEVELOPER_DIR: xcodeDirectory },
});
lldbPath = stdout.trimEnd();

if (await pathExists(toolchainExecutablePath)) {
return toolchainExecutablePath;
}
return lldbPath;

if (process.platform !== "darwin") {
throw new Error(`Failed to find ${executable} in swift toolchain`);
}
return this.findXcodeExecutable(executable);
}

private async findXcodeExecutable(executable: string): Promise<string> {
const xcodeDirectory = SwiftToolchain.getXcodeDirectory(this.toolchainPath);
if (!xcodeDirectory) {
throw new Error(`Failed to find ${executable} in Swift toolchain`);
}
const { stdout } = await execFile("xcrun", ["-find", executable], {
env: { ...process.env, DEVELOPER_DIR: xcodeDirectory },
});
return stdout.trimEnd();
}

private basePlatformDeveloperPath(): string | undefined {
Expand Down