Skip to content

Commit 17ff55d

Browse files
committed
[Toolchains] Generalize lookup routines as a Toolchain extension.
1 parent 25b51ce commit 17ff55d

File tree

5 files changed

+68
-58
lines changed

5 files changed

+68
-58
lines changed

Sources/SwiftDriver/Toolchains/DarwinToolchain.swift

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -115,29 +115,4 @@ public final class DarwinToolchain: Toolchain {
115115
\(isShared ? "_dynamic.dylib" : ".a")
116116
"""
117117
}
118-
119-
/// Looks for the executable in the `SWIFT_DRIVER_TOOLNAME_EXEC` enviroment variable, if found nothing,
120-
/// looks in the executable path; finally, fallback to xcrunFind.
121-
/// - Parameter exec: executable to look for [i.e. `swift`].
122-
func lookup(exec: String) throws -> AbsolutePath {
123-
if let overrideString = envVar(forExecutable: exec) {
124-
return try AbsolutePath(validating: overrideString)
125-
} else if let path = lookupExecutablePath(filename: exec, searchPaths: [executableDir]) {
126-
return path
127-
}
128-
return try xcrunFind(exec: exec)
129-
}
130-
131-
private func xcrunFind(exec: String) throws -> AbsolutePath {
132-
#if os(macOS)
133-
let path = try Process.checkNonZeroExit(
134-
arguments: ["xcrun", "-sdk", "macosx", "--find", exec],
135-
environment: env
136-
).spm_chomp()
137-
return AbsolutePath(path)
138-
#else
139-
// This is a hack so our tests work on linux. We need a better way for looking up tools in general.
140-
return AbsolutePath("/usr/bin/" + exec)
141-
#endif
142-
}
143118
}

Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,10 @@ import TSCBasic
1313

1414
/// Toolchain for Unix-like systems.
1515
public final class GenericUnixToolchain: Toolchain {
16-
enum Error: Swift.Error {
17-
case unableToFind(tool: String)
18-
}
19-
2016
public let env: [String: String]
2117

22-
private let searchPaths: [AbsolutePath]
23-
2418
public init(env: [String: String]) {
2519
self.env = env
26-
self.searchPaths = getEnvSearchPaths(pathString: env["PATH"], currentWorkingDirectory: localFileSystem.currentWorkingDirectory)
27-
}
28-
29-
/// Looks in the `executablePath`, if found nothing, looks in the enviroment search paths.
30-
/// - Parameter exec: executable to look for [i.e. `swift`].
31-
private func lookup(exec: String) throws -> AbsolutePath {
32-
if let path = lookupExecutablePath(filename: exec, searchPaths: [executableDir]) {
33-
return path
34-
} else if let path = lookupExecutablePath(filename: exec, searchPaths: searchPaths) {
35-
return path
36-
}
37-
38-
// If we happen to be on a macOS host, some tools might not be in our
39-
// PATH, so we'll just use xcrun to find them too.
40-
#if os(macOS)
41-
return try DarwinToolchain(env: self.env).lookup(exec: exec)
42-
#else
43-
throw Error.unableToFind(tool: exec)
44-
#endif
4520
}
4621

4722
public func makeLinkerOutputFilename(moduleName: String, type: LinkOutputType) -> String {

Sources/SwiftDriver/Toolchains/Toolchain.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public protocol Toolchain {
2828

2929
var env: [String: String] { get }
3030

31+
var searchPaths: [AbsolutePath] { get }
32+
3133
/// Retrieve the absolute path to a particular tool.
3234
func getToolPath(_ tool: Tool) throws -> AbsolutePath
3335

@@ -60,6 +62,10 @@ public protocol Toolchain {
6062
}
6163

6264
extension Toolchain {
65+
public var searchPaths: [AbsolutePath] {
66+
getEnvSearchPaths(pathString: env["PATH"], currentWorkingDirectory: localFileSystem.currentWorkingDirectory)
67+
}
68+
6369
public func swiftCompilerVersion() throws -> String {
6470
try Process.checkNonZeroExit(
6571
args: getToolPath(.swiftCompiler).pathString, "-version",
@@ -94,4 +100,42 @@ extension Toolchain {
94100
private func envVarName(for toolName: String) -> String {
95101
return "SWIFT_DRIVER_\(toolName.uppercased())_EXEC"
96102
}
103+
104+
/// Looks for the executable in the `SWIFT_DRIVER_TOOLNAME_EXEC` enviroment variable, if found nothing,
105+
/// looks in the executable path; finally, fallback to xcrunFind on macOS.
106+
/// - Parameter exec: executable to look for [i.e. `swift`].
107+
func lookup(exec: String) throws -> AbsolutePath {
108+
if let overrideString = envVar(forExecutable: exec) {
109+
return try AbsolutePath(validating: overrideString)
110+
} else if let path = lookupExecutablePath(filename: exec, searchPaths: [executableDir]) {
111+
return path
112+
}
113+
114+
#if os(macOS)
115+
return try xcrunFind(exec: exec)
116+
#elseif os(Linux)
117+
if let path = lookupExecutablePath(filename: exec, searchPaths: searchPaths) {
118+
return path
119+
} else {
120+
throw ToolchainError.unableToFind(tool: exec)
121+
}
122+
#endif
123+
}
124+
125+
private func xcrunFind(exec: String) throws -> AbsolutePath {
126+
#if os(macOS)
127+
let path = try Process.checkNonZeroExit(
128+
arguments: ["xcrun", "-sdk", "macosx", "--find", exec],
129+
environment: env
130+
).spm_chomp()
131+
return AbsolutePath(path)
132+
#else
133+
// This is a hack so our tests work on linux. We need a better way for looking up tools in general.
134+
return AbsolutePath("/usr/bin/" + exec)
135+
#endif
136+
}
137+
}
138+
139+
fileprivate enum ToolchainError: Swift.Error {
140+
case unableToFind(tool: String)
97141
}

Tests/SwiftDriverTests/JobExecutorTests.swift

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,25 @@ final class JobExecutorTests: XCTestCase {
191191

192192
func testSwiftDriverExecOverride() throws {
193193
var env = ProcessEnv.vars
194+
let envVarName = "SWIFT_DRIVER_SWIFT_EXEC"
195+
let dummyPath = "/some/garbage/path/fnord"
194196

195-
env.removeValue(forKey: "SWIFT_DRIVER_SWIFT_EXEC")
196-
let normalToolchain = DarwinToolchain(env: env)
197-
let normalSwiftPath = try normalToolchain.getToolPath(.swiftCompiler)
197+
// DarwinToolchain
198+
env.removeValue(forKey: envVarName)
199+
let normalSwiftPath = try DarwinToolchain(env: env).getToolPath(.swiftCompiler)
198200
XCTAssertEqual(normalSwiftPath.basenameWithoutExt, "swift")
199201

200-
env["SWIFT_DRIVER_SWIFT_EXEC"] = "/some/garbage/path/fnord"
201-
let overriddenToolchain = DarwinToolchain(env: env)
202-
let overriddenSwiftPath = try overriddenToolchain.getToolPath(.swiftCompiler)
203-
XCTAssertEqual(overriddenSwiftPath, AbsolutePath("/some/garbage/path/fnord"))
202+
env[envVarName] = dummyPath
203+
let overriddenSwiftPath = try DarwinToolchain(env: env).getToolPath(.swiftCompiler)
204+
XCTAssertEqual(overriddenSwiftPath, AbsolutePath(dummyPath))
205+
206+
// GenericUnixToolchain
207+
env.removeValue(forKey: envVarName)
208+
let unixSwiftPath = try GenericUnixToolchain(env: env).getToolPath(.swiftCompiler)
209+
XCTAssertEqual(unixSwiftPath.basenameWithoutExt, "swift")
210+
211+
env[envVarName] = dummyPath
212+
let unixOverriddenSwiftPath = try GenericUnixToolchain(env: env).getToolPath(.swiftCompiler)
213+
XCTAssertEqual(unixOverriddenSwiftPath, AbsolutePath(dummyPath))
204214
}
205215
}

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ final class SwiftDriverTests: XCTestCase {
278278
}
279279

280280
func testStandardCompileJobs() throws {
281+
#if os(macOS)
281282
var driver1 = try Driver(args: ["swiftc", "foo.swift", "bar.swift", "-module-name", "Test", "-target", "x86_64-apple-macosx10.15"])
282283
let plannedJobs = try driver1.planBuild()
283284
XCTAssertEqual(plannedJobs.count, 3)
@@ -306,6 +307,7 @@ final class SwiftDriverTests: XCTestCase {
306307
XCTAssertTrue(plannedJobs3[0].commandLine.contains(.flag("-module-name")))
307308
XCTAssertTrue(plannedJobs3[0].commandLine.contains(.flag("Test")))
308309
XCTAssertTrue(plannedJobs3[0].commandLine.contains(.flag("-parse-as-library")))
310+
#endif
309311
}
310312

311313
func testOutputFileMapLoading() throws {
@@ -430,6 +432,7 @@ final class SwiftDriverTests: XCTestCase {
430432

431433
func testLinking() throws {
432434
let commonArgs = ["swiftc", "foo.swift", "bar.swift", "-module-name", "Test"]
435+
#if os(macOS)
433436
do {
434437
// macOS target
435438
var driver = try Driver(args: commonArgs + ["-emit-library", "-target", "x86_64-apple-macosx10.15"])
@@ -546,7 +549,7 @@ final class SwiftDriverTests: XCTestCase {
546549
XCTAssertFalse(cmd.contains(.flag("-dylib")))
547550
XCTAssertFalse(cmd.contains(.flag("-shared")))
548551
}
549-
552+
#elseif os(Linux)
550553
do {
551554
// linux target
552555
var driver = try Driver(args: commonArgs + ["-emit-library", "-target", "x86_64-unknown-linux"])
@@ -603,6 +606,7 @@ final class SwiftDriverTests: XCTestCase {
603606
XCTAssertFalse(cmd.contains(.flag("-static")))
604607
XCTAssertFalse(cmd.contains(.flag("-shared")))
605608
}
609+
#endif
606610
}
607611

608612
func testSanitizerArgs() throws {
@@ -802,6 +806,7 @@ final class SwiftDriverTests: XCTestCase {
802806
}
803807

804808
func testDSYMGeneration() throws {
809+
#if os(macOS)
805810
let commonArgs = [
806811
"swiftc", "-target", "x86_64-apple-macosx",
807812
"foo.swift", "bar.swift", "-emit-executable",
@@ -840,6 +845,7 @@ final class SwiftDriverTests: XCTestCase {
840845
let cmd = generateDSYMJob.commandLine
841846
XCTAssertTrue(cmd.contains(.path(try VirtualPath(path: "Test"))))
842847
}
848+
#endif
843849
}
844850

845851
func testDOTFileEmission() throws {

0 commit comments

Comments
 (0)