Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
BuildStep.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using SiliconStudio.Core.Serialization.Assets;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Threading.Tasks;
8 
9 namespace SiliconStudio.BuildEngine
10 {
11  public abstract class BuildStep
12  {
13  protected BuildStep(ResultStatus status = ResultStatus.NotProcessed)
14  {
15  Status = status;
16  }
17 
18  /// <summary>
19  /// Gets or sets the module associated with this build step, used when logging error/information.
20  /// </summary>
21  /// <value>The module.</value>
22  public string Module { get; set; }
23 
24  /// <summary>
25  /// Gets or sets the priority amongst other build steps.
26  /// </summary>
27  /// <value>
28  /// The priority.
29  /// </value>
30  public int? Priority { get; set; }
31 
32  /// <summary>
33  /// Title of the build step. Intended to be short
34  /// </summary>
35  public abstract string Title { get; }
36 
37  /// <summary>
38  /// Description of the build step. Intended to be longer and more descriptive than the <see cref="Title"/>
39  /// </summary>
40  public string Description { get { return ToString(); } }
41 
42  /// <summary>
43  /// The status of the result.
44  /// </summary>
45  public ResultStatus Status { get; private set; }
46 
47  /// <summary>
48  /// Indicate whether this command has already been processed (ie. executed or skipped) by the Builder
49  /// </summary>
50  public bool Processed { get { return Status != ResultStatus.NotProcessed; } }
51 
52  /// <summary>
53  /// Indicate whether the result corresponds to a successful execution (even if the command has not been triggered)
54  /// </summary>
55  public bool Succeeded { get { return Status == ResultStatus.Successful || Status == ResultStatus.NotTriggeredWasSuccessful; } }
56 
57  /// <summary>
58  /// Indicate whether the result corresponds to a failed execution (even if the command has not been triggered)
59  /// </summary>
60  public bool Failed { get { return Status == ResultStatus.Failed || Status == ResultStatus.NotTriggeredPrerequisiteFailed; } }
61 
62  /// <summary>
63  /// A tag property that can contain anything useful for tools based on this build Engine.
64  /// </summary>
65  public object Tag { get; set; }
66 
67  /// <summary>
68  /// List of commands that must be executed prior this one (direct dependence only).
69  /// </summary>
70  // TODO: this is probably obsolete now
71  public IEnumerable<BuildStep> PrerequisiteSteps { get { return prerequisiteSteps; } }
72  private readonly List<BuildStep> prerequisiteSteps = new List<BuildStep>();
73 
74  /// <summary>
75  /// List of commands that needs this command to be successfully executed before being processed
76  /// </summary>
77  public IEnumerable<CommandBuildStep> SpawnedSteps { get { return SpawnedStepsList; } }
78  protected readonly List<CommandBuildStep> SpawnedStepsList = new List<CommandBuildStep>();
79 
80  /// <summary>
81  /// The parent build step, which will be the instigator of the step
82  /// </summary>
83  public BuildStep Parent { get { return parent; } protected internal set { if (parent != null && value != null) throw new InvalidOperationException("BuildStep already has a parent"); parent = value; } }
84  private BuildStep parent;
85 
86  /// <summary>
87  /// An unique id during a build execution, assigned once the build step is scheduled.
88  /// </summary>
89  public long ExecutionId { get; internal set; }
90 
91  /// <summary>
92  /// Indicate whether all prerequisite commands have been processed
93  /// </summary>
94  public bool ArePrerequisitesCompleted { get { return PrerequisiteSteps.All(x => x.Processed); } }
95 
96  /// <summary>
97  /// Indicate whether all prerequisite commands have been processed and are in a successful state
98  /// </summary>
99  public bool ArePrerequisitesSuccessful { get { return PrerequisiteSteps.All(x => x.Succeeded); } }
100 
101  /// <summary>
102  /// Event raised when the command is processed (even if it has been skipped or if it failed)
103  /// </summary>
104  public event EventHandler<BuildStepEventArgs> StepProcessed;
105 
106  /// <summary>
107  /// Execute the BuildStep, usually resulting in scheduling tasks in the scheduler
108  /// </summary>
109  /// <param name="executeContext">The execute context</param>
110  /// <param name="builderContext">The builder context</param>
111  /// <returns>A task returning <see cref="ResultStatus"/> indicating weither the execution has successed or failed.</returns>
112  public abstract Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext);
113 
114  /// <summary>
115  /// Clean the build, deleting the command cache which is used to determine wheither a command has already been executed, and deleting the output objects if asked.
116  /// </summary>
117  /// <param name="executeContext">The execute context</param>
118  /// <param name="builderContext">The builder context</param>
119  /// <param name="deleteOutput">if true, every output object is also deleted, in addition of the command cache.</param>
120  public virtual void Clean(IExecuteContext executeContext, BuilderContext builderContext, bool deleteOutput)
121  {
122  // By default, do the same as Execute. This will apply for flow control steps (lists, enumerations...)
123  // Specific implementation exists for CommandBuildStep
124  Execute(executeContext, builderContext);
125  }
126 
127  /// <summary>
128  /// Clone this Build Step.
129  /// </summary>
130  /// <returns></returns>
131  public abstract BuildStep Clone();
132 
133  public abstract override string ToString();
134 
135  public static void LinkBuildSteps(BuildStep parent, BuildStep child)
136  {
137  lock (child.prerequisiteSteps)
138  {
139  child.prerequisiteSteps.Add(parent);
140  }
141  }
142 
144  {
145  var tcs = new TaskCompletionSource<BuildStep>();
146  StepProcessed += (sender, e) => tcs.TrySetResult(e.Step);
147  return Processed ? Task.FromResult(this) : tcs.Task;
148  }
149 
150  /// <summary>
151  /// Associate the given <see cref="ResultStatus" /> object as the result of the current step and execute the <see cref="StepProcessed"/> event.
152  /// </summary>
153  /// <param name="executeContext">The execute context.</param>
154  /// <param name="status">The result status.</param>
155  internal void RegisterResult(IExecuteContext executeContext, ResultStatus status)
156  {
157  Status = status;
158 
159  //executeContext.Logger.Debug("Step timer for {0}: callbacks: {1}ms, total: {2}ms", this, CallbackWatch.ElapsedMilliseconds, MicroThreadWatch.ElapsedMilliseconds);
160 
161  if (StepProcessed != null)
162  {
163  try
164  {
165  IndexFileCommand.MountDatabases(executeContext);
166  StepProcessed(this, new BuildStepEventArgs(this, executeContext.Logger));
167  }
168  catch (Exception ex)
169  {
170  executeContext.Logger.Error("Exception in command " + this + ": " + ex);
171  }
172  finally
173  {
174  IndexFileCommand.UnmountDatabases(executeContext);
175  }
176  }
177  }
178 
180  {
181  var currentBuildStep = this;
182  while (currentBuildStep != null)
183  {
184  var enumBuildStep = currentBuildStep as EnumerableBuildStep;
185  if (enumBuildStep != null)
186  yield return enumBuildStep.OutputObjects;
187  currentBuildStep = currentBuildStep.Parent;
188  }
189  }
190  }
191 }
virtual void Clean(IExecuteContext executeContext, BuilderContext builderContext, bool deleteOutput)
Clean the build, deleting the command cache which is used to determine wheither a command has already...
Definition: BuildStep.cs:120
A BuildStep that can spawn multiple BuildStep. Input and output tracking and merging will be performe...
IEnumerable< IDictionary< ObjectUrl, OutputObject > > GetOutputObjectsGroups()
Definition: BuildStep.cs:179
static void LinkBuildSteps(BuildStep parent, BuildStep child)
Definition: BuildStep.cs:135
EventHandler< BuildStepEventArgs > StepProcessed
Event raised when the command is processed (even if it has been skipped or if it failed) ...
Definition: BuildStep.cs:104
ResultStatus
Status of a command.
Definition: ResultStatus.cs:8
BuildStep(ResultStatus status=ResultStatus.NotProcessed)
Definition: BuildStep.cs:13
Task< BuildStep > ExecutedAsync()
Definition: BuildStep.cs:143