@@ -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
@@ -221,33 +222,47 @@ extension Toolchain {
221
222
/// looks in the `executableDir`, `xcrunFind` or in the `searchPaths`.
222
223
/// - Parameter executable: executable to look for [i.e. `swift`]. Executable suffix (eg. `.exe`) should be omitted.
223
224
func lookup( executable: String ) throws -> AbsolutePath {
225
+ // 1. Check the `SWIFT_DRIVER_<TOOLNAME>_EXEC` override.
224
226
if let overrideString = envVar ( forExecutable: executable) ,
225
227
let path = try ? AbsolutePath ( validating: overrideString) {
228
+ if !fallbackToExecutableDefaultPath && !fileSystem. isExecutableFile ( path) {
229
+ throw ToolchainError . notAValidExecutablePath ( path. pathString)
230
+ }
226
231
return path
232
+ // 2. If `-tools-directory` is set, check there.
227
233
} else if let toolDir = toolDirectory,
228
234
let path = lookupExecutablePath ( filename: executableName ( executable) , currentWorkingDirectory: nil , searchPaths: [ toolDir] ) {
229
- // Looking for tools from the tools directory.
230
235
return path
236
+ // 3. Perform lookup relative to the driver's executable
231
237
} else if let path = lookupExecutablePath ( filename: executableName ( executable) , currentWorkingDirectory: fileSystem. currentWorkingDirectory, searchPaths: [ try executableDir] ) {
232
238
return path
233
239
}
240
+
241
+ // 4. Attempt lookup with `xcrun --find`.
234
242
#if canImport(Darwin)
235
243
if let path = try ? xcrunFind ( executable: executableName ( executable) ) {
236
244
return path
237
245
}
238
246
#endif
247
+
248
+ // 5. If querying not the compiler frontend itself and the above attempts failed,
249
+ // attempt to resolve adjacent to the compiler frontend.
239
250
if ![ " swift-frontend " , " swift " ] . contains ( executable) ,
240
251
let parentDirectory = try ? getToolPath ( . swiftCompiler) . parentDirectory,
241
252
try parentDirectory != executableDir,
242
253
let path = lookupExecutablePath ( filename: executableName ( executable) , searchPaths: [ parentDirectory] ) {
243
254
// If the driver library's client and the frontend are in different directories,
244
255
// try looking for tools next to the frontend.
245
256
return path
257
+ // 6. Perform lookup in the toolchain search paths (e.g. $PATH)
246
258
} else if let path = lookupExecutablePath ( filename: executableName ( executable) , searchPaths: searchPaths) {
247
259
return path
260
+ // 7. Attempt lookup of `swift` for the compiler frontned
261
+ // FIXME: we should remove this now
248
262
} else if executable == " swift-frontend " {
249
263
// Temporary shim: fall back to looking for "swift" before failing.
250
264
return try lookup ( executable: " swift " )
265
+ // 8. For testing purposes, attempt lookup in the system "default" paths
251
266
} else if fallbackToExecutableDefaultPath {
252
267
if self is WindowsToolchain {
253
268
return try getToolPath ( . swiftCompiler)
@@ -258,7 +273,7 @@ extension Toolchain {
258
273
}
259
274
}
260
275
261
- throw ToolchainError . unableToFind ( tool : executable)
276
+ throw ToolchainError . unableToFind ( executable)
262
277
}
263
278
264
279
/// Looks for the executable in the `SWIFT_DRIVER_SWIFTSCAN_LIB` environment variable, if found nothing,
@@ -311,7 +326,7 @@ extension Toolchain {
311
326
private func xcrunFind( executable: String ) throws -> AbsolutePath {
312
327
let xcrun = " xcrun "
313
328
guard lookupExecutablePath ( filename: xcrun, searchPaths: searchPaths) != nil else {
314
- throw ToolchainError . unableToFind ( tool : xcrun)
329
+ throw ToolchainError . unableToFind ( xcrun)
315
330
}
316
331
317
332
let path = try executor. checkNonZeroExit (
@@ -378,6 +393,17 @@ extension Toolchain {
378
393
}
379
394
}
380
395
381
- @_spi ( Testing) public enum ToolchainError : Swift . Error {
382
- case unableToFind( tool: String )
396
+ @_spi ( Testing) public enum ToolchainError : Swift . Error , Equatable , DiagnosticData {
397
+ case unableToFind( String )
398
+ case notAValidExecutablePath( String )
399
+
400
+ public var description : String {
401
+ switch self {
402
+ case . unableToFind( let tool) :
403
+ return " unable to locate tool: ' \( tool) ' "
404
+ case . notAValidExecutablePath( let path) :
405
+ return " not a valid executable: \( path) "
406
+
407
+ }
408
+ }
383
409
}
0 commit comments