Skip to content

[SwiftScan] Add APIs to load/check libSwiftScan directly #1529

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Sources/SwiftDriver/Driver/Driver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,10 @@ public struct Driver {
return supportedFrontendFeatures.contains(feature.rawValue)
}

public func getSwiftScanLibPath() throws -> AbsolutePath? {
return try toolchain.lookupSwiftScanLib()
}

@_spi(Testing)
public static func findBlocklists(RelativeTo execDir: AbsolutePath) throws -> [AbsolutePath] {
// Expect to find all blocklists in such dir:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,23 +77,17 @@ public class InterModuleDependencyOracle {
}

/// Given a specified toolchain path, locate and instantiate an instance of the SwiftScan library
/// Returns True if a library instance exists (either verified or newly-created).
@_spi(Testing) public func verifyOrCreateScannerInstance(fileSystem: FileSystem,
swiftScanLibPath: AbsolutePath)
throws -> Bool {
public func verifyOrCreateScannerInstance(fileSystem: FileSystem,
swiftScanLibPath: AbsolutePath) throws {
return try queue.sync {
if swiftScanLibInstance == nil {
guard fileSystem.exists(swiftScanLibPath) else {
return false
}
swiftScanLibInstance = try SwiftScan(dylib: swiftScanLibPath)
} else {
guard swiftScanLibInstance!.path == swiftScanLibPath else {
throw DependencyScanningError
.scanningLibraryInvocationMismatch(swiftScanLibInstance!.path, swiftScanLibPath)
}
}
return true
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,25 +159,26 @@ public extension Driver {
// If `-nonlib-dependency-scanner` was specified or the libSwiftScan library cannot be found,
// attempt to fallback to using `swift-frontend -scan-dependencies` invocations for dependency
// scanning.
var fallbackToFrontend = parsedOptions.hasArgument(.driverScanDependenciesNonLib)
let optionalScanLibPath = try toolchain.lookupSwiftScanLib()
if let scanLibPath = optionalScanLibPath,
try interModuleDependencyOracle
.verifyOrCreateScannerInstance(fileSystem: fileSystem,
swiftScanLibPath: scanLibPath) == false {
fallbackToFrontend = true
guard !parsedOptions.hasArgument(.driverScanDependenciesNonLib),
let scanLibPath = try toolchain.lookupSwiftScanLib(),
fileSystem.exists(scanLibPath) else {
// This warning is mostly useful for debugging the driver, so let's hide it
// when libSwiftDriver is used, instead of a swift-driver executable.
// when libSwiftDriver is used, instead of a swift-driver executable.
if !integratedDriver {
diagnosticEngine.emit(.warn_scanner_frontend_fallback())
}

return true
}
if !fallbackToFrontend && isCachingEnabled {

try interModuleDependencyOracle.verifyOrCreateScannerInstance(fileSystem: fileSystem,
swiftScanLibPath: scanLibPath)
if isCachingEnabled {
self.cas = try interModuleDependencyOracle.getOrCreateCAS(pluginPath: try getCASPluginPath(),
onDiskPath: try getOnDiskCASPath(),
pluginOptions: try getCASPluginOptions())
}
return fallbackToFrontend
return false
}

static func sanitizeCommandForLibScanInvocation(_ command: inout [String]) {
Expand Down
50 changes: 15 additions & 35 deletions Tests/SwiftDriverTests/CachingBuildTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -499,13 +499,9 @@ final class CachingBuildTests: XCTestCase {
try driver.run(jobs: jobs)
XCTAssertFalse(driver.diagnosticEngine.hasErrors)

let scanLibPath = try XCTUnwrap(driver.toolchain.lookupSwiftScanLib())
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
let scanLibPath = try XCTUnwrap(driver.getSwiftScanLibPath())
try dependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)

let cas = try dependencyOracle.getOrCreateCAS(pluginPath: nil, onDiskPath: casPath, pluginOptions: [])
if let driverCAS = driver.cas {
Expand Down Expand Up @@ -558,13 +554,9 @@ final class CachingBuildTests: XCTestCase {
env: ProcessEnv.vars,
interModuleDependencyOracle: dependencyOracle)

let scanLibPath = try XCTUnwrap(fooBuildDriver.toolchain.lookupSwiftScanLib())
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
let scanLibPath = try XCTUnwrap(fooBuildDriver.getSwiftScanLibPath())
try dependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)
guard try dependencyOracle.supportsBinaryModuleHeaderDependencies() else {
throw XCTSkip("libSwiftScan does not support binary module header dependencies.")
}
Expand Down Expand Up @@ -630,13 +622,9 @@ final class CachingBuildTests: XCTestCase {
main.nativePathString(escaped: true)] + sdkArgumentsForTesting,
env: ProcessEnv.vars,
interModuleDependencyOracle: dependencyOracle)
let scanLibPath = try XCTUnwrap(driver.toolchain.lookupSwiftScanLib())
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
let scanLibPath = try XCTUnwrap(driver.getSwiftScanLibPath())
try dependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)
let resolver = try ArgsResolver(fileSystem: localFileSystem)
var scannerCommand = try driver.dependencyScannerInvocationCommand().1.map { try resolver.resolve($0) }
// We generate full swiftc -frontend -scan-dependencies invocations in order to also be
Expand Down Expand Up @@ -770,13 +758,9 @@ final class CachingBuildTests: XCTestCase {
guard driver.isFrontendArgSupported(.scannerPrefixMap) else {
throw XCTSkip("frontend doesn't support prefix map")
}
let scanLibPath = try XCTUnwrap(driver.toolchain.lookupSwiftScanLib())
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
let scanLibPath = try XCTUnwrap(driver.getSwiftScanLibPath())
try dependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)
let resolver = try ArgsResolver(fileSystem: localFileSystem)
let scannerCommand = try driver.dependencyScannerInvocationCommand().1.map { try resolver.resolve($0) }

Expand Down Expand Up @@ -841,13 +825,9 @@ final class CachingBuildTests: XCTestCase {
try driver.run(jobs: jobs)
XCTAssertFalse(driver.diagnosticEngine.hasErrors)

let scanLibPath = try XCTUnwrap(driver.toolchain.lookupSwiftScanLib())
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
let scanLibPath = try XCTUnwrap(driver.getSwiftScanLibPath())
try dependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)

let cas = try dependencyOracle.getOrCreateCAS(pluginPath: nil, onDiskPath: casPath, pluginOptions: [])
if let driverCAS = driver.cas {
Expand Down
64 changes: 16 additions & 48 deletions Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -903,12 +903,8 @@ final class ExplicitModuleBuildTests: XCTestCase {
// queries.
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
try dependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)

try withTemporaryDirectory { path in
let main = path.appending(component: "foo.swift")
Expand Down Expand Up @@ -1083,12 +1079,8 @@ final class ExplicitModuleBuildTests: XCTestCase {
// 2. Run a dependency scan to find the just-built module
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
try dependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)
guard try dependencyOracle.supportsBinaryFrameworkDependencies() else {
throw XCTSkip("libSwiftScan does not support framework binary dependency reporting.")
}
Expand Down Expand Up @@ -1184,12 +1176,8 @@ final class ExplicitModuleBuildTests: XCTestCase {
// queries.
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
try dependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)

// Create a simple test case.
try withTemporaryDirectory { path in
Expand Down Expand Up @@ -1293,12 +1281,8 @@ final class ExplicitModuleBuildTests: XCTestCase {
// queries.
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
try dependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)
guard try dependencyOracle.supportsScannerDiagnostics() else {
throw XCTSkip("libSwiftScan does not support diagnostics query.")
}
Expand Down Expand Up @@ -1361,12 +1345,8 @@ final class ExplicitModuleBuildTests: XCTestCase {
// queries.
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
try dependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)

// Create a simple test case.
try withTemporaryDirectory { path in
Expand Down Expand Up @@ -1566,12 +1546,8 @@ final class ExplicitModuleBuildTests: XCTestCase {
let (stdlibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
try dependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)
// Create a simple test case.
try withTemporaryDirectory { path in
let main = path.appending(component: "testDependencyScanning.swift")
Expand Down Expand Up @@ -1668,12 +1644,8 @@ final class ExplicitModuleBuildTests: XCTestCase {
let scanLibPath = try XCTUnwrap(toolchain.lookupSwiftScanLib())
// Run the first scan and serialize the cache contents.
let firstDependencyOracle = InterModuleDependencyOracle()
guard try firstDependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
try firstDependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)

let firstScanGraph =
try firstDependencyOracle.getDependencies(workingDirectory: path,
Expand All @@ -1682,12 +1654,8 @@ final class ExplicitModuleBuildTests: XCTestCase {

// Run the second scan, re-using the serialized cache contents.
let secondDependencyOracle = InterModuleDependencyOracle()
guard try secondDependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
XCTFail("Dependency scanner library not found")
return
}
try secondDependencyOracle.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath)
XCTAssertFalse(secondDependencyOracle.loadScannerCache(from: cacheSavePath))
let secondScanGraph =
try secondDependencyOracle.getDependencies(workingDirectory: path,
Expand Down
4 changes: 2 additions & 2 deletions Tests/SwiftDriverTests/SwiftDriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5130,7 +5130,7 @@ final class SwiftDriverTests: XCTestCase {
swiftCompilerPrefixArgs: [])
var printTargetInfoCommand = try Driver.itemizedJobCommand(of: printTargetInfoJob, useResponseFiles: .disabled, using: ArgsResolver(fileSystem: InMemoryFileSystem()))
Driver.sanitizeCommandForLibScanInvocation(&printTargetInfoCommand)
let swiftScanLibPath = try XCTUnwrap(driver.toolchain.lookupSwiftScanLib())
let swiftScanLibPath = try XCTUnwrap(driver.getSwiftScanLibPath())
if localFileSystem.exists(swiftScanLibPath) {
let libSwiftScanInstance = try SwiftScan(dylib: swiftScanLibPath)
if libSwiftScanInstance.canQueryTargetInfo() {
Expand All @@ -5150,7 +5150,7 @@ final class SwiftDriverTests: XCTestCase {
swiftCompilerPrefixArgs: [])
var printTargetInfoCommand = try Driver.itemizedJobCommand(of: printTargetInfoJob, useResponseFiles: .disabled, using: ArgsResolver(fileSystem: InMemoryFileSystem()))
Driver.sanitizeCommandForLibScanInvocation(&printTargetInfoCommand)
let swiftScanLibPath = try XCTUnwrap(driver.toolchain.lookupSwiftScanLib())
let swiftScanLibPath = try XCTUnwrap(driver.getSwiftScanLibPath())
if localFileSystem.exists(swiftScanLibPath) {
let libSwiftScanInstance = try SwiftScan(dylib: swiftScanLibPath)
if libSwiftScanInstance.canQueryTargetInfo() {
Expand Down