Skip to content

Commit a021f1b

Browse files
committed
[core] Teach ToolchainRegistry to search install path
When the ToolchainRegistry is used in code embedded into a toolchain, we want to prefer that toolchain over any other search paths other than the explicit SOURCEKIT_TOOLCHAIN_PATH environment.
1 parent 0e03291 commit a021f1b

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed

Sources/SKCore/ToolchainRegistry.swift

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ extension ToolchainRegistry {
6868
///
6969
/// If called with the default values, creates a toolchain registry that searches:
7070
/// * env SOURCEKIT_TOOLCHAIN_PATH <-- will override default toolchain
71+
/// * installPath <-- will override default toolchain
7172
/// * (Darwin) The currently selected Xcode
7273
/// * (Darwin) [~]/Library/Developer/Toolchains
7374
/// * env SOURCEKIT_PATH, PATH
@@ -77,9 +78,9 @@ extension ToolchainRegistry {
7778
/// let tr = ToolchainRegistry()
7879
/// tr.scanForToolchains()
7980
/// ```
80-
public convenience init(_ fileSystem: FileSystem) {
81+
public convenience init(installPath: AbsolutePath? = nil, _ fileSystem: FileSystem) {
8182
self.init()
82-
scanForToolchains(fileSystem)
83+
scanForToolchains(installPath: installPath, fileSystem)
8384
}
8485
}
8586

@@ -222,18 +223,12 @@ extension ToolchainRegistry {
222223
///
223224
/// If called with the default values, creates a toolchain registry that searches:
224225
/// * env SOURCEKIT_TOOLCHAIN_PATH <-- will override default toolchain
226+
/// * installPath <-- will override default toolchain
225227
/// * (Darwin) The currently selected Xcode
226228
/// * (Darwin) [~]/Library/Developer/Toolchains
227229
/// * env SOURCEKIT_PATH, PATH
228-
///
229-
/// This is equivalent to
230-
/// ```
231-
/// tr.scanForToolchains(environmentVariables: environmentVariables, setDefault: true)
232-
/// xcodes.forEach { tr.scanForToolchains(xcode: $0) }
233-
/// xctoolchainSearchPaths.forEach { tr.scanForToolchains(xctoolchainSearchPath: $0) }
234-
/// tr.scanForToolchains(pathVariables: pathVariables)
235-
/// ```
236230
public func scanForToolchains(
231+
installPath: AbsolutePath? = nil,
237232
environmentVariables: [String] = ["SOURCEKIT_TOOLCHAIN_PATH"],
238233
xcodes: [AbsolutePath] = [currentXcodeDeveloperPath].compactMap({$0}),
239234
xctoolchainSearchPaths: [AbsolutePath] = [
@@ -245,6 +240,12 @@ extension ToolchainRegistry {
245240
{
246241
queue.sync {
247242
_scanForToolchains(environmentVariables: environmentVariables, setDefault: true, fileSystem)
243+
if let installPath = installPath,
244+
let toolchain = try? _registerToolchain(installPath, fileSystem),
245+
_default == nil
246+
{
247+
_default = toolchain
248+
}
248249
xcodes.forEach { _scanForToolchains(xcode: $0, fileSystem) }
249250
xctoolchainSearchPaths.forEach { _scanForToolchains(xctoolchainSearchPath: $0, fileSystem) }
250251
_scanForToolchains(pathVariables: pathVariables, fileSystem)

Tests/SKCoreTests/ToolchainRegistryTests.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ final class ToolchainRegistryTests: XCTestCase {
171171
XCTAssertEqual(tc?.path, tcBin?.path)
172172
XCTAssertEqual(tc?.displayName, tcBin?.displayName)
173173

174+
175+
let trInstall = ToolchainRegistry()
176+
trInstall.scanForToolchains(installPath: path.appending(components: "usr", "bin"), environmentVariables: [], xcodes: [], xctoolchainSearchPaths: [], pathVariables: [], fs)
177+
XCTAssertEqual(trInstall.default?.identifier, "org.fake.explicit")
178+
XCTAssertEqual(trInstall.default?.path, path)
179+
174180
let overrideReg = ToolchainRegistry(fs)
175181
overrideReg.darwinToolchainOverride = "org.fake.global.B"
176182
XCTAssertEqual(overrideReg.darwinToolchainIdentifier, "org.fake.global.B")
@@ -418,6 +424,36 @@ final class ToolchainRegistryTests: XCTestCase {
418424
XCTAssert(toolchains[0] === xcodeA)
419425
XCTAssert(toolchains[1] === xcodeB)
420426
}
427+
428+
func testInstallPath() {
429+
let fs = InMemoryFileSystem()
430+
makeToolchain(binPath: AbsolutePath("/t1/bin"), fs, sourcekitd: true)
431+
432+
let trEmpty = ToolchainRegistry(installPath: nil, fs)
433+
XCTAssertNil(trEmpty.default)
434+
435+
let tr1 = ToolchainRegistry(installPath: AbsolutePath("/t1/bin"), fs)
436+
XCTAssertEqual(tr1.default?.path, AbsolutePath("/t1/bin"))
437+
XCTAssertNotNil(tr1.default?.sourcekitd)
438+
439+
let tr2 = ToolchainRegistry(installPath: AbsolutePath("/t2/bin"), fs)
440+
XCTAssertNil(tr2.default)
441+
}
442+
443+
func testInstallPathVsEnv() {
444+
let fs = InMemoryFileSystem()
445+
makeToolchain(binPath: AbsolutePath("/t1/bin"), fs, sourcekitd: true)
446+
makeToolchain(binPath: AbsolutePath("/t2/bin"), fs, sourcekitd: true)
447+
448+
try! ProcessEnv.setVar("TEST_SOURCEKIT_TOOLCHAIN_PATH_1", value: "/t2/bin")
449+
450+
let tr = ToolchainRegistry()
451+
tr.scanForToolchains(installPath: AbsolutePath("/t1/bin"), environmentVariables: ["TEST_SOURCEKIT_TOOLCHAIN_PATH_1"], fs)
452+
XCTAssertEqual(tr.toolchains.count, 2)
453+
454+
// Env variable wins.
455+
XCTAssertEqual(tr.default?.path, AbsolutePath("/t2/bin"))
456+
}
421457
}
422458

423459
#if os(macOS)

0 commit comments

Comments
 (0)