Skip to content

Commit b67a70c

Browse files
committed
Improve/fix SDK and platform external plugin path arguments
Improve on the prior implementation of adding SDK and platform external plugin path arguments in a few ways: * Only do this for Darwin, because other platforms don't have similar abstractions at the moment * Fix incorrect paths, because I had not written tests * Add tests, because otherwise nobody should trust this code * Make sure all of the command-line arguments for compiler plugins are passed through to the frontend in the order they were provided * Pass `-load-plugin-library` and `-load-plugin-executable` through to the frontend
1 parent 05c59ab commit b67a70c

File tree

3 files changed

+107
-62
lines changed

3 files changed

+107
-62
lines changed

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

Lines changed: 14 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,6 @@ fileprivate func shouldColorDiagnostics() -> Bool {
2727
return TerminalController.isTTY(stderrStream)
2828
}
2929

30-
extension VirtualPath {
31-
// Given a virtual path pointing into a toolchain/SDK/platform, produce the
32-
// path to `swift-plugin-server`.
33-
fileprivate var pluginServerPath: VirtualPath {
34-
self.appending(components: "usr", "swift-plugin-server")
35-
}
36-
37-
// Given a virtual path pointing into a toolchain/SDK/platform, produce the
38-
// path to the plugins.
39-
fileprivate var pluginPath: VirtualPath {
40-
self.appending(components: "lib", "swift", "host", "plugins")
41-
}
42-
43-
// Given a virtual path pointing into a toolchain/SDK/platform, produce the
44-
// path to the plugins.
45-
fileprivate var localPluginPath: VirtualPath {
46-
self.appending(component: "local").pluginPath
47-
}
48-
}
49-
5030
extension Driver {
5131
/// How the bridging header should be handled.
5232
enum BridgingHeaderHandling {
@@ -283,48 +263,9 @@ extension Driver {
283263

284264
// Emit user-provided plugin paths, in order.
285265
if isFrontendArgSupported(.externalPluginPath) {
286-
try commandLine.appendAll(.pluginPath, .externalPluginPath, from: &parsedOptions)
266+
try commandLine.appendAll(.pluginPath, .externalPluginPath, .loadPluginLibrary, .loadPluginExecutable, from: &parsedOptions)
287267
} else if isFrontendArgSupported(.pluginPath) {
288-
try commandLine.appendAll(.pluginPath, from: &parsedOptions)
289-
}
290-
291-
if isFrontendArgSupported(.externalPluginPath), let sdkPath = frontendTargetInfo.sdkPath?.path {
292-
// Default paths for compiler plugins found within an SDK (accessed via
293-
// that SDK's plugin server).
294-
let sdkPathRoot = VirtualPath.lookup(sdkPath).appending(components: "usr")
295-
commandLine.appendFlag(.externalPluginPath)
296-
commandLine.appendFlag("\(sdkPathRoot.pluginServerPath.name.spm_shellEscaped())#\(sdkPathRoot.pluginPath.name)")
297-
298-
commandLine.appendFlag(.externalPluginPath)
299-
commandLine.appendFlag("\(sdkPathRoot.pluginServerPath.name.spm_shellEscaped())#\(sdkPathRoot.localPluginPath.name)")
300-
301-
// Default paths for compiler plugins within the platform (accessed via that
302-
// platform's plugin server).
303-
let platformPathRoot = VirtualPath.lookup(sdkPath)
304-
.parentDirectory
305-
.parentDirectory
306-
.parentDirectory
307-
.appending(components: "Developer", "usr")
308-
commandLine.appendFlag(.externalPluginPath)
309-
commandLine.appendFlag("\(platformPathRoot.pluginServerPath.name.spm_shellEscaped())#\(platformPathRoot.pluginPath.name)")
310-
311-
commandLine.appendFlag(.externalPluginPath)
312-
commandLine.appendFlag("\(platformPathRoot.pluginServerPath.name.spm_shellEscaped())#\(platformPathRoot.localPluginPath.name)")
313-
}
314-
315-
if isFrontendArgSupported(.pluginPath) {
316-
// Default paths for compiler plugins found within the toolchain
317-
// (loaded as shared libraries).
318-
let pluginPathRoot = VirtualPath.absolute(try toolchain.executableDir.parentDirectory)
319-
commandLine.appendFlag(.pluginPath)
320-
commandLine.appendPath(pluginPathRoot.pluginPath)
321-
322-
commandLine.appendFlag(.pluginPath)
323-
commandLine.appendPath(pluginPathRoot.localPluginPath)
324-
}
325-
326-
if isFrontendArgSupported(.externalPluginPath) {
327-
try commandLine.appendAll(.externalPluginPath, from: &parsedOptions)
268+
try commandLine.appendAll(.pluginPath, .loadPluginLibrary, from: &parsedOptions)
328269
}
329270

330271
if isFrontendArgSupported(.blockListFile) {
@@ -442,6 +383,18 @@ extension Driver {
442383
inputs: &inputs,
443384
frontendTargetInfo: frontendTargetInfo,
444385
driver: &self)
386+
387+
// Platform-agnostic options that need to happen after platform-specific ones.
388+
if isFrontendArgSupported(.pluginPath) {
389+
// Default paths for compiler plugins found within the toolchain
390+
// (loaded as shared libraries).
391+
let pluginPathRoot = VirtualPath.absolute(try toolchain.executableDir.parentDirectory)
392+
commandLine.appendFlag(.pluginPath)
393+
commandLine.appendPath(pluginPathRoot.pluginPath)
394+
395+
commandLine.appendFlag(.pluginPath)
396+
commandLine.appendPath(pluginPathRoot.localPluginPath)
397+
}
445398
}
446399

447400
mutating func addFrontendSupplementaryOutputArguments(commandLine: inout [Job.ArgTemplate],

Sources/SwiftDriver/Toolchains/DarwinToolchain.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,30 @@ public final class DarwinToolchain: Toolchain {
421421
commandLine.appendFlag(.clangTarget)
422422
commandLine.appendFlag(clangTargetTriple)
423423
}
424+
425+
if driver.isFrontendArgSupported(.externalPluginPath) {
426+
// Default paths for compiler plugins found within an SDK (accessed via
427+
// that SDK's plugin server).
428+
let sdkPathRoot = VirtualPath.lookup(sdkPath).appending(components: "usr")
429+
commandLine.appendFlag(.externalPluginPath)
430+
commandLine.appendFlag("\(sdkPathRoot.pluginPath.name)#\(sdkPathRoot.pluginServerPath.name.spm_shellEscaped())")
431+
432+
commandLine.appendFlag(.externalPluginPath)
433+
commandLine.appendFlag("\(sdkPathRoot.localPluginPath.name)#\(sdkPathRoot.pluginServerPath.name.spm_shellEscaped())")
434+
435+
// Default paths for compiler plugins within the platform (accessed via that
436+
// platform's plugin server).
437+
let platformPathRoot = VirtualPath.lookup(sdkPath)
438+
.parentDirectory
439+
.parentDirectory
440+
.parentDirectory
441+
.appending(components: "Developer", "usr")
442+
commandLine.appendFlag(.externalPluginPath)
443+
commandLine.appendFlag("\(platformPathRoot.pluginPath.name)#\(platformPathRoot.pluginServerPath.name.spm_shellEscaped())")
444+
445+
commandLine.appendFlag(.externalPluginPath)
446+
commandLine.appendFlag("\(platformPathRoot.localPluginPath.name)#\(platformPathRoot.pluginServerPath.name.spm_shellEscaped())")
447+
}
424448
}
425449
}
426450

@@ -441,3 +465,23 @@ private extension Version {
441465
return self.description
442466
}
443467
}
468+
469+
extension VirtualPath {
470+
// Given a virtual path pointing into a toolchain/SDK/platform, produce the
471+
// path to `swift-plugin-server`.
472+
fileprivate var pluginServerPath: VirtualPath {
473+
self.appending(components: "bin", "swift-plugin-server")
474+
}
475+
476+
// Given a virtual path pointing into a toolchain/SDK/platform, produce the
477+
// path to the plugins.
478+
var pluginPath: VirtualPath {
479+
self.appending(components: "lib", "swift", "host", "plugins")
480+
}
481+
482+
// Given a virtual path pointing into a toolchain/SDK/platform, produce the
483+
// path to the plugins.
484+
var localPluginPath: VirtualPath {
485+
self.appending(component: "local").pluginPath
486+
}
487+
}

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6799,15 +6799,63 @@ final class SwiftDriverTests: XCTestCase {
67996799

68006800
func testPluginPaths() throws {
68016801
let sdkRoot = testInputsPath.appending(component: "SDKChecks").appending(component: "iPhoneOS.sdk")
6802-
var driver = try Driver(args: ["swiftc", "-typecheck", "foo.swift", "-sdk", VirtualPath.absolute(sdkRoot).name])
6802+
var driver = try Driver(args: ["swiftc", "-typecheck", "foo.swift", "-sdk", VirtualPath.absolute(sdkRoot).name, "-plugin-path", "PluginA", "-external-plugin-path", "PluginB#Bexe", "-load-plugin-library", "PluginB2", "-plugin-path", "PluginC"])
68036803
guard driver.isFrontendArgSupported(.pluginPath) && driver.isFrontendArgSupported(.externalPluginPath) else {
68046804
return
68056805
}
68066806

68076807
let jobs = try driver.planBuild().removingAutolinkExtractJobs()
68086808
XCTAssertEqual(jobs.count, 1)
68096809
let job = jobs.first!
6810+
6811+
// Check that the we have the plugin paths we expect, in the order we expect.
6812+
let pluginAIndex = job.commandLine.firstIndex(of: .path(VirtualPath.relative(.init("PluginA"))))
6813+
XCTAssertNotNil(pluginAIndex)
6814+
6815+
let pluginBIndex = job.commandLine.firstIndex(of: .path(VirtualPath.relative(.init("PluginB#Bexe"))))
6816+
XCTAssertNotNil(pluginBIndex)
6817+
XCTAssertLessThan(pluginAIndex!, pluginBIndex!)
6818+
6819+
let pluginB2Index = job.commandLine.firstIndex(of: .path(VirtualPath.relative(.init("PluginB2"))))
6820+
XCTAssertNotNil(pluginB2Index)
6821+
XCTAssertLessThan(pluginBIndex!, pluginB2Index!)
6822+
6823+
let pluginCIndex = job.commandLine.firstIndex(of: .path(VirtualPath.relative(.init("PluginC"))))
6824+
XCTAssertNotNil(pluginCIndex)
6825+
XCTAssertLessThan(pluginB2Index!, pluginCIndex!)
6826+
6827+
#if os(macOS)
68106828
XCTAssertTrue(job.commandLine.contains(.flag("-external-plugin-path")))
6829+
let sdkServerPath = sdkRoot.appending(components: "usr", "bin", "swift-plugin-server").pathString
6830+
let sdkPluginPath = sdkRoot.appending(components: "usr", "lib", "swift", "host", "plugins").pathString
6831+
6832+
let sdkPluginPathIndex = job.commandLine.firstIndex(of: .flag("\(sdkPluginPath)#\(sdkServerPath)"))
6833+
XCTAssertNotNil(sdkPluginPathIndex)
6834+
XCTAssertLessThan(pluginCIndex!, sdkPluginPathIndex!)
6835+
6836+
let sdkLocalPluginPath = sdkRoot.appending(components: "usr", "local", "lib", "swift", "host", "plugins").pathString
6837+
let sdkLocalPluginPathIndex = job.commandLine.firstIndex(of: .flag("\(sdkLocalPluginPath)#\(sdkServerPath)"))
6838+
XCTAssertNotNil(sdkLocalPluginPathIndex)
6839+
XCTAssertLessThan(sdkPluginPathIndex!, sdkLocalPluginPathIndex!)
6840+
6841+
let platformPath = sdkRoot.parentDirectory.parentDirectory.parentDirectory.appending(components: "Developer", "usr")
6842+
let platformServerPath = platformPath.appending(components: "bin", "swift-plugin-server").pathString
6843+
6844+
let platformPluginPath = platformPath.appending(components: "lib", "swift", "host", "plugins")
6845+
let platformPluginPathIndex = job.commandLine.firstIndex(of: .flag("\(platformPluginPath)#\(platformServerPath)"))
6846+
XCTAssertNotNil(platformPluginPathIndex)
6847+
XCTAssertLessThan(sdkLocalPluginPathIndex!, platformPluginPathIndex!)
6848+
6849+
let platformLocalPluginPath = platformPath.appending(components: "local", "lib", "swift", "host", "plugins")
6850+
let platformLocalPluginPathIndex = job.commandLine.firstIndex(of: .flag("\(platformLocalPluginPath)#\(platformServerPath)"))
6851+
XCTAssertNotNil(platformLocalPluginPathIndex)
6852+
XCTAssertLessThan(platformPluginPathIndex!, platformLocalPluginPathIndex!)
6853+
6854+
let toolchainPluginPathIndex = job.commandLine.firstIndex(of: .path(.absolute(try driver.toolchain.executableDir.parentDirectory.appending(components: "lib", "swift", "host", "plugins"))))
6855+
XCTAssertNotNil(toolchainPluginPathIndex)
6856+
XCTAssertLessThan(platformLocalPluginPathIndex!, toolchainPluginPathIndex!)
6857+
#endif
6858+
68116859
XCTAssertTrue(job.commandLine.contains(.flag("-plugin-path")))
68126860
XCTAssertTrue(job.commandLine.contains(.path(.absolute(try driver.toolchain.executableDir.parentDirectory.appending(components: "lib", "swift", "host", "plugins")))))
68136861
XCTAssertTrue(job.commandLine.contains(.path(.absolute(try driver.toolchain.executableDir.parentDirectory.appending(components: "local", "lib", "swift", "host", "plugins")))))

0 commit comments

Comments
 (0)