Skip to content

Commit 4486b10

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 3e33739 commit 4486b10

File tree

8 files changed

+95
-80
lines changed

8 files changed

+95
-80
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -650,11 +650,10 @@ public struct Driver {
650650
outputFileMap: outputFileMap)
651651

652652
self.supportedFrontendFlags =
653-
try Self.computeSupportedCompilerArgs(of: self.toolchain, hostTriple: self.hostTriple,
654-
parsedOptions: &self.parsedOptions,
655-
diagnosticsEngine: diagnosticEngine,
656-
fileSystem: fileSystem, executor: executor,
657-
env: env)
653+
try Self.computeSupportedCompilerArgs(of: self.toolchain,
654+
parsedOptions: &self.parsedOptions,
655+
diagnosticsEngine: diagnosticEngine,
656+
executor: executor)
658657
let supportedFrontendFlagsLocal = self.supportedFrontendFlags
659658
self.savedUnknownDriverFlagsForSwiftFrontend = try self.parsedOptions.saveUnknownFlags {
660659
Driver.isOptionFound($0, allOpts: supportedFrontendFlagsLocal)

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+
@_spi(Testing) public 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/Jobs/EmitSupportedFeaturesJob.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ extension Toolchain {
5757
}
5858

5959
extension Driver {
60+
<<<<<<< HEAD
6061
static func computeSupportedCompilerArgs(of toolchain: Toolchain, hostTriple: Triple,
6162
parsedOptions: inout ParsedOptions,
6263
diagnosticsEngine: DiagnosticsEngine,

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 the compiler executable.
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

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6685,6 +6685,8 @@ final class SwiftDriverTests: XCTestCase {
66856685
let PATH = "PATH"
66866686
#endif
66876687
let SWIFT_FRONTEND_EXEC = "SWIFT_DRIVER_SWIFT_FRONTEND_EXEC"
6688+
let SWIFT_SCANNER_LIB = "SWIFT_DRIVER_SWIFTSCAN_LIB"
6689+
66886690

66896691
// Reset the environment to ensure tool resolution is exactly run against PATH.
66906692
var driver = try Driver(args: ["swiftc", "-print-target-info"], env: [PATH: ProcessEnv.path!])
@@ -6695,6 +6697,7 @@ final class SwiftDriverTests: XCTestCase {
66956697

66966698
try withTemporaryDirectory { toolsDirectory in
66976699
let customSwiftFrontend = toolsDirectory.appending(component: executableName("swift-frontend"))
6700+
let customSwiftScan = toolsDirectory.appending(component: sharedLibraryName("lib_InternalSwiftScan"))
66986701
try localFileSystem.createSymbolicLink(customSwiftFrontend, pointingAt: defaultSwiftFrontend, relative: false)
66996702

67006703
try withTemporaryDirectory { tempDirectory in
@@ -6707,7 +6710,9 @@ final class SwiftDriverTests: XCTestCase {
67076710
// test if SWIFT_DRIVER_TOOLNAME_EXEC is respected
67086711
do {
67096712
var driver = try Driver(args: ["swiftc", "-print-target-info"],
6710-
env: [PATH: ProcessEnv.path!, SWIFT_FRONTEND_EXEC: customSwiftFrontend.pathString])
6713+
env: [PATH: ProcessEnv.path!,
6714+
SWIFT_FRONTEND_EXEC: customSwiftFrontend.pathString,
6715+
SWIFT_SCANNER_LIB: customSwiftScan.pathString])
67116716
let jobs = try driver.planBuild()
67126717
XCTAssertEqual(jobs.count, 1)
67136718
XCTAssertEqual(jobs.first!.tool.name, customSwiftFrontend.pathString)
@@ -6716,15 +6721,16 @@ final class SwiftDriverTests: XCTestCase {
67166721
// test if tools directory is respected
67176722
do {
67186723
var driver = try Driver(args: ["swiftc", "-print-target-info", "-tools-directory", toolsDirectory.pathString],
6719-
env: [PATH: ProcessEnv.path!])
6724+
env: [PATH: ProcessEnv.path!, SWIFT_SCANNER_LIB: customSwiftScan.pathString])
67206725
let jobs = try driver.planBuild()
67216726
XCTAssertEqual(jobs.count, 1)
67226727
XCTAssertEqual(jobs.first!.tool.name, customSwiftFrontend.pathString)
67236728
}
67246729

67256730
// test if current working directory is searched before PATH
67266731
do {
6727-
var driver = try Driver(args: ["swiftc", "-print-target-info"], env: [PATH: toolsDirectory.pathString])
6732+
var driver = try Driver(args: ["swiftc", "-print-target-info"],
6733+
env: [PATH: toolsDirectory.pathString, SWIFT_SCANNER_LIB: customSwiftScan.pathString])
67286734
let jobs = try driver.planBuild()
67296735
XCTAssertEqual(jobs.count, 1)
67306736
XCTAssertEqual(jobs.first!.tool.name, anotherSwiftFrontend.pathString)

0 commit comments

Comments
 (0)