Skip to content

Commit 6640ed5

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

File tree

5 files changed

+58
-58
lines changed

5 files changed

+58
-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: 40 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,38 @@ 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 `executableDir`, `xcrunFind` or in the `searchPaths`.
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+
} else if let path = try? xcrunFind(exec: exec) {
113+
return path
114+
} else if let path = lookupExecutablePath(filename: exec, searchPaths: searchPaths) {
115+
return path
116+
} else {
117+
throw ToolchainError.unableToFind(tool: exec)
118+
}
119+
}
120+
121+
private func xcrunFind(exec: String) throws -> AbsolutePath {
122+
#if os(macOS)
123+
let path = try Process.checkNonZeroExit(
124+
arguments: ["xcrun", "-sdk", "macosx", "--find", exec],
125+
environment: env
126+
).spm_chomp()
127+
return AbsolutePath(path)
128+
#else
129+
// This is a hack so our tests work on linux. We need a better way for looking up tools in general.
130+
return AbsolutePath("/usr/bin/" + exec)
131+
#endif
132+
}
133+
}
134+
135+
fileprivate enum ToolchainError: Swift.Error {
136+
case unableToFind(tool: String)
97137
}

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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ final class SwiftDriverTests: XCTestCase {
546546
XCTAssertFalse(cmd.contains(.flag("-dylib")))
547547
XCTAssertFalse(cmd.contains(.flag("-shared")))
548548
}
549-
549+
550550
do {
551551
// linux target
552552
var driver = try Driver(args: commonArgs + ["-emit-library", "-target", "x86_64-unknown-linux"])

0 commit comments

Comments
 (0)