Skip to content

Commit 4d911fa

Browse files
committed
Allow passing extra arguments to plugin compilation.
For most case, compiling against the host toolchain does not need extra arguments, but in some complicated setups, the host toolchain might need extra arguments for search paths and such. In the case of the manifest, the option of using `-Xmanifest` arguments to customize the manifest compilation has existed for a while, but in the case of plugins, the same option was not available and made consuming packages with plugins very complicated. The changes in this commit add `-Xbuild-tools-swiftc` to affect both manifest and plugin compilation, allowing complicated setups to provide their values and compile and use plugins. `-Xmanifest` is kept for backwards compatibility, but it will only affect manifest compilation, as before, and it will print a warning if used. Includes modifications in one of the plugin tests to show that the `-Xbuild-tools-swiftc` parameters are passed to the plugin compilation (I could not find a similar test for `-Xmanifest`).
1 parent 1059cb8 commit 4d911fa

6 files changed

Lines changed: 74 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ Note: This is in reverse chronological order, so newer entries are added to the
33
Swift Next
44
-----------
55

6+
* [#5966]
7+
8+
Plugin compilation can be influenced by using `-Xbuild-tools-swiftc` arguments in the SwiftPM command line. This is similar to the existing mechanism for influencing the manifest compilation using `-Xmanifest` arguments. Manifest compilation will also be influenced by `-Xbuild-tools-swiftc`, but only if no other `-Xmanifest` arguments are provided. Using `-Xmanifest` will show a deprecation message. `-Xmanifest` will be removed in the future.
9+
610
* [#5728]
711

812
In packages that specify resources using a future tools version, the generated resource bundle accessor will import `Foundation.Bundle` for its own implementation only. _Clients_ of such packages therefore no longer silently import `Foundation`, preventing inadvertent use of Foundation extensions to standard library APIs, which helps to avoid unexpected code size increases.
@@ -294,3 +298,4 @@ Swift 3.0
294298
[#5728]: https://github.com/apple/swift-package-manager/pull/5728
295299
[#5874]: https://github.com/apple/swift-package-manager/pull/5874
296300
[#5949]: https://github.com/apple/swift-package-manager/pull/5949
301+
[#5966]: https://github.com/apple/swift-package-manager/pull/5966

Fixtures/Miscellaneous/Plugins/MySourceGenPlugin/Plugins/MySourceGenBuildToolPlugin/plugin.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import PackagePlugin
22

33
@main
44
struct MyPlugin: BuildToolPlugin {
5-
5+
#if USE_CREATE
6+
let verb = "Creating"
7+
#else
8+
let verb = "Generating"
9+
#endif
10+
611
func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] {
712
print("Hello from the Build Tool Plugin!")
813
guard let target = target as? SourceModuleTarget else { return [] }
@@ -12,7 +17,7 @@ struct MyPlugin: BuildToolPlugin {
1217
let outputPath = context.pluginWorkDirectory.appending(outputName)
1318
return .buildCommand(
1419
displayName:
15-
"Generating \(outputName) from \($0.lastComponent)",
20+
"\(verb) \(outputName) from \($0.lastComponent)",
1621
executable:
1722
try context.tool(named: "MySourceGenBuildTool").path,
1823
arguments: [

Sources/CoreCommands/Options.swift

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,11 +306,31 @@ public struct BuildOptions: ParsableArguments {
306306
))
307307
public var xcbuildFlags: [String] = []
308308

309+
@Option(name: .customLong("Xbuild-tools-swiftc", withSingleDash: true),
310+
parsing: .unconditionalSingleValue,
311+
help: ArgumentHelp(
312+
"Pass flag to Swift compiler invocations for build-time executables (manifest and plugins)",
313+
visibility: .hidden
314+
))
315+
public var _buildToolsSwiftCFlags: [String] = []
316+
309317
@Option(name: .customLong("Xmanifest", withSingleDash: true),
310318
parsing: .unconditionalSingleValue,
311-
help: ArgumentHelp("Pass flag to the manifest build invocation",
312-
visibility: .hidden))
313-
var manifestFlags: [String] = []
319+
help: ArgumentHelp(
320+
"Pass flag to the manifest build invocation. Deprecated: use '-Xbuild-tools-swiftc' instead",
321+
visibility: .hidden
322+
))
323+
public var _deprecated_manifestFlags: [String] = []
324+
325+
var manifestFlags: [String] {
326+
self._deprecated_manifestFlags.isEmpty ?
327+
self._buildToolsSwiftCFlags :
328+
self._deprecated_manifestFlags
329+
}
330+
331+
var pluginSwiftCFlags: [String] {
332+
self._buildToolsSwiftCFlags
333+
}
314334

315335
public var buildFlags: BuildFlags {
316336
BuildFlags(

Sources/CoreCommands/SwiftTool.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,10 @@ public final class SwiftTool {
345345
if let _ = options.security.netrcFilePath, options.security.netrc == false {
346346
observabilityScope.emit(.mutuallyExclusiveArgumentsError(arguments: ["--disable-netrc", "--netrc-file"]))
347347
}
348+
349+
if !options.build._deprecated_manifestFlags.isEmpty {
350+
observabilityScope.emit(warning: "'-Xmanifest' option is deprecated; use '-Xbuild-tools-swiftc' instead")
351+
}
348352
}
349353

350354
func waitForObservabilityEvents(timeout: DispatchTime) {
@@ -517,6 +521,7 @@ public final class SwiftTool {
517521
fileSystem: self.fileSystem,
518522
cacheDir: cacheDir,
519523
toolchain: self.getHostToolchain(),
524+
extraPluginSwiftCFlags: self.options.build.pluginSwiftCFlags,
520525
enableSandbox: !self.shouldDisableSandbox,
521526
verboseOutput: self.logLevel <= .info
522527
)

Sources/Workspace/DefaultPluginScriptRunner.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,25 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable {
2525
private let fileSystem: FileSystem
2626
private let cacheDir: AbsolutePath
2727
private let toolchain: UserToolchain
28+
private let extraPluginSwiftCFlags: [String]
2829
private let enableSandbox: Bool
2930
private let cancellator: Cancellator
3031
private let verboseOutput: Bool
3132

3233
private let sdkRootCache = ThreadSafeBox<AbsolutePath>()
3334

34-
public init(fileSystem: FileSystem, cacheDir: AbsolutePath, toolchain: UserToolchain, enableSandbox: Bool = true, verboseOutput: Bool = false) {
35+
public init(
36+
fileSystem: FileSystem,
37+
cacheDir: AbsolutePath,
38+
toolchain: UserToolchain,
39+
extraPluginSwiftCFlags: [String] = [],
40+
enableSandbox: Bool = true,
41+
verboseOutput: Bool = false
42+
) {
3543
self.fileSystem = fileSystem
3644
self.cacheDir = cacheDir
3745
self.toolchain = toolchain
46+
self.extraPluginSwiftCFlags = extraPluginSwiftCFlags
3847
self.enableSandbox = enableSandbox
3948
self.cancellator = Cancellator(observabilityScope: .none)
4049
self.verboseOutput = verboseOutput
@@ -210,6 +219,9 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable {
210219
// Finally add the output path of the compiled executable.
211220
commandLine += ["-o", execFilePath.pathString]
212221

222+
// Add any extra flags passed for the host in the command line
223+
commandLine += self.extraPluginSwiftCFlags
224+
213225
if (verboseOutput) {
214226
commandLine.append("-v")
215227
}

Tests/FunctionalTests/PluginTests.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,4 +1009,25 @@ class PluginTests: XCTestCase {
10091009
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")
10101010
}
10111011
}
1012+
1013+
func testPluginCanBeAffectedByXBuildToolsParameters() throws {
1014+
// Only run the test if the environment in which we're running actually supports Swift concurrency (which the
1015+
// plugin APIs require).
1016+
try XCTSkipIf(
1017+
!UserToolchain.default.supportsSwiftConcurrency(),
1018+
"skipping because test environment doesn't support concurrency"
1019+
)
1020+
1021+
try fixture(name: "Miscellaneous/Plugins") { fixturePath in
1022+
let (stdout, _) = try executeSwiftBuild(
1023+
fixturePath.appending(component: "MySourceGenPlugin"),
1024+
configuration: .Debug,
1025+
extraArgs: ["--product", "MyLocalTool", "-Xbuild-tools-swiftc", "-DUSE_CREATING"]
1026+
)
1027+
XCTAssert(stdout.contains("Linking MySourceGenBuildTool"), "stdout:\n\(stdout)")
1028+
XCTAssert(stdout.contains("Creating foo.swift from foo.dat"), "stdout:\n\(stdout)")
1029+
XCTAssert(stdout.contains("Linking MyLocalTool"), "stdout:\n\(stdout)")
1030+
XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)")
1031+
}
1032+
}
10121033
}

0 commit comments

Comments
 (0)