Skip to content

Commit 44b5b24

Browse files
committed
Fallback on 'swift-frontend -scan-dependencies ...' fallback path in case libSwiftScan shared library cannot be loaded.
Resolves rdar://127768140
1 parent 22b351b commit 44b5b24

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

Sources/SwiftDriver/ExplicitModuleBuilds/ModuleDependencyScanning.swift

+15-7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ extension Diagnostic.Message {
2626
static func warn_scanner_frontend_fallback() -> Diagnostic.Message {
2727
.warning("Fallback to `swift-frontend` dependency scanner invocation")
2828
}
29+
static func remark_inprocess_dependency_scan_failed(_ libPath: String) -> Diagnostic.Message {
30+
.remark("In-process dependency scan query failed due to incompatible libSwiftScan (\(libPath)). Fallback to `swift-frontend` dependency scanner invocation.")
31+
}
2932
static func scanner_diagnostic_error(_ message: String) -> Diagnostic.Message {
3033
.error(message)
3134
}
@@ -171,12 +174,17 @@ public extension Driver {
171174
return true
172175
}
173176

174-
try interModuleDependencyOracle.verifyOrCreateScannerInstance(fileSystem: fileSystem,
175-
swiftScanLibPath: scanLibPath)
176-
if isCachingEnabled {
177-
self.cas = try interModuleDependencyOracle.getOrCreateCAS(pluginPath: try getCASPluginPath(),
178-
onDiskPath: try getOnDiskCASPath(),
179-
pluginOptions: try getCASPluginOptions())
177+
do {
178+
try interModuleDependencyOracle.verifyOrCreateScannerInstance(fileSystem: fileSystem,
179+
swiftScanLibPath: scanLibPath)
180+
if isCachingEnabled {
181+
self.cas = try interModuleDependencyOracle.getOrCreateCAS(pluginPath: try getCASPluginPath(),
182+
onDiskPath: try getOnDiskCASPath(),
183+
pluginOptions: try getCASPluginOptions())
184+
}
185+
} catch {
186+
diagnosticEngine.emit(.remark_inprocess_dependency_scan_failed(scanLibPath.description))
187+
return true
180188
}
181189
return false
182190
}
@@ -257,7 +265,7 @@ public extension Driver {
257265
}
258266
}
259267

260-
mutating internal func performDependencyScan() throws -> InterModuleDependencyGraph {
268+
mutating func performDependencyScan() throws -> InterModuleDependencyGraph {
261269
let scannerJob = try dependencyScanningJob()
262270
let forceResponseFiles = parsedOptions.hasArgument(.driverForceResponseFiles)
263271
let dependencyGraph: InterModuleDependencyGraph

Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift

+44
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,50 @@ final class ExplicitModuleBuildTests: XCTestCase {
15171517
}
15181518
}
15191519

1520+
// Ensure dependency scanning succeeds via fallback `swift-frontend -scan-dependenceis`
1521+
// mechanism if libSwiftScan.dylib fails to load.
1522+
func testDependencyScanningFallback() throws {
1523+
let (stdlibPath, shimsPath, _, _) = try getDriverArtifactsForScanning()
1524+
1525+
// Create a simple test case.
1526+
try withTemporaryDirectory { path in
1527+
let main = path.appending(component: "testDependencyScanningFallback.swift")
1528+
try localFileSystem.writeFileContents(main, bytes: "import C;")
1529+
1530+
let dummyBrokenDylib = path.appending(component: "lib_InternalSwiftScan.dylib")
1531+
try localFileSystem.writeFileContents(dummyBrokenDylib, bytes: "n/a")
1532+
1533+
var environment = ProcessEnv.vars
1534+
environment["SWIFT_DRIVER_SWIFTSCAN_LIB"] = dummyBrokenDylib.nativePathString(escaped: true)
1535+
1536+
let cHeadersPath: AbsolutePath =
1537+
try testInputsPath.appending(component: "ExplicitModuleBuilds")
1538+
.appending(component: "CHeaders")
1539+
let swiftModuleInterfacesPath: AbsolutePath =
1540+
try testInputsPath.appending(component: "ExplicitModuleBuilds")
1541+
.appending(component: "Swift")
1542+
let sdkArgumentsForTesting = (try? Driver.sdkArgumentsForTesting()) ?? []
1543+
var driver = try Driver(args: ["swiftc",
1544+
"-I", cHeadersPath.nativePathString(escaped: true),
1545+
"-I", swiftModuleInterfacesPath.nativePathString(escaped: true),
1546+
"-I", stdlibPath.nativePathString(escaped: true),
1547+
"-I", shimsPath.nativePathString(escaped: true),
1548+
"/tmp/Foo.o",
1549+
"-explicit-module-build",
1550+
"-working-directory", path.nativePathString(escaped: true),
1551+
"-disable-clang-target",
1552+
main.nativePathString(escaped: true)] + sdkArgumentsForTesting,
1553+
env: environment)
1554+
let interModuleDependencyGraph = try driver.performDependencyScan()
1555+
1556+
1557+
print(driver.diagnosticEngine.diagnostics)
1558+
XCTAssertTrue(driver.diagnosticEngine.diagnostics.contains { $0.behavior == .remark &&
1559+
$0.message.text == "In-process dependency scan query failed due to incompatible libSwiftScan (\(dummyBrokenDylib.nativePathString(escaped: true))). Fallback to `swift-frontend` dependency scanner invocation."})
1560+
XCTAssertTrue(interModuleDependencyGraph.mainModule.directDependencies?.contains(where: { $0.moduleName == "C" }))
1561+
}
1562+
}
1563+
15201564
func testParallelDependencyScanningDiagnostics() throws {
15211565
let (stdlibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
15221566
// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across

0 commit comments

Comments
 (0)