diff --git a/Sources/CSwiftScan/include/swiftscan_header.h b/Sources/CSwiftScan/include/swiftscan_header.h index dc5be47ea..54c8be23b 100644 --- a/Sources/CSwiftScan/include/swiftscan_header.h +++ b/Sources/CSwiftScan/include/swiftscan_header.h @@ -193,6 +193,10 @@ typedef struct { void (*swiftscan_scan_invocation_dispose)(swiftscan_scan_invocation_t); + //=== Target Info Functions-------- ---------------------------------------===// + swiftscan_string_ref_t + (*swiftscan_compiler_target_info_query)(swiftscan_scan_invocation_t); + //=== Functionality Query Functions ---------------------------------------===// swiftscan_string_set_t * (*swiftscan_compiler_supported_arguments_query)(void); diff --git a/Sources/SwiftDriver/SwiftScan/SwiftScan.swift b/Sources/SwiftDriver/SwiftScan/SwiftScan.swift index 2df4682f1..2f35e9d18 100644 --- a/Sources/SwiftDriver/SwiftScan/SwiftScan.swift +++ b/Sources/SwiftDriver/SwiftScan/SwiftScan.swift @@ -56,7 +56,7 @@ public enum DependencyScanningError: Error, DiagnosticData { } /// Wrapper for libSwiftScan, taking care of initialization, shutdown, and dispatching dependency scanning queries. -internal final class SwiftScan { +@_spi(Testing) public final class SwiftScan { /// The path to the libSwiftScan dylib. let path: AbsolutePath @@ -251,6 +251,26 @@ internal final class SwiftScan { throw DependencyScanningError.argumentQueryFailed } } + + @_spi(Testing) public func canQueryTargetInfo() -> Bool { + return api.swiftscan_compiler_target_info_query != nil && + api.swiftscan_string_set_dispose != nil + } + + @_spi(Testing) public func queryTargetInfo(invocationCommand: [String]) + throws -> FrontendTargetInfo { + // Create and configure the scanner invocation + let invocation = api.swiftscan_scan_invocation_create() + defer { api.swiftscan_scan_invocation_dispose(invocation) } + withArrayOfCStrings(invocationCommand) { invocationStringArray in + api.swiftscan_scan_invocation_set_argv(invocation, + Int32(invocationCommand.count), + invocationStringArray) + } + let targetInfoString = try toSwiftString(api.swiftscan_compiler_target_info_query(invocation)) + let targetInfoData = Data(targetInfoString.utf8) + return try JSONDecoder().decode(FrontendTargetInfo.self, from: targetInfoData) + } } // Used for testing purposes only @@ -290,6 +310,10 @@ private extension swiftscan_functions_t { self.swiftscan_compiler_supported_features_query = try loadOptional("swiftscan_compiler_supported_features_query") + // Target Info query + self.swiftscan_compiler_target_info_query = + try loadOptional("swiftscan_compiler_target_info_query") + // Dependency scanner serialization/deserialization features self.swiftscan_scanner_cache_serialize = try loadOptional("swiftscan_scanner_cache_serialize") diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index db1abea84..9f80c4dce 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -4649,7 +4649,7 @@ final class SwiftDriverTests: XCTestCase { func testPrintTargetInfo() throws { do { - var driver = try Driver(args: ["swift", "-print-target-info", "-target", "arm64-apple-ios12.0", "-sdk", "bar", "-resource-dir", "baz"]) + var driver = try Driver(args: ["swift", "-print-target-info", "-sdk", "bar", "-resource-dir", "baz"]) let plannedJobs = try driver.planBuild() XCTAssertTrue(plannedJobs.count == 1) let job = plannedJobs[0] @@ -4660,6 +4660,22 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(job.commandLine.contains(.flag("-resource-dir"))) } + do { + let targetInfoArgs = ["-print-target-info", "-sdk", "bar", "-resource-dir", "baz"] + let driver = try Driver(args: ["swift"] + targetInfoArgs) + + let env = ProcessEnv.vars + let swiftScanLibPath = try Driver.getScanLibPath(of: driver.toolchain, + hostTriple: driver.hostTriple, + env: env) + if localFileSystem.exists(swiftScanLibPath) { + let libSwiftScanInstance = try SwiftScan(dylib: swiftScanLibPath) + if libSwiftScanInstance.canQueryTargetInfo() { + let _ = try libSwiftScanInstance.queryTargetInfo(invocationCommand: targetInfoArgs) + } + } + } + do { struct MockExecutor: DriverExecutor { let resolver: ArgsResolver