Skip to content

Commit 3d5347b

Browse files
authored
Merge pull request #1852 from cwakamo/eng/PR-147692019-getSingleFrontendInvocationFromDriverArguments-compilerExecutableDir-arg
Added a new `getSingleFrontendInvocationFromDriverArgumentsV4` function. This variant adds a compilerExecutableDir parameter which gets passed along to the Driver during initialization. This allows callers of getSingleFrontendInvocationFromDriverArgumentsV4 to set a custom compilerExecutableDir, which influences paths passed to the frontend for things like the in-process plugin library. This addresses <rdar://problem/147692019>.
2 parents b4eaebf + fe77491 commit 3d5347b

File tree

2 files changed

+109
-2
lines changed

2 files changed

+109
-2
lines changed

Sources/SwiftDriver/ToolingInterface/ToolingUtil.swift

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import class TSCBasic.ProcessSet
1616
import enum TSCBasic.ProcessEnv
1717
import struct TSCBasic.ProcessEnvironmentBlock
1818
import var TSCBasic.localFileSystem
19+
import struct TSCBasic.AbsolutePath
1920
import SwiftOptions
2021

2122
//typedef enum {
@@ -102,6 +103,18 @@ public func getSingleFrontendInvocationFromDriverArgumentsV2(driverPath: String,
102103
return getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: driverPath, argList: argList, action: action, diagnostics: &diagnostics, diagnosticCallback: diagnosticCallback, env: env, executor: executor, compilerIntegratedTooling: compilerIntegratedTooling, forceNoOutputs: forceNoOutputs)
103104
}
104105

106+
public func getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: String,
107+
argList: [String],
108+
action: ([String]) -> Bool,
109+
diagnostics: inout [Diagnostic],
110+
diagnosticCallback: @escaping (CInt, String) -> Void,
111+
env: [String: String],
112+
executor: some DriverExecutor,
113+
compilerIntegratedTooling: Bool = false,
114+
forceNoOutputs: Bool = false) -> Bool {
115+
return getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: driverPath, argList: argList, action: action, diagnostics: &diagnostics, diagnosticCallback: diagnosticCallback, env: env, executor: executor, compilerIntegratedTooling: compilerIntegratedTooling, compilerExecutableDir: nil, forceNoOutputs: forceNoOutputs)
116+
}
117+
105118
/// Generates the list of arguments that would be passed to the compiler
106119
/// frontend from the given driver arguments, for a single-compiler-invocation
107120
/// context.
@@ -120,14 +133,15 @@ public func getSingleFrontendInvocationFromDriverArgumentsV2(driverPath: String,
120133
///
121134
/// \note This function is not intended to create invocations which are
122135
/// suitable for use in REPL or immediate modes.
123-
public func getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: String,
136+
public func getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: String,
124137
argList: [String],
125138
action: ([String]) -> Bool,
126139
diagnostics: inout [Diagnostic],
127140
diagnosticCallback: @escaping (CInt, String) -> Void,
128141
env: [String: String],
129142
executor: some DriverExecutor,
130143
compilerIntegratedTooling: Bool = false,
144+
compilerExecutableDir: AbsolutePath? = nil,
131145
forceNoOutputs: Bool = false) -> Bool {
132146
/// Handler for emitting diagnostics to tooling clients.
133147
let toolingDiagnosticsHandler: DiagnosticsEngine.DiagnosticsHandler = { diagnostic in
@@ -189,7 +203,8 @@ public func getSingleFrontendInvocationFromDriverArgumentsV3(driverPath: String,
189203
env: env,
190204
diagnosticsOutput: .engine(diagnosticsEngine),
191205
executor: executor,
192-
compilerIntegratedTooling: compilerIntegratedTooling)
206+
compilerIntegratedTooling: compilerIntegratedTooling,
207+
compilerExecutableDir: compilerExecutableDir)
193208
if diagnosticsEngine.hasErrors {
194209
return true
195210
}

Tests/SwiftDriverTests/SwiftDriverToolingInterfaceTests.swift

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,98 @@ final class SwiftDriverToolingInterfaceTests: XCTestCase {
186186
}
187187
}
188188

189+
func testCreateCompilerInvocationV4() throws {
190+
try withTemporaryDirectory { path in
191+
let inputFile = path.appending(components: "test.swift")
192+
try localFileSystem.writeFileContents(inputFile) { $0.send("public func foo()") }
193+
194+
let env = ProcessEnv.vars
195+
let resolver = try ArgsResolver(fileSystem: localFileSystem)
196+
let executor = SimpleExecutor(resolver: resolver, fileSystem: localFileSystem, env: env)
197+
198+
// Expected success scenarios:
199+
do {
200+
let testCommand = inputFile.description
201+
var emittedDiagnostics: [Diagnostic] = []
202+
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
203+
argList: testCommand.components(separatedBy: " "),
204+
action: { _ in false },
205+
diagnostics: &emittedDiagnostics,
206+
diagnosticCallback: {_,_ in },
207+
env: env,
208+
executor: executor))
209+
}
210+
do {
211+
let testCommand = "-emit-executable " + inputFile.description + " main.swift lib.swift -module-name createCompilerInvocation -emit-module -emit-objc-header -o t.out"
212+
var emittedDiagnostics: [Diagnostic] = []
213+
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
214+
argList: testCommand.components(separatedBy: " "),
215+
action: { _ in false },
216+
diagnostics: &emittedDiagnostics,
217+
diagnosticCallback: {_,_ in },
218+
env: env,
219+
executor: executor))
220+
}
221+
do {
222+
let testCommand = "-c " + inputFile.description + " main.swift lib.swift -module-name createCompilerInvocation -emit-module -emit-objc-header"
223+
var emittedDiagnostics: [Diagnostic] = []
224+
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
225+
argList: testCommand.components(separatedBy: " "),
226+
action: { _ in false },
227+
diagnostics: &emittedDiagnostics,
228+
diagnosticCallback: {_,_ in },
229+
env: env,
230+
executor: executor))
231+
}
232+
do {
233+
let testCommand = inputFile.description + " -enable-batch-mode"
234+
var emittedDiagnostics: [Diagnostic] = []
235+
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
236+
argList: testCommand.components(separatedBy: " "),
237+
action: { _ in false },
238+
diagnostics: &emittedDiagnostics,
239+
diagnosticCallback: {_,_ in },
240+
env: env,
241+
executor: executor))
242+
}
243+
do { // Force no outputs
244+
let testCommand = "-module-name foo -emit-module -emit-module-path /tmp/foo.swiftmodule -emit-objc-header -emit-objc-header-path /tmp/foo.h -enable-library-evolution -emit-module-interface -emit-module-interface-path /tmp/foo.swiftinterface -emit-library -emit-tbd -emit-tbd-path /tmp/foo.tbd -emit-dependencies -serialize-diagnostics " + inputFile.description
245+
var resultingFrontendArgs: [String] = []
246+
var emittedDiagnostics: [Diagnostic] = []
247+
XCTAssertFalse(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
248+
argList: testCommand.components(separatedBy: " "),
249+
action: { args in
250+
resultingFrontendArgs = args
251+
return false
252+
},
253+
diagnostics: &emittedDiagnostics,
254+
diagnosticCallback: {_,_ in },
255+
env: env,
256+
executor: executor,
257+
forceNoOutputs: true))
258+
XCTAssertFalse(resultingFrontendArgs.contains("-emit-module-interface-path"))
259+
XCTAssertFalse(resultingFrontendArgs.contains("-emit-objc-header"))
260+
XCTAssertFalse(resultingFrontendArgs.contains("-emit-objc-header-path"))
261+
XCTAssertFalse(resultingFrontendArgs.contains("-emit-module-path"))
262+
XCTAssertFalse(resultingFrontendArgs.contains("-emit-tbd-path"))
263+
}
264+
265+
// Expected failure scenarios:
266+
do {
267+
let testCommand = "-v" // No inputs
268+
var emittedDiagnostics: [Diagnostic] = []
269+
XCTAssertTrue(getSingleFrontendInvocationFromDriverArgumentsV4(driverPath: "swiftc",
270+
argList: testCommand.components(separatedBy: " "),
271+
action: { _ in false },
272+
diagnostics: &emittedDiagnostics,
273+
diagnosticCallback: {_,_ in },
274+
env: env,
275+
executor: executor))
276+
let errorMessage = try XCTUnwrap(emittedDiagnostics.first?.message.text)
277+
XCTAssertEqual(errorMessage, "unable to handle compilation, expected exactly one frontend job")
278+
}
279+
}
280+
}
189281

190282
func testCreateCompilerInvocationCAPI() throws {
191283
try withTemporaryDirectory { path in

0 commit comments

Comments
 (0)