4 using System.Collections.Generic;
6 using System.Threading.Tasks;
7 using SiliconStudio.Core.Storage;
8 using SiliconStudio.Core.Serialization.Assets;
10 namespace SiliconStudio.BuildEngine
20 public override string Title {
get {
return ToString(); } }
22 private int mergeCounter;
23 private readonly List<BuildStep> executedSteps =
new List<BuildStep>();
25 protected readonly Dictionary<ObjectUrl, OutputObject> outputObjects =
new Dictionary<ObjectUrl, OutputObject>();
28 protected readonly Dictionary<ObjectUrl, InputObject> inputObjects =
new Dictionary<ObjectUrl, InputObject>();
45 var buildStepsToWait =
new List<BuildStep>();
47 foreach (var child
in Steps)
52 await CompleteCommands(executeContext, buildStepsToWait);
56 executeContext.ScheduleBuildStep(child);
57 buildStepsToWait.Add(child);
60 executedSteps.Add(child);
63 await CompleteCommands(executeContext, buildStepsToWait);
65 return ComputeResultStatusFromExecutedSteps();
74 if (executedSteps.Count == 0)
75 return ResultStatus.Successful;
82 var result = executedSteps[0].Status;
83 foreach (var executedStep
in executedSteps)
87 result = ResultStatus.Cancelled;
91 if (executedStep.Failed)
92 result = ResultStatus.Failed;
94 result = ResultStatus.Successful;
109 if (buildStepsToWait.Count > 0)
110 await Task.WhenAll(buildStepsToWait.Select(x => x.ExecutedAsync()));
113 await Task.WhenAll(buildStepsToWait.SelectMany(EnumerateSpawnedBuildSteps).Select(x => x.ExecutedAsync()));
116 foreach (var buildStep
in buildStepsToWait)
119 if (enumerableBuildStep != null)
124 foreach (var inputObject
in enumerableBuildStep.inputObjects)
126 CheckInputObject(executeContext, inputObject.Key, inputObject.Value.Command);
129 foreach (var outputObject
in enumerableBuildStep.OutputObjects)
131 CheckOutputObject(executeContext, outputObject.Key, outputObject.Value.ObjectId, outputObject.Value.Command);
135 foreach (var inputObject
in enumerableBuildStep.inputObjects)
137 AddInputObject(executeContext, inputObject.Key, inputObject.Value.Command);
140 foreach (var outputObject
in enumerableBuildStep.OutputObjects)
142 var newOutputObject = AddOutputObject(executeContext, outputObject.Key, outputObject.Value.ObjectId, outputObject.Value.Command);
145 foreach (var tag
in outputObject.Value.Tags)
147 newOutputObject.Tags.Add(tag);
153 if (commandBuildStep != null)
156 ProcessCommandBuildStepResult(executeContext, commandBuildStep);
160 buildStepsToWait.Clear();
173 AddInputObject(executeContext, resultInputObject, buildStep.
Command);
176 if (buildStep.
Result != null)
181 CheckInputObject(executeContext, resultInputObject.Key, buildStep.
Command);
186 CheckOutputObject(executeContext, resultOutputObject.Key, resultOutputObject.Value, buildStep.
Command);
192 AddInputObject(executeContext, resultInputObject.Key, buildStep.
Command);
197 AddOutputObject(executeContext, resultOutputObject.Key, resultOutputObject.Value, buildStep.
Command);
205 ProcessCommandBuildStepResult(executeContext, spawnedStep);
208 if (buildStep.
Result != null)
212 foreach (var tagGroup
in buildStep.
Result
214 .Where(x => buildStep.
Command.TagSymbols.ContainsKey(x.Value))
215 .GroupBy(x => x.Key, x => buildStep.
Command.TagSymbols[x.Value].RealName))
217 var url = tagGroup.Key;
220 OutputObject outputObject;
221 if (outputObjects.TryGetValue(url, out outputObject))
223 outputObject.Tags.UnionWith(tagGroup);
236 private void CheckInputObject(IExecuteContext executeContext,
ObjectUrl inputObjectUrl, Command command)
238 OutputObject outputObject;
239 if (outputObjects.TryGetValue(inputObjectUrl, out outputObject)
240 && outputObject.Command != command
241 && outputObject.Counter == mergeCounter)
243 var error = string.Format(
"Command {0} is writing {1} while command {2} is reading it", outputObject.Command, inputObjectUrl, command);
244 executeContext.Logger.Error(error);
245 throw new InvalidOperationException(error);
249 private void AddInputObject(IExecuteContext executeContext,
ObjectUrl inputObjectUrl, Command command)
251 OutputObject outputObject;
252 if (outputObjects.TryGetValue(inputObjectUrl, out outputObject)
253 && mergeCounter > outputObject.Counter)
259 inputObjects[inputObjectUrl] =
new InputObject { Command = command, Counter = mergeCounter };
270 private void CheckOutputObject(IExecuteContext executeContext,
ObjectUrl outputObjectUrl,
ObjectId outputObjectId, Command command)
272 InputObject inputObject;
273 if (inputObjects.TryGetValue(outputObjectUrl, out inputObject)
274 && inputObject.Command != command
275 && inputObject.Counter == mergeCounter)
277 var error = string.Format(
"Command {0} is writing {1} while command {2} is reading it", command, outputObjectUrl, inputObject.Command);
278 executeContext.Logger.Error(error);
279 throw new InvalidOperationException(error);
283 private OutputObject AddOutputObject(IExecuteContext executeContext,
ObjectUrl outputObjectUrl,
ObjectId outputObjectId, Command command)
285 OutputObject outputObject;
287 if (!outputObjects.TryGetValue(outputObjectUrl, out outputObject))
290 outputObject =
new OutputObject(outputObjectUrl, outputObjectId);
291 outputObjects.Add(outputObjectUrl, outputObject);
296 if (outputObject.ObjectId != outputObjectId && outputObject.Counter == mergeCounter)
298 var error = string.Format(
"Commands {0} and {1} are both writing {2} at the same time", command, outputObject.Command, outputObjectUrl);
299 executeContext.Logger.Error(error);
300 throw new InvalidOperationException(error);
304 outputObject.ObjectId = outputObjectId;
308 outputObject.Counter = mergeCounter;
309 outputObject.Command = command;
316 foreach (var spawnedStep
in buildStep.SpawnedSteps)
318 yield
return spawnedStep;
319 foreach (var childSpawnedStep
in EnumerateSpawnedBuildSteps(spawnedStep))
321 yield
return childSpawnedStep;
IEnumerable< CommandBuildStep > SpawnedSteps
List of commands that needs this command to be successfully executed before being processed ...
A BuildStep that can spawn multiple BuildStep. Input and output tracking and merging will be performe...
readonly IEnumerable< ObjectUrl > InputUrls
CommandResultEntry Result
Command Result, set only after step completion. Not thread safe, should not be modified ...
Dictionary< ObjectUrl, ObjectId > InputDependencyVersions
ResultStatus
Status of a command.
When embedded in a EnumerableBuildStep, this build step will force all previous computations to be fi...
override async Task< ResultStatus > Execute(IExecuteContext executeContext, BuilderContext builderContext)
Execute the BuildStep, usually resulting in scheduling tasks in the scheduler
async Task CompleteCommands(IExecuteContext executeContext, List< BuildStep > buildStepsToWait)
Wait for given build steps to finish, then processes their inputs and outputs.
virtual IEnumerable< ObjectUrl > GetInputFiles()
Gets the list of input files (that can be deduced without running the command, only from command para...
ResultStatus ComputeResultStatusFromExecutedSteps()
Determine the result status of an execution of enumeration of build steps.
A hash to uniquely identify data.
EnumerableBuildStep(IEnumerable< BuildStep > steps)
List< KeyValuePair< ObjectUrl, string > > TagSymbols
Tags added for a given URL.
Dictionary< ObjectUrl, ObjectId > OutputObjects
Output object ids as saved in the object database.