PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Microsoft.Build/Microsoft.Build/Microsoft/Build/BackEnd/TargetEntry.cs

#
C# | 532 lines | 502 code | 30 blank | 0 comment | 97 complexity | 49420a7750c483ccf9cef9c2263b35c4 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-3.0
  1. namespace Microsoft.Build.BackEnd
  2. {
  3. using Microsoft.Build.BackEnd.Logging;
  4. using Microsoft.Build.Collections;
  5. using Microsoft.Build.Debugging;
  6. using Microsoft.Build.Evaluation;
  7. using Microsoft.Build.Exceptions;
  8. using Microsoft.Build.Execution;
  9. using Microsoft.Build.Framework;
  10. using Microsoft.Build.Shared;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Diagnostics;
  14. using System.Runtime;
  15. using System.Runtime.CompilerServices;
  16. [DebuggerDisplay("Name={targetSpecification.TargetName} State={state} Result={targetResult.ResultCode}")]
  17. internal class TargetEntry : IEquatable<TargetEntry>
  18. {
  19. private Microsoft.Build.BackEnd.Lookup baseLookup;
  20. private bool cancelled;
  21. private object cancelLock = new object();
  22. private ITaskBuilder currentTaskBuilder;
  23. private Expander<ProjectPropertyInstance, ProjectItemInstance> expander;
  24. private IBuildComponentHost host;
  25. private Stack<Microsoft.Build.BackEnd.Lookup.Scope> legacyCallTargetScopes;
  26. private TargetEntry parentTarget;
  27. private BuildRequestEntry requestEntry;
  28. private TargetEntryState state;
  29. private ProjectTargetInstance target;
  30. private ITargetBuilderCallback targetBuilderCallback;
  31. private TargetResult targetResult;
  32. private TargetSpecification targetSpecification;
  33. internal TargetEntry(BuildRequestEntry requestEntry, ITargetBuilderCallback targetBuilderCallback, TargetSpecification targetSpecification, Microsoft.Build.BackEnd.Lookup baseLookup, TargetEntry parentTarget, IBuildComponentHost host, bool stopProcessingOnCompletion)
  34. {
  35. ErrorUtilities.VerifyThrowArgumentNull(requestEntry, "requestEntry");
  36. ErrorUtilities.VerifyThrowArgumentNull(targetBuilderCallback, "targetBuilderCallback");
  37. ErrorUtilities.VerifyThrowArgumentNull(targetSpecification, "targetName");
  38. ErrorUtilities.VerifyThrowArgumentNull(baseLookup, "lookup");
  39. ErrorUtilities.VerifyThrowArgumentNull(host, "host");
  40. this.requestEntry = requestEntry;
  41. this.targetBuilderCallback = targetBuilderCallback;
  42. this.targetSpecification = targetSpecification;
  43. this.parentTarget = parentTarget;
  44. this.expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(baseLookup.ReadOnlyLookup, baseLookup.ReadOnlyLookup);
  45. this.state = TargetEntryState.Dependencies;
  46. this.baseLookup = baseLookup;
  47. this.host = host;
  48. this.StopProcessingOnCompletion = stopProcessingOnCompletion;
  49. }
  50. internal void CancelTarget()
  51. {
  52. this.cancelled = true;
  53. ITaskBuilder currentTaskBuilder = this.currentTaskBuilder;
  54. if (currentTaskBuilder != null)
  55. {
  56. currentTaskBuilder.CancelTask();
  57. }
  58. }
  59. internal void EnterLegacyCallTargetScope(Microsoft.Build.BackEnd.Lookup lookup)
  60. {
  61. if (this.legacyCallTargetScopes == null)
  62. {
  63. this.legacyCallTargetScopes = new Stack<Microsoft.Build.BackEnd.Lookup.Scope>();
  64. }
  65. this.legacyCallTargetScopes.Push(lookup.EnterScope("EnterLegacyCallTargetScope()"));
  66. }
  67. public bool Equals(TargetEntry other)
  68. {
  69. return string.Equals(this.Name, other.Name, StringComparison.OrdinalIgnoreCase);
  70. }
  71. internal void ExecuteTarget(ITaskBuilder taskBuilder, BuildRequestEntry requestEntry, ProjectLoggingContext projectLoggingContext)
  72. {
  73. this.VerifyState(this.state, TargetEntryState.Execution);
  74. List<ItemBucket> list = BatchingEngine.PrepareBatchingBuckets(this.GetBatchableParametersForTarget(), this.baseLookup, this.target.Location);
  75. TaskResultCode skipped = TaskResultCode.Skipped;
  76. Exception exception = null;
  77. TargetLoggingContext targetLoggingContext = null;
  78. bool success = false;
  79. int count = list.Count;
  80. string projectFullPath = requestEntry.RequestConfiguration.ProjectFullPath;
  81. string parentTargetName = null;
  82. if ((this.ParentEntry != null) && (this.ParentEntry.Target != null))
  83. {
  84. parentTargetName = this.ParentEntry.Target.Name;
  85. }
  86. for (int i = 0; i < count; i++)
  87. {
  88. ItemBucket bucket = list[i];
  89. if (skipped == TaskResultCode.StopWithError)
  90. {
  91. break;
  92. }
  93. targetLoggingContext = projectLoggingContext.LogTargetBatchStarted(projectFullPath, this.target, parentTargetName);
  94. TaskResult result = null;
  95. success = false;
  96. Microsoft.Build.BackEnd.Lookup.Scope scope = null;
  97. Microsoft.Build.BackEnd.Lookup.Scope scope2 = null;
  98. try
  99. {
  100. ItemDictionary<ProjectItemInstance> dictionary;
  101. ItemDictionary<ProjectItemInstance> dictionary2;
  102. DependencyAnalysisResult analysis = new TargetUpToDateChecker(requestEntry.RequestConfiguration.Project, this.target, targetLoggingContext.LoggingService, targetLoggingContext.BuildEventContext).PerformDependencyAnalysis(bucket, out dictionary, out dictionary2);
  103. switch (analysis)
  104. {
  105. case DependencyAnalysisResult.SkipUpToDate:
  106. case DependencyAnalysisResult.IncrementalBuild:
  107. case DependencyAnalysisResult.FullBuild:
  108. break;
  109. case DependencyAnalysisResult.SkipNoInputs:
  110. case DependencyAnalysisResult.SkipNoOutputs:
  111. {
  112. success = true;
  113. continue;
  114. }
  115. default:
  116. {
  117. continue;
  118. }
  119. }
  120. Microsoft.Build.BackEnd.Lookup lookupForInference = bucket.Lookup;
  121. Microsoft.Build.BackEnd.Lookup lookupForExecution = bucket.Lookup.Clone();
  122. scope = lookupForInference.EnterScope("ExecuteTarget() Inference");
  123. scope2 = lookupForExecution.EnterScope("ExecuteTarget() Execution");
  124. if (analysis == DependencyAnalysisResult.IncrementalBuild)
  125. {
  126. foreach (string str3 in dictionary2.ItemTypes)
  127. {
  128. lookupForInference.PopulateWithItems(str3, dictionary2[str3]);
  129. }
  130. foreach (string str4 in dictionary.ItemTypes)
  131. {
  132. lookupForExecution.PopulateWithItems(str4, dictionary[str4]);
  133. }
  134. }
  135. result = this.ProcessBucket(taskBuilder, targetLoggingContext, this.GetTaskExecutionMode(analysis), lookupForInference, lookupForExecution);
  136. if (analysis != DependencyAnalysisResult.SkipUpToDate)
  137. {
  138. if ((result.ResultCode == TaskResultCode.StopWithError) || (result.ResultCode == TaskResultCode.Cancelled))
  139. {
  140. skipped = TaskResultCode.StopWithError;
  141. exception = result.Exception;
  142. }
  143. else if (((result.ResultCode == TaskResultCode.ContinueWithError) || (result.ResultCode == TaskResultCode.Success)) && (skipped != TaskResultCode.StopWithError))
  144. {
  145. skipped = TaskResultCode.Success;
  146. }
  147. else
  148. {
  149. ErrorUtilities.VerifyThrow(result.ResultCode == TaskResultCode.Skipped, "Task result should have been 'Skipped', was {0}.", result);
  150. }
  151. }
  152. else if (skipped == TaskResultCode.Skipped)
  153. {
  154. skipped = TaskResultCode.Success;
  155. }
  156. scope.LeaveScope();
  157. scope = null;
  158. scope2.LeaveScope();
  159. scope2 = null;
  160. success = (result != null) && ((result.ResultCode == TaskResultCode.Success) || (result.ResultCode == TaskResultCode.ContinueWithError));
  161. }
  162. catch (InvalidProjectFileException exception2)
  163. {
  164. targetLoggingContext.LogInvalidProjectFileError(exception2);
  165. if (scope != null)
  166. {
  167. scope.LeaveScope();
  168. }
  169. if (scope2 != null)
  170. {
  171. scope2.LeaveScope();
  172. }
  173. skipped = TaskResultCode.StopWithError;
  174. }
  175. finally
  176. {
  177. if ((targetLoggingContext != null) && (i < (count - 1)))
  178. {
  179. targetLoggingContext.LogTargetBatchFinished(projectFullPath, success, null);
  180. targetLoggingContext = null;
  181. }
  182. }
  183. }
  184. List<ProjectItemInstance.TaskItem> list2 = new List<ProjectItemInstance.TaskItem>();
  185. try
  186. {
  187. this.LeaveLegacyCallTargetScopes();
  188. foreach (ItemBucket bucket2 in list)
  189. {
  190. bucket2.LeaveScope();
  191. }
  192. string returns = this.target.Returns;
  193. IElementLocation returnsLocation = this.target.ReturnsLocation;
  194. if ((returns == null) && !this.target.ParentProjectSupportsReturnsAttribute)
  195. {
  196. returns = this.target.Outputs;
  197. returnsLocation = this.target.OutputsLocation;
  198. }
  199. if (!string.IsNullOrEmpty(returns))
  200. {
  201. bool flag2 = ConditionEvaluator.EvaluateCondition<ProjectPropertyInstance, ProjectItemInstance>(this.target.KeepDuplicateOutputs, ParserOptions.AllowPropertiesAndItemLists, this.expander, ExpanderOptions.ExpandPropertiesAndItems, requestEntry.ProjectRootDirectory, this.target.KeepDuplicateOutputsLocation, projectLoggingContext.LoggingService, projectLoggingContext.BuildEventContext);
  202. List<ItemBucket> list3 = BatchingEngine.PrepareBatchingBuckets(this.GetBatchableParametersForTarget(), this.baseLookup, this.target.Location);
  203. if (flag2)
  204. {
  205. foreach (ItemBucket bucket3 in list3)
  206. {
  207. list2.AddRange(bucket3.Expander.ExpandIntoTaskItemsLeaveEscaped(returns, ExpanderOptions.ExpandAll, returnsLocation));
  208. }
  209. }
  210. else
  211. {
  212. HashSet<ProjectItemInstance.TaskItem> set = new HashSet<ProjectItemInstance.TaskItem>();
  213. foreach (ItemBucket bucket4 in list3)
  214. {
  215. foreach (ProjectItemInstance.TaskItem item in bucket4.Expander.ExpandIntoTaskItemsLeaveEscaped(returns, ExpanderOptions.ExpandAll, returnsLocation))
  216. {
  217. if (!set.Contains(item))
  218. {
  219. list2.Add(item);
  220. set.Add(item);
  221. }
  222. }
  223. }
  224. }
  225. }
  226. }
  227. finally
  228. {
  229. if (targetLoggingContext != null)
  230. {
  231. targetLoggingContext.LogTargetBatchFinished(projectFullPath, success, ((list2 != null) && (list2.Count > 0)) ? list2 : null);
  232. }
  233. }
  234. TargetResultCode failure = TargetResultCode.Skipped;
  235. switch (skipped)
  236. {
  237. case TaskResultCode.Success:
  238. failure = TargetResultCode.Success;
  239. break;
  240. case TaskResultCode.StopWithError:
  241. failure = TargetResultCode.Failure;
  242. break;
  243. default:
  244. ErrorUtilities.VerifyThrow(skipped == TaskResultCode.Skipped, "Aggregate result should have been 'Skipped', was {0}.", skipped);
  245. ErrorUtilities.VerifyThrow(failure == TargetResultCode.Skipped, "Target result should have been 'Skipped', was {0}.", failure);
  246. break;
  247. }
  248. this.targetResult = new TargetResult(list2.ToArray(), exception, failure);
  249. if (failure == TargetResultCode.Failure)
  250. {
  251. this.state = TargetEntryState.ErrorExecution;
  252. }
  253. else
  254. {
  255. this.state = TargetEntryState.Completed;
  256. }
  257. }
  258. internal TargetResult GatherResults()
  259. {
  260. this.VerifyState(this.state, TargetEntryState.Completed);
  261. ErrorUtilities.VerifyThrow(this.legacyCallTargetScopes == null, "We should have already left any legacy call target scopes.");
  262. return this.targetResult;
  263. }
  264. private List<string> GetBatchableParametersForTarget()
  265. {
  266. List<string> list = new List<string>();
  267. if (this.target.Inputs.Length > 0)
  268. {
  269. list.Add(this.target.Inputs);
  270. }
  271. if (this.target.Outputs.Length > 0)
  272. {
  273. list.Add(this.target.Outputs);
  274. }
  275. if ((this.target.Returns != null) && (this.target.Returns.Length > 0))
  276. {
  277. list.Add(this.target.Returns);
  278. }
  279. return list;
  280. }
  281. internal List<TargetSpecification> GetDependencies(ProjectLoggingContext projectLoggingContext)
  282. {
  283. this.VerifyState(this.state, TargetEntryState.Dependencies);
  284. this.GetTargetInstance();
  285. if (ExpressionShredder.ContainsMetadataExpressionOutsideTransform(this.target.Condition))
  286. {
  287. ProjectErrorUtilities.ThrowInvalidProject(this.target.ConditionLocation, "TargetConditionHasInvalidMetadataReference", this.target.Name, this.target.Condition);
  288. }
  289. if (!ConditionEvaluator.EvaluateCondition<ProjectPropertyInstance, ProjectItemInstance>(this.target.Condition, ParserOptions.AllowPropertiesAndItemLists, this.expander, ExpanderOptions.ExpandPropertiesAndItems, this.requestEntry.ProjectRootDirectory, this.target.ConditionLocation, projectLoggingContext.LoggingService, projectLoggingContext.BuildEventContext))
  290. {
  291. this.targetResult = new TargetResult(new ProjectItemInstance.TaskItem[0], TargetResultCode.Skipped);
  292. this.state = TargetEntryState.Completed;
  293. if (!projectLoggingContext.LoggingService.OnlyLogCriticalEvents)
  294. {
  295. string str = this.expander.ExpandIntoStringAndUnescape(this.target.Condition, ExpanderOptions.ExpandPropertiesAndItems, this.target.ConditionLocation);
  296. projectLoggingContext.LogComment(MessageImportance.Low, "TargetSkippedFalseCondition", new object[] { this.target.Name, this.target.Condition, str });
  297. }
  298. return new List<TargetSpecification>();
  299. }
  300. IList<string> list = this.expander.ExpandIntoStringListLeaveEscaped(this.target.DependsOnTargets, ExpanderOptions.ExpandPropertiesAndItems, this.target.DependsOnTargetsLocation);
  301. List<TargetSpecification> list2 = new List<TargetSpecification>(list.Count);
  302. foreach (string str2 in list)
  303. {
  304. string targetName = EscapingUtilities.UnescapeAll(str2);
  305. list2.Add(new TargetSpecification(targetName, this.target.DependsOnTargetsLocation));
  306. }
  307. this.state = TargetEntryState.Execution;
  308. return list2;
  309. }
  310. internal List<TargetSpecification> GetErrorTargets(ProjectLoggingContext projectLoggingContext)
  311. {
  312. this.VerifyState(this.state, TargetEntryState.ErrorExecution);
  313. ErrorUtilities.VerifyThrow(this.legacyCallTargetScopes == null, "We should have already left any legacy call target scopes.");
  314. List<TargetSpecification> list = new List<TargetSpecification>(this.target.OnErrorChildren.Count);
  315. foreach (ProjectOnErrorInstance instance in this.target.OnErrorChildren)
  316. {
  317. if (ConditionEvaluator.EvaluateCondition<ProjectPropertyInstance, ProjectItemInstance>(instance.Condition, ParserOptions.AllowPropertiesAndItemLists, this.expander, ExpanderOptions.ExpandPropertiesAndItems, this.requestEntry.ProjectRootDirectory, instance.ConditionLocation, projectLoggingContext.LoggingService, projectLoggingContext.BuildEventContext))
  318. {
  319. foreach (string str in this.expander.ExpandIntoStringListLeaveEscaped(instance.ExecuteTargets, ExpanderOptions.ExpandPropertiesAndItems, instance.ExecuteTargetsLocation))
  320. {
  321. string targetName = EscapingUtilities.UnescapeAll(str);
  322. list.Add(new TargetSpecification(targetName, instance.ExecuteTargetsLocation));
  323. }
  324. continue;
  325. }
  326. }
  327. if (this.targetResult == null)
  328. {
  329. this.targetResult = new TargetResult(new ProjectItemInstance.TaskItem[0], null, TargetResultCode.Failure);
  330. }
  331. this.state = TargetEntryState.Completed;
  332. return list;
  333. }
  334. private void GetTargetInstance()
  335. {
  336. this.requestEntry.RequestConfiguration.Project.Targets.TryGetValue(this.targetSpecification.TargetName, out this.target);
  337. ProjectErrorUtilities.VerifyThrowInvalidProject(this.target != null, this.targetSpecification.ReferenceLocation ?? this.requestEntry.RequestConfiguration.Project.ProjectFileLocation, "TargetDoesNotExist", this.targetSpecification.TargetName);
  338. }
  339. private TaskExecutionMode GetTaskExecutionMode(DependencyAnalysisResult analysis)
  340. {
  341. TaskExecutionMode inferOutputsOnly;
  342. if ((analysis == DependencyAnalysisResult.SkipUpToDate) || (analysis == DependencyAnalysisResult.IncrementalBuild))
  343. {
  344. inferOutputsOnly = TaskExecutionMode.InferOutputsOnly;
  345. }
  346. else
  347. {
  348. inferOutputsOnly = TaskExecutionMode.ExecuteTaskAndGatherOutputs;
  349. }
  350. if ((analysis != DependencyAnalysisResult.FullBuild) && (analysis != DependencyAnalysisResult.IncrementalBuild))
  351. {
  352. return inferOutputsOnly;
  353. }
  354. return (inferOutputsOnly | TaskExecutionMode.ExecuteTaskAndGatherOutputs);
  355. }
  356. internal void LeaveLegacyCallTargetScopes()
  357. {
  358. if (this.legacyCallTargetScopes != null)
  359. {
  360. while (this.legacyCallTargetScopes.Count != 0)
  361. {
  362. this.legacyCallTargetScopes.Pop().LeaveScope();
  363. }
  364. this.legacyCallTargetScopes = null;
  365. }
  366. }
  367. internal void MarkForError()
  368. {
  369. ErrorUtilities.VerifyThrow(this.state != TargetEntryState.Completed, "State must not be Completed. State is {0}.", this.state);
  370. this.state = TargetEntryState.ErrorExecution;
  371. }
  372. private TaskResult ProcessBucket(ITaskBuilder taskBuilder, TargetLoggingContext targetLoggingContext, TaskExecutionMode mode, Microsoft.Build.BackEnd.Lookup lookupForInference, Microsoft.Build.BackEnd.Lookup lookupForExecution)
  373. {
  374. TaskResult result = new TaskResult(TaskResultCode.Success);
  375. try
  376. {
  377. this.currentTaskBuilder = taskBuilder;
  378. for (int i = 0; (i < this.target.Children.Count) && !this.cancelled; i++)
  379. {
  380. ProjectTargetInstanceChild task = this.target.Children[i];
  381. if (DebuggerManager.DebuggingEnabled)
  382. {
  383. DebuggerManager.EnterState(task.Location, lookupForExecution.GlobalsForDebugging);
  384. }
  385. result = taskBuilder.ExecuteTask(targetLoggingContext, this.requestEntry, this.targetBuilderCallback, task, mode, lookupForInference, lookupForExecution);
  386. if (DebuggerManager.DebuggingEnabled)
  387. {
  388. DebuggerManager.LeaveState(task.Location);
  389. }
  390. if ((result.ResultCode != TaskResultCode.Success) && (result.ResultCode != TaskResultCode.ContinueWithError))
  391. {
  392. break;
  393. }
  394. }
  395. if (this.cancelled)
  396. {
  397. result = new TaskResult(TaskResultCode.Cancelled);
  398. }
  399. }
  400. finally
  401. {
  402. this.currentTaskBuilder = null;
  403. }
  404. return result;
  405. }
  406. private void VerifyState(TargetEntryState actual, TargetEntryState expected)
  407. {
  408. ErrorUtilities.VerifyThrow(actual == expected, "Expected state {1}. Got {0}", actual, expected);
  409. }
  410. internal bool ErrorTarget
  411. {
  412. [CompilerGenerated, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  413. get
  414. {
  415. return this.<ErrorTarget>k__BackingField;
  416. }
  417. [CompilerGenerated, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  418. set
  419. {
  420. this.<ErrorTarget>k__BackingField = value;
  421. }
  422. }
  423. internal Microsoft.Build.BackEnd.Lookup Lookup
  424. {
  425. [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  426. get
  427. {
  428. return this.baseLookup;
  429. }
  430. }
  431. internal string Name
  432. {
  433. get
  434. {
  435. return this.targetSpecification.TargetName;
  436. }
  437. }
  438. internal TargetEntry ParentEntry
  439. {
  440. [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  441. get
  442. {
  443. return this.parentTarget;
  444. }
  445. }
  446. internal IElementLocation ReferenceLocation
  447. {
  448. get
  449. {
  450. return this.targetSpecification.ReferenceLocation;
  451. }
  452. }
  453. internal BuildRequestEntry RequestEntry
  454. {
  455. [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  456. get
  457. {
  458. return this.requestEntry;
  459. }
  460. }
  461. internal TargetResult Result
  462. {
  463. [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  464. get
  465. {
  466. return this.targetResult;
  467. }
  468. }
  469. internal TargetEntryState State
  470. {
  471. [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  472. get
  473. {
  474. return this.state;
  475. }
  476. }
  477. internal bool StopProcessingOnCompletion
  478. {
  479. [CompilerGenerated, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  480. get
  481. {
  482. return this.<StopProcessingOnCompletion>k__BackingField;
  483. }
  484. [CompilerGenerated, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  485. set
  486. {
  487. this.<StopProcessingOnCompletion>k__BackingField = value;
  488. }
  489. }
  490. internal ProjectTargetInstance Target
  491. {
  492. get
  493. {
  494. if (this.target == null)
  495. {
  496. this.GetTargetInstance();
  497. }
  498. return this.target;
  499. }
  500. }
  501. }
  502. }