Skip to content

Commit 1972c29

Browse files
committed
[Dependency Scanning] Move computation of the path for libSwiftScan to the toolchain
Alongside lookup of executable tools, the toolchain is now responsible for looking up the driver's compiler support and dependency scanning library. It also adds an environment variable override 'SWIFT_DRIVER_SWIFTSCAN_LIB' for clients to specify a specific path to this shared library that they would like to be used instead of the default.
1 parent cee8c66 commit 1972c29

File tree

5 files changed

+81
-72
lines changed

5 files changed

+81
-72
lines changed

Sources/SwiftDriver/Driver/WindowsExtensions.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,27 @@ internal func executableName(_ name: String) -> String {
2020
return name
2121
#endif
2222
}
23+
24+
internal func sharedLibraryName(_ name: String) -> String {
25+
#if canImport(Darwin)
26+
let ext = ".dylib"
27+
#elseif os(Windows)
28+
let ext = ".dll"
29+
#else
30+
let ext = ".so"
31+
#endif
32+
return name + ext
33+
}
34+
35+
// FIXME: This can be subtly wrong, we should rather
36+
// try to get the client to provide this info or move to a better
37+
// path convention for where we keep compiler support libraries
38+
internal var compilerHostSupportLibraryOSComponent : String {
39+
#if canImport(Darwin)
40+
return "macosx"
41+
#elseif os(Windows)
42+
return "windows"
43+
#else
44+
return "linux"
45+
#endif
46+
}

Sources/SwiftDriver/ExplicitModuleBuilds/ModuleDependencyScanning.swift

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ public extension Driver {
221221
// attempt to fallback to using `swift-frontend -scan-dependencies` invocations for dependency
222222
// scanning.
223223
var fallbackToFrontend = parsedOptions.hasArgument(.driverScanDependenciesNonLib)
224-
let scanLibPath = try Self.getScanLibPath(of: toolchain, hostTriple: hostTriple, env: env)
224+
let scanLibPath = try toolchain.lookupSwiftScanLib()
225225
if try interModuleDependencyOracle
226226
.verifyOrCreateScannerInstance(fileSystem: fileSystem,
227227
swiftScanLibPath: scanLibPath) == false {
@@ -490,46 +490,9 @@ public extension Driver {
490490
useResponseFiles: useResponseFiles)
491491
return args
492492
}
493-
}
494-
495-
@_spi(Testing) public extension Driver {
496-
static func getScanLibPath(of toolchain: Toolchain, hostTriple: Triple,
497-
env: [String: String]) throws -> AbsolutePath {
498-
if hostTriple.isWindows {
499-
// no matter if we are in a build tree or an installed tree, the layout is
500-
// always: `bin/_InternalSwiftScan.dll`
501-
return try getRootPath(of: toolchain, env: env)
502-
.appending(component: "bin")
503-
.appending(component: "_InternalSwiftScan.dll")
504-
}
505-
506-
let sharedLibExt: String
507-
if hostTriple.isMacOSX {
508-
sharedLibExt = ".dylib"
509-
} else {
510-
sharedLibExt = ".so"
511-
}
512-
let libScanner = "lib_InternalSwiftScan\(sharedLibExt)"
513-
// We first look into position in toolchain
514-
let libPath
515-
= try getRootPath(of: toolchain, env: env).appending(component: "lib")
516-
.appending(component: "swift")
517-
.appending(component: hostTriple.osNameUnversioned)
518-
.appending(component: libScanner)
519-
if localFileSystem.exists(libPath) {
520-
return libPath
521-
}
522-
// In case we are using a compiler from the build dir, we should also try
523-
// this path.
524-
return try getRootPath(of: toolchain, env: env).appending(component: "lib")
525-
.appending(component: libScanner)
526-
}
527493

528494
static func getRootPath(of toolchain: Toolchain, env: [String: String])
529495
throws -> AbsolutePath {
530-
if let overrideString = env["SWIFT_DRIVER_SWIFT_SCAN_TOOLCHAIN_PATH"] {
531-
return try AbsolutePath(validating: overrideString)
532-
}
533496
return try toolchain.getToolPath(.swiftCompiler)
534497
.parentDirectory // bin
535498
.parentDirectory // toolchain root

Sources/SwiftDriver/SwiftScan/SwiftScan.swift

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -317,14 +317,10 @@ internal final class SwiftScan {
317317
@_spi(Testing) public extension Driver {
318318
func querySupportedArgumentsForTest() throws -> Set<String>? {
319319
// If a capable libSwiftScan is found, manually ensure we can get the supported arguments
320-
let scanLibPath = try Self.getScanLibPath(of: toolchain,
321-
hostTriple: hostTriple,
322-
env: env)
323-
if fileSystem.exists(scanLibPath) {
324-
let libSwiftScanInstance = try SwiftScan(dylib: scanLibPath)
325-
if libSwiftScanInstance.canQuerySupportedArguments() {
326-
return try libSwiftScanInstance.querySupportedArguments()
327-
}
320+
let scanLibPath = try toolchain.lookupSwiftScanLib()
321+
let libSwiftScanInstance = try SwiftScan(dylib: scanLibPath)
322+
if libSwiftScanInstance.canQuerySupportedArguments() {
323+
return try libSwiftScanInstance.querySupportedArguments()
328324
}
329325
return nil
330326
}

Sources/SwiftDriver/Toolchains/Toolchain.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,46 @@ extension Toolchain {
245245
}
246246
}
247247

248+
/// Looks for the executable in the `SWIFT_DRIVER_SWIFTSCAN_LIB` environment variable, if found nothing,
249+
/// looks in the `lib` relative to `executableDir`, `toolsDir`, `xcrunFind` or in the `searchPaths`.
250+
/// TODO: If the driver needs to lookup other shared libraries, this is simple to generalize
251+
@_spi(Testing) public func lookupSwiftScanLib() throws -> AbsolutePath {
252+
#if os(Windows)
253+
// no matter if we are in a build tree or an installed tree, the layout is
254+
// always: `bin/_InternalSwiftScan.dll`
255+
return try toolchain.getToolPath(.swiftCompiler)
256+
.parentDirectory // bin
257+
.appending(component: "_InternalSwiftScan.dll")
258+
#else
259+
let libraryName = sharedLibraryName("lib_InternalSwiftScan")
260+
if let overrideString = env["SWIFT_DRIVER_SWIFTSCAN_LIB"],
261+
let path = try? AbsolutePath(validating: overrideString) {
262+
return path
263+
} else {
264+
let compilerPath = try getToolPath(.swiftCompiler)
265+
let toolchainRootPath = compilerPath.parentDirectory // bin
266+
.parentDirectory // toolchain root
267+
268+
let searchPaths = [toolchainRootPath.appending(component: "lib")
269+
.appending(component: "swift")
270+
.appending(component: compilerHostSupportLibraryOSComponent),
271+
toolchainRootPath.appending(component: "lib")
272+
.appending(component: "swift")
273+
.appending(component: "host"),
274+
// In case we are using a compiler from the build dir, we should also try
275+
// this path.
276+
toolchainRootPath.appending(component: "lib")]
277+
for libraryPath in searchPaths.map({ $0.appending(component: libraryName) }) {
278+
if fileSystem.isFile(libraryPath) {
279+
return libraryPath
280+
}
281+
}
282+
}
283+
284+
throw ToolchainError.unableToFind(tool: libraryName)
285+
#endif
286+
}
287+
248288
private func xcrunFind(executable: String) throws -> AbsolutePath {
249289
let xcrun = "xcrun"
250290
guard lookupExecutablePath(filename: xcrun, searchPaths: searchPaths) != nil else {

Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
640640
}
641641

642642
func testModuleAliasingWithImportPrescan() throws {
643-
let (_, _, toolchain, hostTriple) = try getDriverArtifactsForScanning()
643+
let (_, _, toolchain, _) = try getDriverArtifactsForScanning()
644644

645645
let dummyDriver = try Driver(args: ["swiftc", "-module-name", "dummyDriverCheck", "test.swift"])
646646
guard dummyDriver.isFrontendArgSupported(.moduleAlias) else {
@@ -650,9 +650,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
650650
// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
651651
// queries.
652652
let dependencyOracle = InterModuleDependencyOracle()
653-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
654-
hostTriple: hostTriple,
655-
env: ProcessEnv.vars)
653+
let scanLibPath = try toolchain.lookupSwiftScanLib()
656654
guard try dependencyOracle
657655
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
658656
swiftScanLibPath: scanLibPath) else {
@@ -832,9 +830,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
832830

833831
// 2. Run a dependency scan to find the just-built module
834832
let dependencyOracle = InterModuleDependencyOracle()
835-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
836-
hostTriple: hostTriple,
837-
env: ProcessEnv.vars)
833+
let scanLibPath = try toolchain.lookupSwiftScanLib()
838834
guard try dependencyOracle
839835
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
840836
swiftScanLibPath: scanLibPath) else {
@@ -931,14 +927,12 @@ final class ExplicitModuleBuildTests: XCTestCase {
931927

932928
/// Test the libSwiftScan dependency scanning (import-prescan).
933929
func testDependencyImportPrescan() throws {
934-
let (stdLibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()
930+
let (stdLibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
935931

936932
// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
937933
// queries.
938934
let dependencyOracle = InterModuleDependencyOracle()
939-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
940-
hostTriple: hostTriple,
941-
env: ProcessEnv.vars)
935+
let scanLibPath = try toolchain.lookupSwiftScanLib()
942936
guard try dependencyOracle
943937
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
944938
swiftScanLibPath: scanLibPath) else {
@@ -1009,14 +1003,12 @@ final class ExplicitModuleBuildTests: XCTestCase {
10091003
}
10101004

10111005
func testDependencyScanningFailure() throws {
1012-
let (stdlibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()
1006+
let (stdlibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
10131007

10141008
// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
10151009
// queries.
10161010
let dependencyOracle = InterModuleDependencyOracle()
1017-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
1018-
hostTriple: hostTriple,
1019-
env: ProcessEnv.vars)
1011+
let scanLibPath = try toolchain.lookupSwiftScanLib()
10201012
guard try dependencyOracle
10211013
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
10221014
swiftScanLibPath: scanLibPath) else {
@@ -1087,9 +1079,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
10871079
// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
10881080
// queries.
10891081
let dependencyOracle = InterModuleDependencyOracle()
1090-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
1091-
hostTriple: hostTriple,
1092-
env: ProcessEnv.vars)
1082+
let scanLibPath = try toolchain.lookupSwiftScanLib()
10931083
guard try dependencyOracle
10941084
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
10951085
swiftScanLibPath: scanLibPath) else {
@@ -1277,11 +1267,9 @@ final class ExplicitModuleBuildTests: XCTestCase {
12771267
}
12781268

12791269
func testDependencyGraphDotSerialization() throws {
1280-
let (stdlibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()
1270+
let (stdlibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
12811271
let dependencyOracle = InterModuleDependencyOracle()
1282-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
1283-
hostTriple: hostTriple,
1284-
env: ProcessEnv.vars)
1272+
let scanLibPath = try toolchain.lookupSwiftScanLib()
12851273
guard try dependencyOracle
12861274
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
12871275
swiftScanLibPath: scanLibPath) else {
@@ -1342,7 +1330,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
13421330

13431331
/// Test the libSwiftScan dependency scanning.
13441332
func testDependencyScanReuseCache() throws {
1345-
let (stdlibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()
1333+
let (stdlibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
13461334
try withTemporaryDirectory { path in
13471335
let cacheSavePath = path.appending(component: "saved.moddepcache")
13481336
let main = path.appending(component: "testDependencyScanning.swift")
@@ -1378,9 +1366,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
13781366
scannerCommand.removeFirst()
13791367
}
13801368

1381-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
1382-
hostTriple: hostTriple,
1383-
env: ProcessEnv.vars)
1369+
let scanLibPath = try toolchain.lookupSwiftScanLib()
13841370
// Run the first scan and serialize the cache contents.
13851371
let firstDependencyOracle = InterModuleDependencyOracle()
13861372
guard try firstDependencyOracle

0 commit comments

Comments
 (0)