Skip to content

Commit 111093f

Browse files
authored
Allow passing extra arguments to plugin compilation. (#5966)
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 8df5ba8 commit 111093f

File tree

6 files changed

+73
-5
lines changed

6 files changed

+73
-5
lines changed

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.
@@ -318,6 +322,7 @@ Swift 3.0
318322
[#5874]: https://github.com/apple/swift-package-manager/pull/5874
319323
[#5949]: https://github.com/apple/swift-package-manager/pull/5949
320324
[#5892]: https://github.com/apple/swift-package-manager/pull/5892
325+
[#5966]: https://github.com/apple/swift-package-manager/pull/5966
321326
[#6060]: https://github.com/apple/swift-package-manager/pull/6060
322327
[#6067]: https://github.com/apple/swift-package-manager/pull/6067
323328
[#6114]: https://github.com/apple/swift-package-manager/pull/6114

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: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,15 +336,35 @@ public struct BuildOptions: ParsableArguments {
336336
)
337337
public var xcbuildFlags: [String] = []
338338

339+
@Option(
340+
name: .customLong("Xbuild-tools-swiftc", withSingleDash: true),
341+
parsing: .unconditionalSingleValue,
342+
help: ArgumentHelp(
343+
"Pass flag to Swift compiler invocations for build-time executables (manifest and plugins)",
344+
visibility: .hidden
345+
)
346+
)
347+
public var _buildToolsSwiftCFlags: [String] = []
348+
339349
@Option(
340350
name: .customLong("Xmanifest", withSingleDash: true),
341351
parsing: .unconditionalSingleValue,
342352
help: ArgumentHelp(
343-
"Pass flag to the manifest build invocation",
353+
"Pass flag to the manifest build invocation. Deprecated: use '-Xbuild-tools-swiftc' instead",
344354
visibility: .hidden
345355
)
346356
)
347-
var manifestFlags: [String] = []
357+
public var _deprecated_manifestFlags: [String] = []
358+
359+
var manifestFlags: [String] {
360+
self._deprecated_manifestFlags.isEmpty ?
361+
self._buildToolsSwiftCFlags :
362+
self._deprecated_manifestFlags
363+
}
364+
365+
var pluginSwiftCFlags: [String] {
366+
self._buildToolsSwiftCFlags
367+
}
348368

349369
public var buildFlags: BuildFlags {
350370
BuildFlags(

Sources/CoreCommands/SwiftTool.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,10 @@ public final class SwiftTool {
423423
if let _ = options.security.netrcFilePath, options.security.netrc == false {
424424
observabilityScope.emit(.mutuallyExclusiveArgumentsError(arguments: ["--disable-netrc", "--netrc-file"]))
425425
}
426+
427+
if !options.build._deprecated_manifestFlags.isEmpty {
428+
observabilityScope.emit(warning: "'-Xmanifest' option is deprecated; use '-Xbuild-tools-swiftc' instead")
429+
}
426430
}
427431

428432
func waitForObservabilityEvents(timeout: DispatchTime) {
@@ -625,6 +629,7 @@ public final class SwiftTool {
625629
fileSystem: self.fileSystem,
626630
cacheDir: cacheDir,
627631
toolchain: self.getHostToolchain(),
632+
extraPluginSwiftCFlags: self.options.build.pluginSwiftCFlags,
628633
enableSandbox: !self.shouldDisableSandbox,
629634
verboseOutput: self.logLevel <= .info
630635
)

Sources/Workspace/DefaultPluginScriptRunner.swift

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

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

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

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

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)