Skip to content

Commit

Permalink
Merge pull request #1377 from DougGregor/executable-plugin-paths
Browse files Browse the repository at this point in the history
Add SDK and platform paths to plugin executables
  • Loading branch information
DougGregor committed Jun 16, 2023
2 parents 9e78be1 + b67a70c commit 99d316a
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 17 deletions.
31 changes: 16 additions & 15 deletions Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift
Expand Up @@ -261,22 +261,11 @@ extension Driver {
try commandLine.appendLast(.emitMacroExpansionFiles, from: &parsedOptions)
}

if isFrontendArgSupported(.pluginPath) {
try commandLine.appendAll(.pluginPath, from: &parsedOptions)

let defaultPluginPath = try toolchain.executableDir.parentDirectory
.appending(components: "lib", "swift", "host", "plugins")
commandLine.appendFlag(.pluginPath)
commandLine.appendPath(defaultPluginPath)

let localPluginPath = try toolchain.executableDir.parentDirectory
.appending(components: "local", "lib", "swift", "host", "plugins")
commandLine.appendFlag(.pluginPath)
commandLine.appendPath(localPluginPath)
}

// Emit user-provided plugin paths, in order.
if isFrontendArgSupported(.externalPluginPath) {
try commandLine.appendAll(.externalPluginPath, from: &parsedOptions)
try commandLine.appendAll(.pluginPath, .externalPluginPath, .loadPluginLibrary, .loadPluginExecutable, from: &parsedOptions)
} else if isFrontendArgSupported(.pluginPath) {
try commandLine.appendAll(.pluginPath, .loadPluginLibrary, from: &parsedOptions)
}

if isFrontendArgSupported(.blockListFile) {
Expand Down Expand Up @@ -394,6 +383,18 @@ extension Driver {
inputs: &inputs,
frontendTargetInfo: frontendTargetInfo,
driver: &self)

// Platform-agnostic options that need to happen after platform-specific ones.
if isFrontendArgSupported(.pluginPath) {
// Default paths for compiler plugins found within the toolchain
// (loaded as shared libraries).
let pluginPathRoot = VirtualPath.absolute(try toolchain.executableDir.parentDirectory)
commandLine.appendFlag(.pluginPath)
commandLine.appendPath(pluginPathRoot.pluginPath)

commandLine.appendFlag(.pluginPath)
commandLine.appendPath(pluginPathRoot.localPluginPath)
}
}

mutating func addFrontendSupplementaryOutputArguments(commandLine: inout [Job.ArgTemplate],
Expand Down
44 changes: 44 additions & 0 deletions Sources/SwiftDriver/Toolchains/DarwinToolchain.swift
Expand Up @@ -421,6 +421,30 @@ public final class DarwinToolchain: Toolchain {
commandLine.appendFlag(.clangTarget)
commandLine.appendFlag(clangTargetTriple)
}

if driver.isFrontendArgSupported(.externalPluginPath) {
// Default paths for compiler plugins found within an SDK (accessed via
// that SDK's plugin server).
let sdkPathRoot = VirtualPath.lookup(sdkPath).appending(components: "usr")
commandLine.appendFlag(.externalPluginPath)
commandLine.appendFlag("\(sdkPathRoot.pluginPath.name)#\(sdkPathRoot.pluginServerPath.name.spm_shellEscaped())")

commandLine.appendFlag(.externalPluginPath)
commandLine.appendFlag("\(sdkPathRoot.localPluginPath.name)#\(sdkPathRoot.pluginServerPath.name.spm_shellEscaped())")

// Default paths for compiler plugins within the platform (accessed via that
// platform's plugin server).
let platformPathRoot = VirtualPath.lookup(sdkPath)
.parentDirectory
.parentDirectory
.parentDirectory
.appending(components: "Developer", "usr")
commandLine.appendFlag(.externalPluginPath)
commandLine.appendFlag("\(platformPathRoot.pluginPath.name)#\(platformPathRoot.pluginServerPath.name.spm_shellEscaped())")

commandLine.appendFlag(.externalPluginPath)
commandLine.appendFlag("\(platformPathRoot.localPluginPath.name)#\(platformPathRoot.pluginServerPath.name.spm_shellEscaped())")
}
}
}

Expand All @@ -441,3 +465,23 @@ private extension Version {
return self.description
}
}

extension VirtualPath {
// Given a virtual path pointing into a toolchain/SDK/platform, produce the
// path to `swift-plugin-server`.
fileprivate var pluginServerPath: VirtualPath {
self.appending(components: "bin", "swift-plugin-server")
}

// Given a virtual path pointing into a toolchain/SDK/platform, produce the
// path to the plugins.
var pluginPath: VirtualPath {
self.appending(components: "lib", "swift", "host", "plugins")
}

// Given a virtual path pointing into a toolchain/SDK/platform, produce the
// path to the plugins.
var localPluginPath: VirtualPath {
self.appending(component: "local").pluginPath
}
}
54 changes: 52 additions & 2 deletions Tests/SwiftDriverTests/SwiftDriverTests.swift
Expand Up @@ -6798,14 +6798,64 @@ final class SwiftDriverTests: XCTestCase {
}

func testPluginPaths() throws {
var driver = try Driver(args: ["swiftc", "-typecheck", "foo.swift"])
guard driver.isFrontendArgSupported(.pluginPath) else {
let sdkRoot = testInputsPath.appending(component: "SDKChecks").appending(component: "iPhoneOS.sdk")
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"])
guard driver.isFrontendArgSupported(.pluginPath) && driver.isFrontendArgSupported(.externalPluginPath) else {
return
}

let jobs = try driver.planBuild().removingAutolinkExtractJobs()
XCTAssertEqual(jobs.count, 1)
let job = jobs.first!

// Check that the we have the plugin paths we expect, in the order we expect.
let pluginAIndex = job.commandLine.firstIndex(of: .path(VirtualPath.relative(.init("PluginA"))))
XCTAssertNotNil(pluginAIndex)

let pluginBIndex = job.commandLine.firstIndex(of: .path(VirtualPath.relative(.init("PluginB#Bexe"))))
XCTAssertNotNil(pluginBIndex)
XCTAssertLessThan(pluginAIndex!, pluginBIndex!)

let pluginB2Index = job.commandLine.firstIndex(of: .path(VirtualPath.relative(.init("PluginB2"))))
XCTAssertNotNil(pluginB2Index)
XCTAssertLessThan(pluginBIndex!, pluginB2Index!)

let pluginCIndex = job.commandLine.firstIndex(of: .path(VirtualPath.relative(.init("PluginC"))))
XCTAssertNotNil(pluginCIndex)
XCTAssertLessThan(pluginB2Index!, pluginCIndex!)

#if os(macOS)
XCTAssertTrue(job.commandLine.contains(.flag("-external-plugin-path")))
let sdkServerPath = sdkRoot.appending(components: "usr", "bin", "swift-plugin-server").pathString
let sdkPluginPath = sdkRoot.appending(components: "usr", "lib", "swift", "host", "plugins").pathString

let sdkPluginPathIndex = job.commandLine.firstIndex(of: .flag("\(sdkPluginPath)#\(sdkServerPath)"))
XCTAssertNotNil(sdkPluginPathIndex)
XCTAssertLessThan(pluginCIndex!, sdkPluginPathIndex!)

let sdkLocalPluginPath = sdkRoot.appending(components: "usr", "local", "lib", "swift", "host", "plugins").pathString
let sdkLocalPluginPathIndex = job.commandLine.firstIndex(of: .flag("\(sdkLocalPluginPath)#\(sdkServerPath)"))
XCTAssertNotNil(sdkLocalPluginPathIndex)
XCTAssertLessThan(sdkPluginPathIndex!, sdkLocalPluginPathIndex!)

let platformPath = sdkRoot.parentDirectory.parentDirectory.parentDirectory.appending(components: "Developer", "usr")
let platformServerPath = platformPath.appending(components: "bin", "swift-plugin-server").pathString

let platformPluginPath = platformPath.appending(components: "lib", "swift", "host", "plugins")
let platformPluginPathIndex = job.commandLine.firstIndex(of: .flag("\(platformPluginPath)#\(platformServerPath)"))
XCTAssertNotNil(platformPluginPathIndex)
XCTAssertLessThan(sdkLocalPluginPathIndex!, platformPluginPathIndex!)

let platformLocalPluginPath = platformPath.appending(components: "local", "lib", "swift", "host", "plugins")
let platformLocalPluginPathIndex = job.commandLine.firstIndex(of: .flag("\(platformLocalPluginPath)#\(platformServerPath)"))
XCTAssertNotNil(platformLocalPluginPathIndex)
XCTAssertLessThan(platformPluginPathIndex!, platformLocalPluginPathIndex!)

let toolchainPluginPathIndex = job.commandLine.firstIndex(of: .path(.absolute(try driver.toolchain.executableDir.parentDirectory.appending(components: "lib", "swift", "host", "plugins"))))
XCTAssertNotNil(toolchainPluginPathIndex)
XCTAssertLessThan(platformLocalPluginPathIndex!, toolchainPluginPathIndex!)
#endif

XCTAssertTrue(job.commandLine.contains(.flag("-plugin-path")))
XCTAssertTrue(job.commandLine.contains(.path(.absolute(try driver.toolchain.executableDir.parentDirectory.appending(components: "lib", "swift", "host", "plugins")))))
XCTAssertTrue(job.commandLine.contains(.path(.absolute(try driver.toolchain.executableDir.parentDirectory.appending(components: "local", "lib", "swift", "host", "plugins")))))
Expand Down

0 comments on commit 99d316a

Please sign in to comment.