@@ -15,6 +15,7 @@ import class Foundation.Bundle
15
15
16
16
import func TSCBasic. getEnvSearchPaths
17
17
import func TSCBasic. lookupExecutablePath
18
+ import protocol TSCBasic. DiagnosticData
18
19
import class TSCBasic. DiagnosticsEngine
19
20
import protocol TSCBasic. FileSystem
20
21
import struct TSCBasic. AbsolutePath
@@ -215,29 +216,41 @@ extension Toolchain {
215
216
/// looks in the `executableDir`, `xcrunFind` or in the `searchPaths`.
216
217
/// - Parameter executable: executable to look for [i.e. `swift`]. Executable suffix (eg. `.exe`) should be omitted.
217
218
func lookup( executable: String ) throws -> AbsolutePath {
219
+ // 1. Check the `SWIFT_DRIVER_<TOOLNAME>_EXEC` override.
218
220
if let overrideString = envVar ( forExecutable: executable) ,
219
221
let path = try ? AbsolutePath ( validating: overrideString) {
222
+ if !fallbackToExecutableDefaultPath && !fileSystem. isExecutableFile ( path) {
223
+ throw ToolchainError . notAValidExecutablePath ( path. pathString)
224
+ }
220
225
return path
226
+ // 2. If `-tools-directory` is set, check there.
221
227
} else if let toolDir = toolDirectory,
222
228
let path = lookupExecutablePath ( filename: executableName ( executable) , currentWorkingDirectory: nil , searchPaths: [ toolDir] ) {
223
- // Looking for tools from the tools directory.
224
229
return path
230
+ // 3. Perform lookup relative to the driver's executable
225
231
} else if let path = lookupExecutablePath ( filename: executableName ( executable) , currentWorkingDirectory: nil , searchPaths: [ try executableDir] ) {
226
232
return path
233
+ // 4. Attempt lookup with `xcrun --find`.
227
234
} else if let path = try ? xcrunFind ( executable: executableName ( executable) ) {
228
235
return path
236
+ // 5. If querying not the compiler frontend itself and the above attempts failed,
237
+ // attempt to resolve adjacent to the compiler frontend.
229
238
} else if ![ " swift-frontend " , " swift " ] . contains ( executable) ,
230
239
let parentDirectory = try ? getToolPath ( . swiftCompiler) . parentDirectory,
231
240
try parentDirectory != executableDir,
232
241
let path = lookupExecutablePath ( filename: executableName ( executable) , searchPaths: [ parentDirectory] ) {
233
242
// If the driver library's client and the frontend are in different directories,
234
243
// try looking for tools next to the frontend.
235
244
return path
245
+ // 6. Perform lookup in the toolchain search paths (e.g. $PATH)
236
246
} else if let path = lookupExecutablePath ( filename: executableName ( executable) , searchPaths: searchPaths) {
237
247
return path
248
+ // 7. Attempt lookup of `swift` for the compiler frontned
249
+ // FIXME: we should remove this now
238
250
} else if executable == " swift-frontend " {
239
251
// Temporary shim: fall back to looking for "swift" before failing.
240
252
return try lookup ( executable: " swift " )
253
+ // 8. For testing purposes, attempt lookup in the system "default" paths
241
254
} else if fallbackToExecutableDefaultPath {
242
255
if self is WindowsToolchain {
243
256
return try getToolPath ( . swiftCompiler)
@@ -247,7 +260,7 @@ extension Toolchain {
247
260
return try AbsolutePath ( validating: " /usr/bin/ " + executable)
248
261
}
249
262
} else {
250
- throw ToolchainError . unableToFind ( tool : executable)
263
+ throw ToolchainError . unableToFind ( executable)
251
264
}
252
265
}
253
266
@@ -302,7 +315,7 @@ extension Toolchain {
302
315
private func xcrunFind( executable: String ) throws -> AbsolutePath {
303
316
let xcrun = " xcrun "
304
317
guard lookupExecutablePath ( filename: xcrun, searchPaths: searchPaths) != nil else {
305
- throw ToolchainError . unableToFind ( tool : xcrun)
318
+ throw ToolchainError . unableToFind ( xcrun)
306
319
}
307
320
308
321
let path = try executor. checkNonZeroExit (
@@ -368,6 +381,17 @@ extension Toolchain {
368
381
}
369
382
}
370
383
371
- @_spi ( Testing) public enum ToolchainError : Swift . Error {
372
- case unableToFind( tool: String )
384
+ @_spi ( Testing) public enum ToolchainError : Swift . Error , Equatable , DiagnosticData {
385
+ case unableToFind( String )
386
+ case notAValidExecutablePath( String )
387
+
388
+ public var description : String {
389
+ switch self {
390
+ case . unableToFind( let tool) :
391
+ return " unable to locate tool: ' \( tool) ' "
392
+ case . notAValidExecutablePath( let path) :
393
+ return " not a valid executable: \( path) "
394
+
395
+ }
396
+ }
373
397
}
0 commit comments