From f9e905d6ab263a9d4562ddaef23cd2dd704294d9 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Wed, 18 Jan 2023 13:27:52 -0800 Subject: [PATCH 1/2] Add capability to query '-print-target-info' in-process using libSwiftScan API --- Sources/CSwiftScan/include/swiftscan_header.h | 6 ++ Sources/SwiftDriver/Driver/Driver.swift | 23 ++++- .../Execution/DriverExecutor.swift | 1 + .../ModuleDependencyScanning.swift | 30 +++---- .../SwiftDriver/Jobs/PrintTargetInfoJob.swift | 84 +++++++++++++++++++ Sources/SwiftDriver/SwiftScan/SwiftScan.swift | 42 +++++++++- Tests/SwiftDriverTests/SwiftDriverTests.swift | 19 +++++ Tests/TestUtilities/DriverExtensions.swift | 12 +++ 8 files changed, 200 insertions(+), 17 deletions(-) diff --git a/Sources/CSwiftScan/include/swiftscan_header.h b/Sources/CSwiftScan/include/swiftscan_header.h index 36c075baa..2cc8316bd 100644 --- a/Sources/CSwiftScan/include/swiftscan_header.h +++ b/Sources/CSwiftScan/include/swiftscan_header.h @@ -193,6 +193,8 @@ typedef struct { //=== Cleanup Functions ---------------------------------------------------===// void + (*swiftscan_string_dispose)(swiftscan_string_ref_t); + void (*swiftscan_string_set_dispose)(swiftscan_string_set_t *); void (*swiftscan_dependency_graph_dispose)(swiftscan_dependency_graph_t); @@ -207,6 +209,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/Driver/Driver.swift b/Sources/SwiftDriver/Driver/Driver.swift index 07e77a9d8..6d2628f05 100644 --- a/Sources/SwiftDriver/Driver/Driver.swift +++ b/Sources/SwiftDriver/Driver/Driver.swift @@ -137,7 +137,7 @@ public struct Driver { public let integratedDriver: Bool /// The file system which we should interact with. - let fileSystem: FileSystem + @_spi(Testing) public let fileSystem: FileSystem /// Diagnostic engine for emitting warnings, errors, etc. public let diagnosticEngine: DiagnosticsEngine @@ -522,12 +522,15 @@ public struct Driver { compilerMode: self.compilerMode, env: env, executor: self.executor, fileSystem: fileSystem, useStaticResourceDir: self.useStaticResourceDir, + workingDirectory: self.workingDirectory, compilerExecutableDir: compilerExecutableDir) // Compute the host machine's triple self.hostTriple = try Self.computeHostTriple(&self.parsedOptions, diagnosticsEngine: diagnosticEngine, toolchain: self.toolchain, executor: self.executor, + fileSystem: fileSystem, + workingDirectory: self.workingDirectory, swiftCompilerPrefixArgs: self.swiftCompilerPrefixArgs) // Classify and collect all of the input files. @@ -2896,6 +2899,8 @@ extension Driver { diagnosticsEngine: DiagnosticsEngine, toolchain: Toolchain, executor: DriverExecutor, + fileSystem: FileSystem, + workingDirectory: AbsolutePath?, swiftCompilerPrefixArgs: [String]) throws -> Triple { let frontendOverride = try FrontendOverride(&parsedOptions, diagnosticsEngine) @@ -2908,6 +2913,11 @@ extension Driver { capturingJSONOutputAs: FrontendTargetInfo.self, forceResponseFiles: false, recordedInputModificationDates: [:]).target.triple +// return try Self.computeTargetInfo(target: nil, targetVariant: nil, +// swiftCompilerPrefixArgs: frontendOverride.prefixArgsForTargetInfo, +// toolchain: toolchain, fileSystem: fileSystem, +// workingDirectory: workingDirectory, +// executor: executor).target.triple } static func computeToolchain( @@ -2918,6 +2928,7 @@ extension Driver { executor: DriverExecutor, fileSystem: FileSystem, useStaticResourceDir: Bool, + workingDirectory: AbsolutePath?, compilerExecutableDir: AbsolutePath? ) throws -> (Toolchain, FrontendTargetInfo, [String]) { let explicitTarget = (parsedOptions.getLastArgument(.target)?.asSingle) @@ -2973,6 +2984,16 @@ extension Driver { capturingJSONOutputAs: FrontendTargetInfo.self, forceResponseFiles: false, recordedInputModificationDates: [:]) +// var info: FrontendTargetInfo = +// try Self.computeTargetInfo(target: explicitTarget, targetVariant: explicitTargetVariant, +// sdkPath: sdkPath, resourceDirPath: resourceDirPath, +// runtimeCompatibilityVersion: +// parsedOptions.getLastArgument(.runtimeCompatibilityVersion)?.asSingle, +// useStaticResourceDir: useStaticResourceDir, +// swiftCompilerPrefixArgs: frontendOverride.prefixArgsForTargetInfo, +// toolchain: toolchain, fileSystem: fileSystem, +// workingDirectory: workingDirectory, +// executor: executor) // Parse the runtime compatibility version. If present, it will override // what is reported by the frontend. diff --git a/Sources/SwiftDriver/Execution/DriverExecutor.swift b/Sources/SwiftDriver/Execution/DriverExecutor.swift index dc5d9ff09..098f91a64 100644 --- a/Sources/SwiftDriver/Execution/DriverExecutor.swift +++ b/Sources/SwiftDriver/Execution/DriverExecutor.swift @@ -87,6 +87,7 @@ extension DriverExecutor { capturingJSONOutputAs outputType: T.Type, forceResponseFiles: Bool, recordedInputModificationDates: [TypedVirtualPath: TimePoint]) throws -> T { + //print(">>> EXEC: \(try self.description(of: job, forceResponseFiles: false))") let result = try execute(job: job, forceResponseFiles: forceResponseFiles, recordedInputModificationDates: recordedInputModificationDates) diff --git a/Sources/SwiftDriver/ExplicitModuleBuilds/ModuleDependencyScanning.swift b/Sources/SwiftDriver/ExplicitModuleBuilds/ModuleDependencyScanning.swift index 622c7e079..9d1e5681e 100644 --- a/Sources/SwiftDriver/ExplicitModuleBuilds/ModuleDependencyScanning.swift +++ b/Sources/SwiftDriver/ExplicitModuleBuilds/ModuleDependencyScanning.swift @@ -236,7 +236,7 @@ public extension Driver { return fallbackToFrontend } - private func sanitizeCommandForLibScanInvocation(_ command: inout [String]) { + static func sanitizeCommandForLibScanInvocation(_ command: inout [String]) { // Remove the tool executable to only leave the arguments. When passing the // command line into libSwiftScan, the library is itself the tool and only // needs to parse the remaining arguments. @@ -257,10 +257,10 @@ public extension Driver { let isSwiftScanLibAvailable = !(try initSwiftScanLib()) if isSwiftScanLibAvailable { let cwd = workingDirectory ?? fileSystem.currentWorkingDirectory! - var command = try itemizedJobCommand(of: preScanJob, - useResponseFiles: .disabled, - using: executor.resolver) - sanitizeCommandForLibScanInvocation(&command) + var command = try Self.itemizedJobCommand(of: preScanJob, + useResponseFiles: .disabled, + using: executor.resolver) + Self.sanitizeCommandForLibScanInvocation(&command) imports = try interModuleDependencyOracle.getImports(workingDirectory: cwd, moduleAliases: moduleOutputInfo.aliases, @@ -293,10 +293,10 @@ public extension Driver { let isSwiftScanLibAvailable = !(try initSwiftScanLib()) if isSwiftScanLibAvailable { let cwd = workingDirectory ?? fileSystem.currentWorkingDirectory! - var command = try itemizedJobCommand(of: scannerJob, - useResponseFiles: .disabled, - using: executor.resolver) - sanitizeCommandForLibScanInvocation(&command) + var command = try Self.itemizedJobCommand(of: scannerJob, + useResponseFiles: .disabled, + using: executor.resolver) + Self.sanitizeCommandForLibScanInvocation(&command) dependencyGraph = try interModuleDependencyOracle.getDependencies(workingDirectory: cwd, moduleAliases: moduleOutputInfo.aliases, @@ -339,10 +339,10 @@ public extension Driver { let isSwiftScanLibAvailable = !(try initSwiftScanLib()) if isSwiftScanLibAvailable { let cwd = workingDirectory ?? fileSystem.currentWorkingDirectory! - var command = try itemizedJobCommand(of: batchScanningJob, - useResponseFiles: .disabled, - using: executor.resolver) - sanitizeCommandForLibScanInvocation(&command) + var command = try Self.itemizedJobCommand(of: batchScanningJob, + useResponseFiles: .disabled, + using: executor.resolver) + Self.sanitizeCommandForLibScanInvocation(&command) moduleVersionedGraphMap = try interModuleDependencyOracle.getBatchDependencies(workingDirectory: cwd, moduleAliases: moduleOutputInfo.aliases, @@ -485,8 +485,8 @@ public extension Driver { contents) } - fileprivate func itemizedJobCommand(of job: Job, useResponseFiles: ResponseFileHandling, - using resolver: ArgsResolver) throws -> [String] { + static func itemizedJobCommand(of job: Job, useResponseFiles: ResponseFileHandling, + using resolver: ArgsResolver) throws -> [String] { let (args, _) = try resolver.resolveArgumentList(for: job, useResponseFiles: useResponseFiles) return args diff --git a/Sources/SwiftDriver/Jobs/PrintTargetInfoJob.swift b/Sources/SwiftDriver/Jobs/PrintTargetInfoJob.swift index a5ff3723b..431899859 100644 --- a/Sources/SwiftDriver/Jobs/PrintTargetInfoJob.swift +++ b/Sources/SwiftDriver/Jobs/PrintTargetInfoJob.swift @@ -10,6 +10,10 @@ // //===----------------------------------------------------------------------===// +import protocol TSCBasic.FileSystem +import class Foundation.JSONDecoder +import struct TSCBasic.AbsolutePath + /// Swift versions are major.minor. struct SwiftVersion { var major: Int @@ -173,3 +177,83 @@ extension Toolchain { ) } } + +extension Driver { + @_spi(Testing) public static func queryTargetInfoInProcess(of toolchain: Toolchain, + fileSystem: FileSystem, + workingDirectory: AbsolutePath?, + invocationCommand: [String]) throws -> FrontendTargetInfo? { + let optionalSwiftScanLibPath = try toolchain.lookupSwiftScanLib() + if let swiftScanLibPath = optionalSwiftScanLibPath, + fileSystem.exists(swiftScanLibPath) { + let libSwiftScanInstance = try SwiftScan(dylib: swiftScanLibPath) + if libSwiftScanInstance.canQueryTargetInfo() { + let cwd = workingDirectory ?? fileSystem.currentWorkingDirectory! + let targetInfoData = + try libSwiftScanInstance.queryTargetInfoJSON(workingDirectory: cwd, + invocationCommand: invocationCommand) + do { + return try JSONDecoder().decode(FrontendTargetInfo.self, from: targetInfoData) + } catch let decodingError as DecodingError { + let stringToDecode = String(data: targetInfoData, encoding: .utf8) + let errorDesc: String + switch decodingError { + case let .typeMismatch(type, context): + errorDesc = "type mismatch: \(type), path: \(context.codingPath)" + case let .valueNotFound(type, context): + errorDesc = "value missing: \(type), path: \(context.codingPath)" + case let .keyNotFound(key, context): + errorDesc = "key missing: \(key), path: \(context.codingPath)" + case let .dataCorrupted(context): + errorDesc = "data corrupted at path: \(context.codingPath)" + @unknown default: + errorDesc = "unknown decoding error" + } + throw Error.unableToDecodeFrontendTargetInfo( + stringToDecode, + invocationCommand, + errorDesc) + } + } + } + return nil + } + + static func computeTargetInfo(target: Triple?, + targetVariant: Triple?, + sdkPath: VirtualPath? = nil, + resourceDirPath: VirtualPath? = nil, + runtimeCompatibilityVersion: String? = nil, + requiresInPlaceExecution: Bool = false, + useStaticResourceDir: Bool = false, + swiftCompilerPrefixArgs: [String], + toolchain: Toolchain, + fileSystem: FileSystem, + workingDirectory: AbsolutePath?, + executor: DriverExecutor) throws -> FrontendTargetInfo { + let frontendTargetInfoJob = + try toolchain.printTargetInfoJob(target: target, targetVariant: targetVariant, + sdkPath: sdkPath, resourceDirPath: resourceDirPath, + runtimeCompatibilityVersion: runtimeCompatibilityVersion, + requiresInPlaceExecution: requiresInPlaceExecution, + useStaticResourceDir: useStaticResourceDir, + swiftCompilerPrefixArgs: swiftCompilerPrefixArgs) + var command = try Self.itemizedJobCommand(of: frontendTargetInfoJob, + useResponseFiles: .disabled, + using: executor.resolver) + Self.sanitizeCommandForLibScanInvocation(&command) + if let targetInfo = + try Self.queryTargetInfoInProcess(of: toolchain, fileSystem: fileSystem, + workingDirectory: workingDirectory, + invocationCommand: command) { + return targetInfo + } + + // Fallback: Invoke `swift-frontend -print-target-info` and decode the output + return try executor.execute( + job: frontendTargetInfoJob, + capturingJSONOutputAs: FrontendTargetInfo.self, + forceResponseFiles: false, + recordedInputModificationDates: [:]) + } +} diff --git a/Sources/SwiftDriver/SwiftScan/SwiftScan.swift b/Sources/SwiftDriver/SwiftScan/SwiftScan.swift index f68479469..8ebf0a8b0 100644 --- a/Sources/SwiftDriver/SwiftScan/SwiftScan.swift +++ b/Sources/SwiftDriver/SwiftScan/SwiftScan.swift @@ -14,6 +14,8 @@ import func Foundation.strdup import func Foundation.free +import class Foundation.JSONDecoder +import struct Foundation.Data import protocol TSCBasic.DiagnosticData import struct TSCBasic.AbsolutePath @@ -80,7 +82,7 @@ internal extension swiftscan_diagnostic_severity_t { } /// 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 @@ -269,6 +271,10 @@ internal final class SwiftScan { api.swiftscan_diagnostic_get_severity != nil && api.swiftscan_diagnostics_set_dispose != nil } + + @_spi(Testing) public func supportsStringDispose() -> Bool { + return api.swiftscan_string_dispose != nil + } @_spi(Testing) public func queryScannerDiagnostics() throws -> [ScannerDiagnosticPayload] { var result: [ScannerDiagnosticPayload] = [] @@ -311,6 +317,34 @@ 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 + } + + func queryTargetInfoJSON(workingDirectory: AbsolutePath, + invocationCommand: [String]) throws -> Data { + // Create and configure the scanner invocation + let invocation = api.swiftscan_scan_invocation_create() + defer { api.swiftscan_scan_invocation_dispose(invocation) } + api.swiftscan_scan_invocation_set_working_directory(invocation, + workingDirectory + .description + .cString(using: String.Encoding.utf8)) + withArrayOfCStrings(invocationCommand) { invocationStringArray in + api.swiftscan_scan_invocation_set_argv(invocation, + Int32(invocationCommand.count), + invocationStringArray) + } + let targetInfoStringRef = api.swiftscan_compiler_target_info_query(invocation) + let targetInfoString = try toSwiftString(targetInfoStringRef) + if supportsStringDispose() { + api.swiftscan_string_dispose(targetInfoStringRef) + } + let targetInfoData = Data(targetInfoString.utf8) + return targetInfoData + } } // Used for testing purposes only @@ -347,6 +381,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") @@ -370,6 +408,8 @@ private extension swiftscan_functions_t { try loadOptional("swiftscan_diagnostic_get_severity") self.swiftscan_diagnostics_set_dispose = try loadOptional("swiftscan_diagnostics_set_dispose") + self.swiftscan_string_dispose = + try loadOptional("swiftscan_string_dispose") // isFramework on binary module dependencies self.swiftscan_swift_binary_detail_get_is_framework = diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index b5018dd58..9bb204bbd 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -4781,6 +4781,21 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(job.commandLine.contains(.flag("-resource-dir"))) } + // In-process query + do { + let targetInfoArgs = ["-print-target-info", "-sdk", "bar", "-resource-dir", "baz"] + let driver = try Driver(args: ["swift"] + targetInfoArgs) + let swiftScanLibPath = try XCTUnwrap(driver.toolchain.lookupSwiftScanLib()) + if localFileSystem.exists(swiftScanLibPath) { + let libSwiftScanInstance = try SwiftScan(dylib: swiftScanLibPath) + if libSwiftScanInstance.canQueryTargetInfo() { + XCTAssertTrue(try driver.verifyBeingAbleToQueryTargetInfoInProcess(workingDirectory: localFileSystem.currentWorkingDirectory, + invocationCommand: targetInfoArgs)) + } + } + + } + do { struct MockExecutor: DriverExecutor { let resolver: ArgsResolver @@ -4803,7 +4818,11 @@ final class SwiftDriverTests: XCTestCase { } } + // Override path to libSwiftScan to force the fallback of using the executor + var hideSwiftScanEnv = ProcessEnv.vars + hideSwiftScanEnv["SWIFT_DRIVER_SWIFTSCAN_LIB"] = "/bad/path/lib_InternalSwiftScan.dylib" XCTAssertThrowsError(try Driver(args: ["swift", "-print-target-info"], + env: hideSwiftScanEnv, executor: MockExecutor(resolver: ArgsResolver(fileSystem: InMemoryFileSystem())))) { error in if case .unableToDecodeFrontendTargetInfo = error as? Driver.Error {} diff --git a/Tests/TestUtilities/DriverExtensions.swift b/Tests/TestUtilities/DriverExtensions.swift index 595b2365e..9d9d18cfa 100644 --- a/Tests/TestUtilities/DriverExtensions.swift +++ b/Tests/TestUtilities/DriverExtensions.swift @@ -42,6 +42,18 @@ extension Driver { public static func sdkArgumentsForTesting() throws -> [String]? { try cachedSDKPath.map {["-sdk", try $0.get()]} } + + + public func verifyBeingAbleToQueryTargetInfoInProcess(workingDirectory: AbsolutePath?, + invocationCommand: [String]) throws -> Bool { + guard try Self.queryTargetInfoInProcess(of: toolchain, + fileSystem: fileSystem, + workingDirectory: workingDirectory, + invocationCommand: invocationCommand) != nil else { + return false + } + return true + } } /// Set to nil if cannot perform on this host From dc63facf83631b3e6462b5de5f7cad44659b7c7b Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Fri, 20 Jan 2023 09:39:23 -0800 Subject: [PATCH 2/2] Switch over to using V2 of the swiftscan_compiler_target_info_query API This new version takes the path to the compiler executable as a parameter, in order for libSwiftScan to compute compiler-relative portions of runtimeLibraryPaths, runtimeResourcePath, etc. --- Sources/CSwiftScan/include/swiftscan_header.h | 3 +- Sources/SwiftDriver/Driver/Driver.swift | 49 ++++++------------- .../Execution/DriverExecutor.swift | 1 - .../SwiftDriver/Jobs/PrintTargetInfoJob.swift | 4 +- Sources/SwiftDriver/SwiftScan/SwiftScan.swift | 17 ++++--- 5 files changed, 30 insertions(+), 44 deletions(-) diff --git a/Sources/CSwiftScan/include/swiftscan_header.h b/Sources/CSwiftScan/include/swiftscan_header.h index 2cc8316bd..3505cd8db 100644 --- a/Sources/CSwiftScan/include/swiftscan_header.h +++ b/Sources/CSwiftScan/include/swiftscan_header.h @@ -211,7 +211,8 @@ typedef struct { //=== Target Info Functions-------- ---------------------------------------===// swiftscan_string_ref_t - (*swiftscan_compiler_target_info_query)(swiftscan_scan_invocation_t); + (*swiftscan_compiler_target_info_query_v2)(swiftscan_scan_invocation_t, + const char *); //=== Functionality Query Functions ---------------------------------------===// swiftscan_string_set_t * diff --git a/Sources/SwiftDriver/Driver/Driver.swift b/Sources/SwiftDriver/Driver/Driver.swift index 6d2628f05..131e321c1 100644 --- a/Sources/SwiftDriver/Driver/Driver.swift +++ b/Sources/SwiftDriver/Driver/Driver.swift @@ -2906,18 +2906,11 @@ extension Driver { let frontendOverride = try FrontendOverride(&parsedOptions, diagnosticsEngine) frontendOverride.setUpForTargetInfo(toolchain) defer { frontendOverride.setUpForCompilation(toolchain) } - return try executor.execute( - job: toolchain.printTargetInfoJob(target: nil, targetVariant: nil, - swiftCompilerPrefixArgs: - frontendOverride.prefixArgsForTargetInfo), - capturingJSONOutputAs: FrontendTargetInfo.self, - forceResponseFiles: false, - recordedInputModificationDates: [:]).target.triple -// return try Self.computeTargetInfo(target: nil, targetVariant: nil, -// swiftCompilerPrefixArgs: frontendOverride.prefixArgsForTargetInfo, -// toolchain: toolchain, fileSystem: fileSystem, -// workingDirectory: workingDirectory, -// executor: executor).target.triple + return try Self.computeTargetInfo(target: nil, targetVariant: nil, + swiftCompilerPrefixArgs: frontendOverride.prefixArgsForTargetInfo, + toolchain: toolchain, fileSystem: fileSystem, + workingDirectory: workingDirectory, + executor: executor).target.triple } static func computeToolchain( @@ -2972,28 +2965,16 @@ extension Driver { // Query the frontend for target information. do { - var info: FrontendTargetInfo = try executor.execute( - job: toolchain.printTargetInfoJob( - target: explicitTarget, targetVariant: explicitTargetVariant, - sdkPath: sdkPath, resourceDirPath: resourceDirPath, - runtimeCompatibilityVersion: - parsedOptions.getLastArgument(.runtimeCompatibilityVersion)?.asSingle, - useStaticResourceDir: useStaticResourceDir, - swiftCompilerPrefixArgs: frontendOverride.prefixArgsForTargetInfo - ), - capturingJSONOutputAs: FrontendTargetInfo.self, - forceResponseFiles: false, - recordedInputModificationDates: [:]) -// var info: FrontendTargetInfo = -// try Self.computeTargetInfo(target: explicitTarget, targetVariant: explicitTargetVariant, -// sdkPath: sdkPath, resourceDirPath: resourceDirPath, -// runtimeCompatibilityVersion: -// parsedOptions.getLastArgument(.runtimeCompatibilityVersion)?.asSingle, -// useStaticResourceDir: useStaticResourceDir, -// swiftCompilerPrefixArgs: frontendOverride.prefixArgsForTargetInfo, -// toolchain: toolchain, fileSystem: fileSystem, -// workingDirectory: workingDirectory, -// executor: executor) + var info: FrontendTargetInfo = + try Self.computeTargetInfo(target: explicitTarget, targetVariant: explicitTargetVariant, + sdkPath: sdkPath, resourceDirPath: resourceDirPath, + runtimeCompatibilityVersion: + parsedOptions.getLastArgument(.runtimeCompatibilityVersion)?.asSingle, + useStaticResourceDir: useStaticResourceDir, + swiftCompilerPrefixArgs: frontendOverride.prefixArgsForTargetInfo, + toolchain: toolchain, fileSystem: fileSystem, + workingDirectory: workingDirectory, + executor: executor) // Parse the runtime compatibility version. If present, it will override // what is reported by the frontend. diff --git a/Sources/SwiftDriver/Execution/DriverExecutor.swift b/Sources/SwiftDriver/Execution/DriverExecutor.swift index 098f91a64..dc5d9ff09 100644 --- a/Sources/SwiftDriver/Execution/DriverExecutor.swift +++ b/Sources/SwiftDriver/Execution/DriverExecutor.swift @@ -87,7 +87,6 @@ extension DriverExecutor { capturingJSONOutputAs outputType: T.Type, forceResponseFiles: Bool, recordedInputModificationDates: [TypedVirtualPath: TimePoint]) throws -> T { - //print(">>> EXEC: \(try self.description(of: job, forceResponseFiles: false))") let result = try execute(job: job, forceResponseFiles: forceResponseFiles, recordedInputModificationDates: recordedInputModificationDates) diff --git a/Sources/SwiftDriver/Jobs/PrintTargetInfoJob.swift b/Sources/SwiftDriver/Jobs/PrintTargetInfoJob.swift index 431899859..a903175aa 100644 --- a/Sources/SwiftDriver/Jobs/PrintTargetInfoJob.swift +++ b/Sources/SwiftDriver/Jobs/PrintTargetInfoJob.swift @@ -188,9 +188,11 @@ extension Driver { fileSystem.exists(swiftScanLibPath) { let libSwiftScanInstance = try SwiftScan(dylib: swiftScanLibPath) if libSwiftScanInstance.canQueryTargetInfo() { - let cwd = workingDirectory ?? fileSystem.currentWorkingDirectory! + let cwd = try workingDirectory ?? fileSystem.currentWorkingDirectory ?? fileSystem.tempDirectory + let compilerExecutablePath = try toolchain.resolvedTool(.swiftCompiler).path let targetInfoData = try libSwiftScanInstance.queryTargetInfoJSON(workingDirectory: cwd, + compilerExecutablePath: compilerExecutablePath, invocationCommand: invocationCommand) do { return try JSONDecoder().decode(FrontendTargetInfo.self, from: targetInfoData) diff --git a/Sources/SwiftDriver/SwiftScan/SwiftScan.swift b/Sources/SwiftDriver/SwiftScan/SwiftScan.swift index 8ebf0a8b0..7e5d04fac 100644 --- a/Sources/SwiftDriver/SwiftScan/SwiftScan.swift +++ b/Sources/SwiftDriver/SwiftScan/SwiftScan.swift @@ -319,11 +319,12 @@ internal extension swiftscan_diagnostic_severity_t { } @_spi(Testing) public func canQueryTargetInfo() -> Bool { - return api.swiftscan_compiler_target_info_query != nil && + return api.swiftscan_compiler_target_info_query_v2 != nil && api.swiftscan_string_set_dispose != nil } func queryTargetInfoJSON(workingDirectory: AbsolutePath, + compilerExecutablePath: AbsolutePath, invocationCommand: [String]) throws -> Data { // Create and configure the scanner invocation let invocation = api.swiftscan_scan_invocation_create() @@ -337,11 +338,13 @@ internal extension swiftscan_diagnostic_severity_t { Int32(invocationCommand.count), invocationStringArray) } - let targetInfoStringRef = api.swiftscan_compiler_target_info_query(invocation) - let targetInfoString = try toSwiftString(targetInfoStringRef) - if supportsStringDispose() { - api.swiftscan_string_dispose(targetInfoStringRef) + + let targetInfoString: String = try compilerExecutablePath.description.withCString { cstring in + let targetInfoStringRef = api.swiftscan_compiler_target_info_query_v2(invocation, cstring) + defer { api.swiftscan_string_dispose(targetInfoStringRef) } + return try toSwiftString(targetInfoStringRef) } + let targetInfoData = Data(targetInfoString.utf8) return targetInfoData } @@ -382,8 +385,8 @@ private extension swiftscan_functions_t { try loadOptional("swiftscan_compiler_supported_features_query") // Target Info query - self.swiftscan_compiler_target_info_query = - try loadOptional("swiftscan_compiler_target_info_query") + self.swiftscan_compiler_target_info_query_v2 = + try loadOptional("swiftscan_compiler_target_info_query_v2") // Dependency scanner serialization/deserialization features self.swiftscan_scanner_cache_serialize =