Skip to content

Commit 102ba05

Browse files
Always use xcrun as a fallback for finding binaries on macOS (#1998)
1 parent 649e1c0 commit 102ba05

File tree

4 files changed

+67
-30
lines changed

4 files changed

+67
-30
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
- When editing .sourcekit-lsp/config.json use the JSON schema from the toolchain ([#1979](https://github.com/swiftlang/vscode-swift/pull/1979))
88

9+
### Fixed
10+
11+
- Fix extension failing to find `lldb-dap` when `swift.path` points at an Xcode toolchain ([#1998](https://github.com/swiftlang/vscode-swift/pull/1998))
12+
913
## 2.14.2 - 2025-12-07
1014

1115
### Fixed

src/toolchain/toolchain.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -436,25 +436,25 @@ export class SwiftToolchain {
436436
* Search for the supplied executable in the toolchain.
437437
*/
438438
private async findToolchainExecutable(executable: string): Promise<string> {
439-
if (process.platform === "win32") {
440-
executable += ".exe";
441-
}
442-
// First search the toolchain's 'bin' directory
443-
const toolchainExecutablePath = path.join(this.toolchainPath, "bin", executable);
444-
if (await pathExists(toolchainExecutablePath)) {
445-
return toolchainExecutablePath;
446-
}
447-
// Fallback to xcrun if the active toolchain comes from Xcode/CommandLineTools
448-
if (
449-
this.manager === "xcrun" ||
450-
(this.manager === "swiftly" && (await Swiftly.inUseVersion()) === "xcode")
451-
) {
452-
const { stdout } = await execFile("xcrun", ["--find", executable]);
453-
return stdout.trim();
454-
}
455-
throw new Error(
456-
`Failed to find ${executable} within Swift toolchain '${this.toolchainPath}'`
457-
);
439+
let cause: unknown = undefined;
440+
try {
441+
if (process.platform === "win32") {
442+
executable += ".exe";
443+
}
444+
// First search the toolchain's 'bin' directory
445+
const toolchainExecutablePath = path.join(this.toolchainPath, "bin", executable);
446+
if (await pathExists(toolchainExecutablePath)) {
447+
return toolchainExecutablePath;
448+
}
449+
// Fallback to using xcrun if we're on macOS
450+
if (process.platform === "darwin") {
451+
const { stdout } = await execFile("xcrun", ["--find", executable]);
452+
return stdout.trim();
453+
}
454+
} catch (error) {
455+
cause = error;
456+
}
457+
throw new Error(`Failed to find ${executable} within Swift toolchain`, { cause });
458458
}
459459

460460
private basePlatformDeveloperPath(): string | undefined {

src/utilities/utilities.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,14 @@ export async function execFile(
153153
options.env = { ...(options.env ?? process.env), ...runtimeEnv };
154154
}
155155
}
156+
if (Object.keys(configuration.swiftEnvironmentVariables).length > 0) {
157+
// when adding environment vars we either combine with vars passed
158+
// into the function or the process environment vars
159+
options.env = {
160+
...(options.env ?? process.env),
161+
...configuration.swiftEnvironmentVariables,
162+
};
163+
}
156164
options = {
157165
...options,
158166
maxBuffer: options.maxBuffer ?? 1024 * 1024 * 64, // 64MB
@@ -261,14 +269,6 @@ export async function execSwift(
261269
swift = toolchain.getToolchainExecutable("swift");
262270
args = toolchain.buildFlags.withAdditionalFlags(args);
263271
}
264-
if (Object.keys(configuration.swiftEnvironmentVariables).length > 0) {
265-
// when adding environment vars we either combine with vars passed
266-
// into the function or the process environment vars
267-
options.env = {
268-
...(options.env ?? process.env),
269-
...configuration.swiftEnvironmentVariables,
270-
};
271-
}
272272
options = {
273273
...options,
274274
maxBuffer: options.maxBuffer ?? 1024 * 1024 * 64, // 64MB

test/unit-tests/toolchain/toolchain.test.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ suite("SwiftToolchain Unit Test Suite", () => {
9999
});
100100

101101
await expect(sut.getLLDBDebugAdapter()).to.eventually.be.rejectedWith(
102-
"Failed to find lldb-dap within Swift toolchain '/Library/Developer/Toolchains/swift-6.0.1-RELEASE.xctoolchain/usr'"
102+
"Failed to find lldb-dap within Swift toolchain"
103103
);
104104
});
105105

@@ -153,6 +153,39 @@ suite("SwiftToolchain Unit Test Suite", () => {
153153
"/Library/Developer/CommandLineTools/usr/bin/lldb-dap"
154154
);
155155
});
156+
157+
test("returns the path to lldb-dap if it exists within an Xcode toolchain selected using swift.path", async () => {
158+
mockFS({
159+
"/Applications/Xcode.app/Contents/Developer": {
160+
Toolchains: {
161+
"XcodeDefault.xctoolchain": {},
162+
},
163+
usr: {
164+
bin: {
165+
"lldb-dap": mockFS.file({
166+
content: "",
167+
mode: 0o770,
168+
}),
169+
},
170+
},
171+
},
172+
});
173+
mockedUtilities.execFile.withArgs("xcrun", ["--find", "lldb-dap"]).resolves({
174+
stdout: "/Applications/Xcode.app/Contents/Developer/usr/bin/lldb-dap",
175+
stderr: "",
176+
});
177+
const sut = createSwiftToolchain({
178+
manager: "unknown",
179+
swiftFolderPath:
180+
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr",
181+
toolchainPath:
182+
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr",
183+
});
184+
185+
await expect(sut.getLLDBDebugAdapter()).to.eventually.equalPath(
186+
"/Applications/Xcode.app/Contents/Developer/usr/bin/lldb-dap"
187+
);
188+
});
156189
});
157190

158191
suite("Linux", () => {
@@ -189,7 +222,7 @@ suite("SwiftToolchain Unit Test Suite", () => {
189222
});
190223

191224
await expect(sut.getLLDBDebugAdapter()).to.eventually.be.rejectedWith(
192-
"Failed to find lldb-dap within Swift toolchain '/toolchains/swift-6.0.0/usr'"
225+
"Failed to find lldb-dap within Swift toolchain"
193226
);
194227
});
195228
});
@@ -228,7 +261,7 @@ suite("SwiftToolchain Unit Test Suite", () => {
228261
});
229262

230263
await expect(sut.getLLDBDebugAdapter()).to.eventually.be.rejectedWith(
231-
"Failed to find lldb-dap.exe within Swift toolchain '/toolchains/swift-6.0.0/usr'"
264+
"Failed to find lldb-dap.exe within Swift toolchain"
232265
);
233266
});
234267
});

0 commit comments

Comments
 (0)