@@ -734,69 +734,41 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
734
734
private func plan( subset: BuildSubset ? = nil ) throws -> ( description: BuildDescription , manifest: LLBuildManifest ) {
735
735
// Load the package graph.
736
736
let graph = try getPackageGraph ( )
737
- let buildToolPluginInvocationResults : [ ResolvedModule . ID : ( target: ResolvedModule , results: [ BuildToolPluginInvocationResult ] ) ]
738
- let prebuildCommandResults : [ ResolvedModule . ID : [ PrebuildCommandResult ] ]
739
- // Invoke any build tool plugins in the graph to generate prebuild commands and build commands.
737
+
738
+ let pluginTools : [ ResolvedModule . ID : [ String : PluginTool ] ]
739
+ // FIXME: This is unfortunate but we need to build plugin tools upfront at the moment because
740
+ // llbuild doesn't support dynamic dependency detection. In order to construct a manifest
741
+ // we need to build and invoke all of the build-tool plugins and capture their outputs in
742
+ // `BuildPlan`.
740
743
if let pluginConfiguration: PluginConfiguration , !self . config. shouldSkipBuilding ( for: . target) {
741
744
let pluginsPerModule = graph. pluginsPerModule (
742
745
satisfying: self . config. buildEnvironment ( for: . host)
743
746
)
744
747
745
- let pluginTools = try buildPluginTools (
748
+ pluginTools = try buildPluginTools (
746
749
graph: graph,
747
750
pluginsPerModule: pluginsPerModule,
748
751
hostTriple: try pluginConfiguration. scriptRunner. hostTriple
749
752
)
750
-
751
- buildToolPluginInvocationResults = try graph. invokeBuildToolPlugins (
752
- pluginsPerTarget: pluginsPerModule,
753
- pluginTools: pluginTools,
754
- outputDir: pluginConfiguration. workDirectory. appending ( " outputs " ) ,
755
- buildParameters: self . config. toolsBuildParameters,
756
- additionalFileRules: self . additionalFileRules,
757
- toolSearchDirectories: [ self . config. toolchain ( for: . host) . swiftCompilerPath. parentDirectory] ,
758
- pkgConfigDirectories: self . pkgConfigDirectories,
759
- pluginScriptRunner: pluginConfiguration. scriptRunner,
760
- observabilityScope: self . observabilityScope,
761
- fileSystem: self . fileSystem
762
- )
763
-
764
- // Surface any diagnostics from build tool plugins.
765
- var succeeded = true
766
- for (_, ( target, results) ) in buildToolPluginInvocationResults {
767
- // There is one result for each plugin that gets applied to a target.
768
- for result in results {
769
- let diagnosticsEmitter = self . observabilityScope. makeDiagnosticsEmitter {
770
- var metadata = ObservabilityMetadata ( )
771
- metadata. moduleName = target. name
772
- metadata. pluginName = result. plugin. name
773
- return metadata
774
- }
775
- for line in result. textOutput. split ( whereSeparator: { $0. isNewline } ) {
776
- diagnosticsEmitter. emit ( info: line)
777
- }
778
- for diag in result. diagnostics {
779
- diagnosticsEmitter. emit ( diag)
780
- }
781
- succeeded = succeeded && result. succeeded
782
- }
783
-
784
- if !succeeded {
785
- throw StringError ( " build stopped due to build-tool plugin failures " )
786
- }
787
- }
788
-
789
- // Run any prebuild commands provided by build tool plugins. Any failure stops the build.
790
- prebuildCommandResults = try graph. reachableModules. reduce ( into: [ : ] , { partial, target in
791
- partial [ target. id] = try buildToolPluginInvocationResults [ target. id] . map {
792
- try self . runPrebuildCommands ( for: $0. results)
793
- }
794
- } )
795
753
} else {
796
- buildToolPluginInvocationResults = [ : ]
797
- prebuildCommandResults = [ : ]
754
+ pluginTools = [ : ]
798
755
}
799
756
757
+ // Create the build plan based on the modules graph and any information from plugins.
758
+ let plan = try BuildPlan (
759
+ destinationBuildParameters: self . config. destinationBuildParameters,
760
+ toolsBuildParameters: self . config. buildParameters ( for: . host) ,
761
+ graph: graph,
762
+ pluginConfiguration: self . pluginConfiguration,
763
+ pluginTools: pluginTools,
764
+ additionalFileRules: additionalFileRules,
765
+ pkgConfigDirectories: pkgConfigDirectories,
766
+ disableSandbox: self . pluginConfiguration? . disableSandbox ?? false ,
767
+ fileSystem: self . fileSystem,
768
+ observabilityScope: self . observabilityScope
769
+ )
770
+ self . _buildPlan = plan
771
+
800
772
// Emit warnings about any unhandled files in authored packages. We do this after applying build tool plugins, once we know what files they handled.
801
773
// rdar://113256834 This fix works for the plugins that do not have PreBuildCommands.
802
774
let targetsToConsider : [ ResolvedModule ]
@@ -809,7 +781,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
809
781
810
782
for module in targetsToConsider {
811
783
// Subtract out any that were inputs to any commands generated by plugins.
812
- if let pluginResults = buildToolPluginInvocationResults [ module. id] ? . results {
784
+ if let pluginResults = plan . buildToolPluginInvocationResults [ module. id] {
813
785
diagnoseUnhandledFiles (
814
786
modulesGraph: graph,
815
787
module: module,
@@ -818,21 +790,6 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
818
790
}
819
791
}
820
792
821
- // Create the build plan based, on the graph and any information from plugins.
822
- let plan = try BuildPlan (
823
- destinationBuildParameters: self . config. destinationBuildParameters,
824
- toolsBuildParameters: self . config. buildParameters ( for: . host) ,
825
- graph: graph,
826
- pluginConfiguration: self . pluginConfiguration,
827
- additionalFileRules: additionalFileRules,
828
- buildToolPluginInvocationResults: buildToolPluginInvocationResults. mapValues ( \. results) ,
829
- prebuildCommandResults: prebuildCommandResults,
830
- disableSandbox: self . pluginConfiguration? . disableSandbox ?? false ,
831
- fileSystem: self . fileSystem,
832
- observabilityScope: self . observabilityScope
833
- )
834
- self . _buildPlan = plan
835
-
836
793
let ( buildDescription, buildManifest) = try BuildDescription . create (
837
794
from: plan,
838
795
using: self . config,
@@ -943,49 +900,6 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
943
900
return ( buildSystem: llbuildSystem, tracker: progressTracker)
944
901
}
945
902
946
- /// Runs any prebuild commands associated with the given list of plugin invocation results, in order, and returns the
947
- /// results of running those prebuild commands.
948
- private func runPrebuildCommands( for pluginResults: [ BuildToolPluginInvocationResult ] ) throws -> [ PrebuildCommandResult ] {
949
- guard let pluginConfiguration = self . pluginConfiguration else {
950
- throw InternalError ( " unknown plugin script runner " )
951
-
952
- }
953
- // Run through all the commands from all the plugin usages in the target.
954
- return try pluginResults. map { pluginResult in
955
- // As we go we will collect a list of prebuild output directories whose contents should be input to the build,
956
- // and a list of the files in those directories after running the commands.
957
- var derivedFiles : [ AbsolutePath ] = [ ]
958
- var prebuildOutputDirs : [ AbsolutePath ] = [ ]
959
- for command in pluginResult. prebuildCommands {
960
- self . observabilityScope. emit ( info: " Running " + ( command. configuration. displayName ?? command. configuration. executable. basename) )
961
-
962
- // Run the command configuration as a subshell. This doesn't return until it is done.
963
- // TODO: We need to also use any working directory, but that support isn't yet available on all platforms at a lower level.
964
- var commandLine = [ command. configuration. executable. pathString] + command. configuration. arguments
965
- if !pluginConfiguration. disableSandbox {
966
- commandLine = try Sandbox . apply ( command: commandLine, fileSystem: self . fileSystem, strictness: . writableTemporaryDirectory, writableDirectories: [ pluginResult. pluginOutputDirectory] )
967
- }
968
- let processResult = try AsyncProcess . popen ( arguments: commandLine, environment: command. configuration. environment)
969
- let output = try processResult. utf8Output ( ) + processResult. utf8stderrOutput ( )
970
- if processResult. exitStatus != . terminated( code: 0 ) {
971
- throw StringError ( " failed: \( command) \n \n \( output) " )
972
- }
973
-
974
- // Add any files found in the output directory declared for the prebuild command after the command ends.
975
- let outputFilesDir = command. outputFilesDirectory
976
- if let swiftFiles = try ? self . fileSystem. getDirectoryContents ( outputFilesDir) . sorted ( ) {
977
- derivedFiles. append ( contentsOf: swiftFiles. map { outputFilesDir. appending ( component: $0) } )
978
- }
979
-
980
- // Add the output directory to the list of directories whose structure should affect the build plan.
981
- prebuildOutputDirs. append ( outputFilesDir)
982
- }
983
-
984
- // Add the results of running any prebuild commands for this invocation.
985
- return PrebuildCommandResult ( derivedFiles: derivedFiles, outputDirectories: prebuildOutputDirs)
986
- }
987
- }
988
-
989
903
public func provideBuildErrorAdvice( for target: String , command: String , message: String ) -> String ? {
990
904
// Find the target for which the error was emitted. If we don't find it, we can't give any advice.
991
905
guard let _ = self . _buildPlan? . targets. first ( where: { $0. target. name == target } ) else { return nil }
@@ -1075,8 +989,6 @@ extension BuildOperation {
1075
989
graph: graph,
1076
990
pluginConfiguration: nil ,
1077
991
additionalFileRules: [ ] ,
1078
- buildToolPluginInvocationResults: [ : ] ,
1079
- prebuildCommandResults: [ : ] ,
1080
992
fileSystem: config. fileSystem,
1081
993
observabilityScope: config. observabilityScope
1082
994
)
0 commit comments