@@ -28,7 +28,19 @@ import protocol TSCUtility.ProgressAnimationProtocol
28
28
29
29
@_implementationOnly import SwiftDriver
30
30
31
+
32
+
31
33
public final class BuildOperation : PackageStructureDelegate , SPMBuildCore . BuildSystem , BuildErrorAdviceProvider {
34
+ public struct PluginConfiguration {
35
+ /// Entity responsible for compiling and running plugin scripts.
36
+ let scriptRunner : PluginScriptRunner
37
+
38
+ /// Directory where plugin intermediate files are stored.
39
+ let workDirectory : AbsolutePath
40
+
41
+ /// Whether to sandbox commands from build tool plugins.
42
+ let disableSandbox : Bool
43
+ }
32
44
33
45
/// The delegate used by the build system.
34
46
public weak var delegate : SPMBuildCore . BuildSystemDelegate ?
@@ -39,14 +51,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
39
51
/// The closure for loading the package graph.
40
52
let packageGraphLoader : ( ) throws -> PackageGraph
41
53
42
- /// Entity responsible for compiling and running plugin scripts.
43
- let pluginScriptRunner : PluginScriptRunner
44
-
45
- /// Directory where plugin intermediate files are stored.
46
- let pluginWorkDirectory : AbsolutePath
47
-
48
- /// Whether to sandbox commands from build tool plugins.
49
- public let disableSandboxForPluginCommands : Bool
54
+ let pluginConfiguration : PluginConfiguration ?
50
55
51
56
/// The llbuild build delegate reference.
52
57
private var buildSystemDelegate : BuildOperationBuildSystemDelegateHandler ?
@@ -99,10 +104,8 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
99
104
buildParameters: BuildParameters ,
100
105
cacheBuildManifest: Bool ,
101
106
packageGraphLoader: @escaping ( ) throws -> PackageGraph ,
107
+ pluginConfiguration: PluginConfiguration ? = . none,
102
108
additionalFileRules: [ FileRuleDescription ] ,
103
- pluginScriptRunner: PluginScriptRunner ,
104
- pluginWorkDirectory: AbsolutePath ,
105
- disableSandboxForPluginCommands: Bool ,
106
109
outputStream: OutputByteStream ,
107
110
logLevel: Basics . Diagnostic . Severity ,
108
111
fileSystem: TSCBasic . FileSystem ,
@@ -116,9 +119,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
116
119
self . cacheBuildManifest = cacheBuildManifest
117
120
self . packageGraphLoader = packageGraphLoader
118
121
self . additionalFileRules = additionalFileRules
119
- self . pluginScriptRunner = pluginScriptRunner
120
- self . pluginWorkDirectory = pluginWorkDirectory
121
- self . disableSandboxForPluginCommands = disableSandboxForPluginCommands
122
+ self . pluginConfiguration = pluginConfiguration
122
123
self . outputStream = outputStream
123
124
self . logLevel = logLevel
124
125
self . fileSystem = fileSystem
@@ -323,6 +324,10 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
323
324
// Compiles a single plugin, emitting its output and throwing an error if it
324
325
// fails.
325
326
func compilePlugin( _ plugin: PluginDescription ) throws {
327
+ guard let pluginConfiguration = self . pluginConfiguration else {
328
+ throw InternalError ( " unknown plugin script runner " )
329
+
330
+ }
326
331
// Compile the plugin, getting back a PluginCompilationResult.
327
332
class Delegate : PluginScriptCompilerDelegate {
328
333
let preparationStepName : String
@@ -351,7 +356,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
351
356
}
352
357
let delegate = Delegate ( preparationStepName: " Compiling plugin \( plugin. targetName) " , buildSystemDelegate: self . buildSystemDelegate)
353
358
let result = try tsc_await {
354
- self . pluginScriptRunner . compilePluginScript (
359
+ pluginConfiguration . scriptRunner . compilePluginScript (
355
360
sourceFiles: plugin. sources. paths,
356
361
pluginName: plugin. targetName,
357
362
toolsVersion: plugin. toolsVersion,
@@ -393,40 +398,47 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
393
398
// Load the package graph.
394
399
let graph = try getPackageGraph ( )
395
400
401
+ let buildToolPluginInvocationResults : [ ResolvedTarget : [ BuildToolPluginInvocationResult ] ]
402
+ let prebuildCommandResults : [ ResolvedTarget : [ PrebuildCommandResult ] ]
396
403
// Invoke any build tool plugins in the graph to generate prebuild commands and build commands.
397
- let buildToolPluginInvocationResults = try graph. invokeBuildToolPlugins (
398
- outputDir: self . pluginWorkDirectory. appending ( component: " outputs " ) ,
399
- builtToolsDir: self . buildParameters. buildPath,
400
- buildEnvironment: self . buildParameters. buildEnvironment,
401
- toolSearchDirectories: [ self . buildParameters. toolchain. swiftCompilerPath. parentDirectory] ,
402
- pluginScriptRunner: self . pluginScriptRunner,
403
- observabilityScope: self . observabilityScope,
404
- fileSystem: self . fileSystem
405
- )
406
-
407
- // Surface any diagnostics from build tool plugins.
408
- for (target, results) in buildToolPluginInvocationResults {
409
- // There is one result for each plugin that gets applied to a target.
410
- for result in results {
411
- let diagnosticsEmitter = self . observabilityScope. makeDiagnosticsEmitter {
412
- var metadata = ObservabilityMetadata ( )
413
- metadata. targetName = target. name
414
- metadata. pluginName = result. plugin. name
415
- return metadata
416
- }
417
- for line in result. textOutput. split ( separator: " \n " ) {
418
- diagnosticsEmitter. emit ( info: line)
419
- }
420
- for diag in result. diagnostics {
421
- diagnosticsEmitter. emit ( diag)
404
+ if let pluginConfiguration = self . pluginConfiguration {
405
+ buildToolPluginInvocationResults = try graph. invokeBuildToolPlugins (
406
+ outputDir: pluginConfiguration. workDirectory. appending ( component: " outputs " ) ,
407
+ builtToolsDir: self . buildParameters. buildPath,
408
+ buildEnvironment: self . buildParameters. buildEnvironment,
409
+ toolSearchDirectories: [ self . buildParameters. toolchain. swiftCompilerPath. parentDirectory] ,
410
+ pluginScriptRunner: pluginConfiguration. scriptRunner,
411
+ observabilityScope: self . observabilityScope,
412
+ fileSystem: self . fileSystem
413
+ )
414
+
415
+ // Surface any diagnostics from build tool plugins.
416
+ for (target, results) in buildToolPluginInvocationResults {
417
+ // There is one result for each plugin that gets applied to a target.
418
+ for result in results {
419
+ let diagnosticsEmitter = self . observabilityScope. makeDiagnosticsEmitter {
420
+ var metadata = ObservabilityMetadata ( )
421
+ metadata. targetName = target. name
422
+ metadata. pluginName = result. plugin. name
423
+ return metadata
424
+ }
425
+ for line in result. textOutput. split ( separator: " \n " ) {
426
+ diagnosticsEmitter. emit ( info: line)
427
+ }
428
+ for diag in result. diagnostics {
429
+ diagnosticsEmitter. emit ( diag)
430
+ }
422
431
}
423
432
}
424
- }
425
433
426
- // Run any prebuild commands provided by build tool plugins. Any failure stops the build.
427
- let prebuildCommandResults = try graph. reachableTargets. reduce ( into: [ : ] , { partial, target in
428
- partial [ target] = try buildToolPluginInvocationResults [ target] . map { try self . runPrebuildCommands ( for: $0) }
429
- } )
434
+ // Run any prebuild commands provided by build tool plugins. Any failure stops the build.
435
+ prebuildCommandResults = try graph. reachableTargets. reduce ( into: [ : ] , { partial, target in
436
+ partial [ target] = try buildToolPluginInvocationResults [ target] . map { try self . runPrebuildCommands ( for: $0) }
437
+ } )
438
+ } else {
439
+ buildToolPluginInvocationResults = [ : ]
440
+ prebuildCommandResults = [ : ]
441
+ }
430
442
431
443
// Emit warnings about any unhandled files in authored packages. We do this after applying build tool plugins, once we know what files they handled.
432
444
for package in graph. rootPackages where package . manifest. toolsVersion >= . v5_3 {
@@ -472,7 +484,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
472
484
473
485
let ( buildDescription, buildManifest) = try BuildDescription . create (
474
486
with: plan,
475
- disableSandboxForPluginCommands: self . disableSandboxForPluginCommands ,
487
+ disableSandboxForPluginCommands: self . pluginConfiguration ? . disableSandbox ?? false ,
476
488
fileSystem: self . fileSystem,
477
489
observabilityScope: self . observabilityScope
478
490
)
@@ -541,6 +553,10 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
541
553
/// Runs any prebuild commands associated with the given list of plugin invocation results, in order, and returns the
542
554
/// results of running those prebuild commands.
543
555
private func runPrebuildCommands( for pluginResults: [ BuildToolPluginInvocationResult ] ) throws -> [ PrebuildCommandResult ] {
556
+ guard let pluginConfiguration = self . pluginConfiguration else {
557
+ throw InternalError ( " unknown plugin script runner " )
558
+
559
+ }
544
560
// Run through all the commands from all the plugin usages in the target.
545
561
return try pluginResults. map { pluginResult in
546
562
// As we go we will collect a list of prebuild output directories whose contents should be input to the build,
@@ -553,7 +569,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
553
569
// Run the command configuration as a subshell. This doesn't return until it is done.
554
570
// TODO: We need to also use any working directory, but that support isn't yet available on all platforms at a lower level.
555
571
var commandLine = [ command. configuration. executable. pathString] + command. configuration. arguments
556
- if !self . disableSandboxForPluginCommands {
572
+ if !pluginConfiguration . disableSandbox {
557
573
commandLine = try Sandbox . apply ( command: commandLine, strictness: . writableTemporaryDirectory, writableDirectories: [ pluginResult. pluginOutputDirectory] )
558
574
}
559
575
let processResult = try TSCBasic . Process. popen ( arguments: commandLine, environment: command. configuration. environment)
0 commit comments