Skip to content

Commit dd6bbf7

Browse files
authored
Merge pull request #1261 from artemcm/RefactorLibSwiftScanLookup_Again
[Dependency Scanning] Move computation of the path for libSwiftScan to the toolchain
2 parents eab32a7 + 2ad97b0 commit dd6bbf7

File tree

8 files changed

+102
-88
lines changed

8 files changed

+102
-88
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -650,11 +650,11 @@ 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+
fileSystem: fileSystem,
657+
executor: executor)
658658
let supportedFrontendFlagsLocal = self.supportedFrontendFlags
659659
self.savedUnknownDriverFlagsForSwiftFrontend = try self.parsedOptions.saveUnknownFlags {
660660
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: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,9 @@ 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)
225-
if try interModuleDependencyOracle
224+
let optionalScanLibPath = try toolchain.lookupSwiftScanLib()
225+
if let scanLibPath = optionalScanLibPath,
226+
try interModuleDependencyOracle
226227
.verifyOrCreateScannerInstance(fileSystem: fileSystem,
227228
swiftScanLibPath: scanLibPath) == false {
228229
fallbackToFrontend = true
@@ -490,46 +491,9 @@ public extension Driver {
490491
useResponseFiles: useResponseFiles)
491492
return args
492493
}
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-
}
527494

528495
static func getRootPath(of toolchain: Toolchain, env: [String: String])
529496
throws -> AbsolutePath {
530-
if let overrideString = env["SWIFT_DRIVER_SWIFT_SCAN_TOOLCHAIN_PATH"] {
531-
return try AbsolutePath(validating: overrideString)
532-
}
533497
return try toolchain.getToolPath(.swiftCompiler)
534498
.parentDirectory // bin
535499
.parentDirectory // toolchain root

Sources/SwiftDriver/Jobs/EmitSupportedFeaturesJob.swift

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,15 @@ extension Toolchain {
5757
}
5858

5959
extension Driver {
60-
static func computeSupportedCompilerArgs(of toolchain: Toolchain, hostTriple: Triple,
60+
61+
static func computeSupportedCompilerArgs(of toolchain: Toolchain,
6162
parsedOptions: inout ParsedOptions,
6263
diagnosticsEngine: DiagnosticsEngine,
6364
fileSystem: FileSystem,
64-
executor: DriverExecutor, env: [String: String])
65+
executor: DriverExecutor)
6566
throws -> Set<String> {
66-
if let supportedArgs = try querySupportedCompilerArgsInProcess(of: toolchain, hostTriple: hostTriple,
67-
fileSystem: fileSystem, env: env) {
67+
if let supportedArgs =
68+
try querySupportedCompilerArgsInProcess(of: toolchain, fileSystem: fileSystem) {
6869
return supportedArgs
6970
}
7071

@@ -84,14 +85,11 @@ extension Driver {
8485
}
8586

8687
static func querySupportedCompilerArgsInProcess(of toolchain: Toolchain,
87-
hostTriple: Triple,
88-
fileSystem: FileSystem,
89-
env: [String: String])
88+
fileSystem: FileSystem)
9089
throws -> Set<String>? {
91-
let swiftScanLibPath = try Self.getScanLibPath(of: toolchain,
92-
hostTriple: hostTriple,
93-
env: env)
94-
if fileSystem.exists(swiftScanLibPath) {
90+
let optionalSwiftScanLibPath = try toolchain.lookupSwiftScanLib()
91+
if let swiftScanLibPath = optionalSwiftScanLibPath,
92+
fileSystem.exists(swiftScanLibPath) {
9593
let libSwiftScanInstance = try SwiftScan(dylib: swiftScanLibPath)
9694
if libSwiftScanInstance.canQuerySupportedArguments() {
9795
return try libSwiftScanInstance.querySupportedArguments()

Sources/SwiftDriver/SwiftScan/SwiftScan.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -317,10 +317,7 @@ 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) {
320+
if let scanLibPath = try toolchain.lookupSwiftScanLib() {
324321
let libSwiftScanInstance = try SwiftScan(dylib: scanLibPath)
325322
if libSwiftScanInstance.canQuerySupportedArguments() {
326323
return try libSwiftScanInstance.querySupportedArguments()

Sources/SwiftDriver/Toolchains/Toolchain.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,45 @@ 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 getToolPath(.swiftCompiler).parentDirectory // bin
256+
.appending(component: "_InternalSwiftScan.dll")
257+
#else
258+
let libraryName = sharedLibraryName("lib_InternalSwiftScan")
259+
if let overrideString = env["SWIFT_DRIVER_SWIFTSCAN_LIB"],
260+
let path = try? AbsolutePath(validating: overrideString) {
261+
return path
262+
} else {
263+
let compilerPath = try getToolPath(.swiftCompiler)
264+
let toolchainRootPath = compilerPath.parentDirectory // bin
265+
.parentDirectory // toolchain root
266+
267+
let searchPaths = [toolchainRootPath.appending(component: "lib")
268+
.appending(component: "swift")
269+
.appending(component: compilerHostSupportLibraryOSComponent),
270+
toolchainRootPath.appending(component: "lib")
271+
.appending(component: "swift")
272+
.appending(component: "host"),
273+
// In case we are using a compiler from the build dir, we should also try
274+
// this path.
275+
toolchainRootPath.appending(component: "lib")]
276+
for libraryPath in searchPaths.map({ $0.appending(component: libraryName) }) {
277+
if fileSystem.isFile(libraryPath) {
278+
return libraryPath
279+
}
280+
}
281+
}
282+
283+
return nil
284+
#endif
285+
}
286+
248287
private func xcrunFind(executable: String) throws -> AbsolutePath {
249288
let xcrun = "xcrun"
250289
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
@@ -648,7 +648,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
648648
}
649649

650650
func testModuleAliasingWithImportPrescan() throws {
651-
let (_, _, toolchain, hostTriple) = try getDriverArtifactsForScanning()
651+
let (_, _, toolchain, _) = try getDriverArtifactsForScanning()
652652

653653
let dummyDriver = try Driver(args: ["swiftc", "-module-name", "dummyDriverCheck", "test.swift"])
654654
guard dummyDriver.isFrontendArgSupported(.moduleAlias) else {
@@ -658,9 +658,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
658658
// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
659659
// queries.
660660
let dependencyOracle = InterModuleDependencyOracle()
661-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
662-
hostTriple: hostTriple,
663-
env: ProcessEnv.vars)
661+
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
664662
guard try dependencyOracle
665663
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
666664
swiftScanLibPath: scanLibPath) else {
@@ -840,9 +838,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
840838

841839
// 2. Run a dependency scan to find the just-built module
842840
let dependencyOracle = InterModuleDependencyOracle()
843-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
844-
hostTriple: hostTriple,
845-
env: ProcessEnv.vars)
841+
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
846842
guard try dependencyOracle
847843
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
848844
swiftScanLibPath: scanLibPath) else {
@@ -939,14 +935,12 @@ final class ExplicitModuleBuildTests: XCTestCase {
939935

940936
/// Test the libSwiftScan dependency scanning (import-prescan).
941937
func testDependencyImportPrescan() throws {
942-
let (stdLibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()
938+
let (stdLibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
943939

944940
// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
945941
// queries.
946942
let dependencyOracle = InterModuleDependencyOracle()
947-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
948-
hostTriple: hostTriple,
949-
env: ProcessEnv.vars)
943+
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
950944
guard try dependencyOracle
951945
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
952946
swiftScanLibPath: scanLibPath) else {
@@ -1020,14 +1014,12 @@ final class ExplicitModuleBuildTests: XCTestCase {
10201014
}
10211015

10221016
func testDependencyScanningFailure() throws {
1023-
let (stdlibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()
1017+
let (stdlibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
10241018

10251019
// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
10261020
// queries.
10271021
let dependencyOracle = InterModuleDependencyOracle()
1028-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
1029-
hostTriple: hostTriple,
1030-
env: ProcessEnv.vars)
1022+
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
10311023
guard try dependencyOracle
10321024
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
10331025
swiftScanLibPath: scanLibPath) else {
@@ -1098,9 +1090,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
10981090
// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
10991091
// queries.
11001092
let dependencyOracle = InterModuleDependencyOracle()
1101-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
1102-
hostTriple: hostTriple,
1103-
env: ProcessEnv.vars)
1093+
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
11041094
guard try dependencyOracle
11051095
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
11061096
swiftScanLibPath: scanLibPath) else {
@@ -1293,11 +1283,9 @@ final class ExplicitModuleBuildTests: XCTestCase {
12931283
}
12941284

12951285
func testDependencyGraphDotSerialization() throws {
1296-
let (stdlibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()
1286+
let (stdlibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
12971287
let dependencyOracle = InterModuleDependencyOracle()
1298-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
1299-
hostTriple: hostTriple,
1300-
env: ProcessEnv.vars)
1288+
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
13011289
guard try dependencyOracle
13021290
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
13031291
swiftScanLibPath: scanLibPath) else {
@@ -1358,7 +1346,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
13581346

13591347
/// Test the libSwiftScan dependency scanning.
13601348
func testDependencyScanReuseCache() throws {
1361-
let (stdlibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()
1349+
let (stdlibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
13621350
try withTemporaryDirectory { path in
13631351
let cacheSavePath = path.appending(component: "saved.moddepcache")
13641352
let main = path.appending(component: "testDependencyScanning.swift")
@@ -1394,9 +1382,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
13941382
scannerCommand.removeFirst()
13951383
}
13961384

1397-
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
1398-
hostTriple: hostTriple,
1399-
env: ProcessEnv.vars)
1385+
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
14001386
// Run the first scan and serialize the cache contents.
14011387
let firstDependencyOracle = InterModuleDependencyOracle()
14021388
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)