/// <summary> /// Expand (recursively) set of active targets to include targets which reference any /// of the active targets with BeforeTarget or AfterTarget. /// </summary> /// <param name="projectInstance">An MSBuild Project instance to use for context.</param> /// <param name="activeTargets"> /// Set of active targets. Will be modified in place to add targets that reference this /// graph with BeforeTarget or AfterTarget. /// </param> public static void AddBeforeAndAfterTargets(this ProjectInstance projectInstance, Dictionary <string, ProjectTargetInstance> activeTargets) { var newTargetsToConsider = true; while (newTargetsToConsider) { newTargetsToConsider = false; foreach (KeyValuePair <string, ProjectTargetInstance> pair in projectInstance.Targets) { string targetName = pair.Key; ProjectTargetInstance targetInstance = pair.Value; // If the target is not already in our list of active targets ... if (!activeTargets.ContainsKey(targetName)) { IEnumerable <string> hookedTargets = projectInstance.EvaluateValue(targetInstance.AfterTargets) .Concat(projectInstance.EvaluateValue(targetInstance.BeforeTargets)); foreach (string hookedTarget in hookedTargets) { // ... and it hooks a running target with BeforeTargets/AfterTargets ... if (activeTargets.ContainsKey(hookedTarget)) { // ... then add it to the list of running targets ... projectInstance.AddToActiveTargets(targetName, activeTargets); // ... and make a note to run again, since activeTargets has changed. newTargetsToConsider = true; } } } } } }
public void AddTargetAddsNewTarget() { string projectFileContent = @" <Project> <Target Name='a' /> </Project>"; ProjectRootElement rootElement = ProjectRootElement.Create(XmlReader.Create(new StringReader(projectFileContent))); ProjectInstance projectInstance = new ProjectInstance(rootElement); ProjectTargetInstance targetInstance = projectInstance.AddTarget("b", "1==1", "inputs", "outputs", "returns", "keepDuplicateOutputs", "dependsOnTargets", "beforeTargets", "afterTargets", true); Assert.Equal(2, projectInstance.Targets.Count); Assert.Equal(targetInstance, projectInstance.Targets["b"]); Assert.Equal("b", targetInstance.Name); Assert.Equal("1==1", targetInstance.Condition); Assert.Equal("inputs", targetInstance.Inputs); Assert.Equal("outputs", targetInstance.Outputs); Assert.Equal("returns", targetInstance.Returns); Assert.Equal("keepDuplicateOutputs", targetInstance.KeepDuplicateOutputs); Assert.Equal("dependsOnTargets", targetInstance.DependsOnTargets); Assert.Equal("beforeTargets", targetInstance.BeforeTargets); Assert.Equal("afterTargets", targetInstance.AfterTargets); Assert.Equal(projectInstance.ProjectFileLocation, targetInstance.Location); Assert.Equal(ElementLocation.EmptyLocation, targetInstance.ConditionLocation); Assert.Equal(ElementLocation.EmptyLocation, targetInstance.InputsLocation); Assert.Equal(ElementLocation.EmptyLocation, targetInstance.OutputsLocation); Assert.Equal(ElementLocation.EmptyLocation, targetInstance.ReturnsLocation); Assert.Equal(ElementLocation.EmptyLocation, targetInstance.KeepDuplicateOutputsLocation); Assert.Equal(ElementLocation.EmptyLocation, targetInstance.DependsOnTargetsLocation); Assert.Equal(ElementLocation.EmptyLocation, targetInstance.BeforeTargetsLocation); Assert.Equal(ElementLocation.EmptyLocation, targetInstance.AfterTargetsLocation); Assert.True(targetInstance.ParentProjectSupportsReturnsAttribute); }
public MSBuildTarget(ProjectTargetInstance pti, Project project, MSBuildFile parent = null) { this.Target = pti; this.Name = pti.Name; this.Inputs = pti.Inputs; this.Outputs = pti.Outputs; this.Location = pti.FullPath; this.DependsOnTargets = pti.DependsOnTargets; this.TargetColor = "Black"; this.FontStyle = "Normal"; if (!string.IsNullOrEmpty(this.Target.Condition)) { this.TargetCondition = this.Target.Condition; this.TargetColor = "Gray"; this.FontStyle = "Italic"; } if (project.Xml.DefaultTargets.Contains(pti.Name)) { this.TargetColor = "MediumBlue"; } if (project.Xml.InitialTargets.Contains(pti.Name)) { this.TargetColor = "LimeGreen"; } if (project.Xml.InitialTargets.Contains(pti.Name) && project.Xml.DefaultTargets.Contains(pti.Name)) { this.TargetColor = "Gold"; } this.Targets = new ObservableCollection <MSBuildTarget>(); string targets = project.ExpandString(pti.DependsOnTargets); targets = this.formatRegex.Replace(targets, string.Empty); int i = 0; foreach (var target in targets.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { this.Targets.Add(new MSBuildTarget(target)); i++; } foreach (var x in project.Xml.Targets.Where(x => x.Name == pti.Name)) { this.BeforeTargets = x.BeforeTargets; this.AfterTargets = x.AfterTargets; } if (parent != null) { this.Parent = parent; } }
/// <summary> /// Creates a new target logging context from an existing project context and target. /// </summary> internal TargetLoggingContext(ProjectLoggingContext projectLoggingContext, string projectFullPath, ProjectTargetInstance target, string parentTargetName, TargetBuiltReason buildReason) : base(projectLoggingContext) { _projectLoggingContext = projectLoggingContext; _target = target; this.BuildEventContext = LoggingService.LogTargetStarted(projectLoggingContext.BuildEventContext, target.Name, projectFullPath, target.Location.File, parentTargetName, buildReason); this.IsValid = true; }
public void ProjectTargetInstanceCanSerializeViaTranslator( ReadOnlyCollection <ProjectTargetInstanceChild> children, ReadOnlyCollection <ProjectOnErrorInstance> errorChildren) { var original = CreateTarget(null, children, errorChildren); ((ITranslatable)original).Translate(TranslationHelpers.GetWriteTranslator()); var copy = ProjectTargetInstance.FactoryForDeserialization(TranslationHelpers.GetReadTranslator()); Assert.Equal(original, copy, new TargetComparer()); }
internal static MSBuildFile GetFile(FileInfo file) { using (ProjectCollection loadedProjects = new ProjectCollection()) { Project currentProject = loadedProjects.GetLoadedProjects(file.FullName).FirstOrDefault(); if (currentProject != null) { loadedProjects.UnloadProject(currentProject); } loadedProjects.LoadProject(file.FullName); currentProject = loadedProjects.GetLoadedProjects(file.FullName).FirstOrDefault(); MSBuildFile m = new MSBuildFile(currentProject); if (currentProject.Targets != null) { SortedDictionary <string, ProjectTargetInstance> sortedTargets = new SortedDictionary <string, ProjectTargetInstance>(currentProject.Targets); foreach (var t in sortedTargets) { ProjectTargetInstance pti = t.Value; m.Targets.Add(new MSBuildTarget(pti, currentProject, m)); } } foreach (var us in currentProject.Xml.UsingTasks) { m.Usings.Add(new MSBuildUsing(currentProject, us)); } foreach (ResolvedImport import in currentProject.Imports) { m.Imports.Add(new MSBuildImport(import)); } foreach (var property in currentProject.Properties) { m.Properties.Add(new MSBuildProperties(property)); } if (currentProject.AllEvaluatedItems != null) { foreach (var item in currentProject.AllEvaluatedItems) { m.Items.Add(new MSBuildItems(item.ItemType, item.UnevaluatedInclude, item.EvaluatedInclude, item.IsImported)); } } return(m); } }
public void TargetOverride_Escaped2() { ProjectRootElement projectXml = ProjectRootElement.Create(); projectXml.AddTarget("t;").Inputs = "i1"; projectXml.AddTarget("t%3b").Inputs = "i2"; Project project = new Project(projectXml); ProjectInstance instance = project.CreateProjectInstance(); ProjectTargetInstance target = instance.Targets["t;"]; Assert.AreEqual("i2", target.Inputs); }
public static int GetNumDependentTargets(this ProjectTargetInstance target, Project project) { if (target == null) { throw new ArgumentNullException("target"); } if (project == null) { throw new ArgumentNullException("project"); } string depndsOnTargets = target.DependsOnTargets; IList <string> targetsList = target.GetDependsOnTargetsAsList(project); return(targetsList.Count()); }
/// <summary> /// Create a ProjectTargetInstance with some parameters /// </summary> private static ProjectTargetInstance GetSampleTargetInstance() { string content = @" <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' > <Target Name='t' Inputs='i' Outputs='o' Condition='c' DependsOnTargets='d' KeepDuplicateOutputs='k' Returns='r'> <t1/> </Target> </Project> "; ProjectRootElement xml = ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); Project project = new Project(xml); ProjectInstance instance = project.CreateProjectInstance(); ProjectTargetInstance target = instance.Targets["t"]; return(target); }
public void TraversalTargetsShouldBeConditionedOnIsGraphBuild(string target) { ProjectTargetInstance traversalTarget = ProjectCreator .Templates .TraversalProject( null, GetTempFile("dirs.proj")) .Save() .Project.Targets.Values.FirstOrDefault(t => t.Name.Equals(target, StringComparison.OrdinalIgnoreCase)); traversalTarget.ShouldNotBeNull(); traversalTarget.Condition .Replace(" ", string.Empty) .Replace('\"', '\'') .ShouldContain("'$(IsGraphBuild)'!='true'"); }
private static ProjectTargetInstance GetSampleTargetInstance() { string content = @" <Project> <Target Name='t' Inputs='i' Outputs='o' Condition='c' DependsOnTargets='d' BeforeTargets='b' AfterTargets='a' KeepDuplicateOutputs='k' Returns='r'> <t1/> </Target> </Project> "; ProjectRootElement xml = ProjectRootElement.Create(XmlReader.Create(new StringReader(content))); Project project = new Project(xml); ProjectInstance instance = project.CreateProjectInstance(); ProjectTargetInstance target = instance.Targets["t"]; return(target); }
public void Accessors() { ProjectTargetInstance target = GetSampleTargetInstance(); Assert.AreEqual("t", target.Name); Assert.AreEqual("c", target.Condition); Assert.AreEqual("i", target.Inputs); Assert.AreEqual("o", target.Outputs); Assert.AreEqual("d", target.DependsOnTargets); Assert.AreEqual("k", target.KeepDuplicateOutputs); Assert.AreEqual("r", target.Returns); Assert.AreEqual("t1", ((ProjectTaskInstance)target.Children[0]).Name); IList <ProjectTaskInstance> tasks = Helpers.MakeList(target.Tasks); Assert.AreEqual(1, tasks.Count); Assert.AreEqual("t1", tasks[0].Name); }
public void FileLocationAvailableEvenAfterEdits() { string path = null; try { path = Microsoft.Build.Shared.FileUtilities.GetTemporaryFile(); ProjectRootElement projectXml = ProjectRootElement.Create(path); projectXml.Save(); projectXml.AddTarget("t"); Project project = new Project(projectXml); ProjectTargetInstance target = project.Targets["t"]; Assert.AreEqual(project.FullPath, target.FullPath); } finally { File.Delete(path); } }
public static IList <string> GetDependsOnTargetsAsList(this ProjectTargetInstance target, Project project) { if (target == null) { throw new ArgumentNullException("target"); } if (project == null) { throw new ArgumentNullException("project"); } List <string> targets = new List <string>(); string depTargets = target.DependsOnTargets != null ? target.DependsOnTargets : string.Empty; string depTargetsEvaluated = project.ExpandString(depTargets); string[] dtArray = depTargetsEvaluated.Split(';'); dtArray.ToList().ForEach(t => { if (!string.IsNullOrWhiteSpace(t)) { string tName = t.Trim(); if (!string.IsNullOrWhiteSpace(tName) && string.Compare(";", tName, StringComparison.InvariantCultureIgnoreCase) != 0) { targets.Add(tName); } } }); int numTarges = targets != null?targets.Count() : 0; string tempDebug = null; if (numTarges >= 1) { tempDebug = targets[0]; } return(targets); }
bool RunBuildTask(ProjectTargetInstance target, ProjectTaskInstance taskInstance, TargetResult targetResult, InternalBuildArguments args) { var request = submission.BuildRequest; var host = request.HostServices == null ? null : request.HostServices.GetHostObject(request.ProjectFullPath, target.Name, taskInstance.Name); // Create Task instance. var factoryIdentityParameters = new Dictionary <string, string> (); factoryIdentityParameters ["MSBuildRuntime"] = taskInstance.MSBuildRuntime; factoryIdentityParameters ["MSBuildArchitecture"] = taskInstance.MSBuildArchitecture; var task = args.BuildTaskFactory.CreateTask(taskInstance.Name, factoryIdentityParameters, this); if (task == null) { throw new InvalidOperationException(string.Format("TaskFactory {0} returned null Task", args.BuildTaskFactory)); } LogMessageEvent(new BuildMessageEventArgs(string.Format("Using task {0} from {1}", taskInstance.Name, task.GetType()), null, null, MessageImportance.Low)); task.HostObject = host; task.BuildEngine = this; // Prepare task parameters. var evaluator = new ExpressionEvaluator(project); var evaluatedTaskParams = taskInstance.Parameters.Select(p => new KeyValuePair <string, string> (p.Key, project.ExpandString(evaluator, p.Value))); var requiredProps = task.GetType().GetProperties() .Where(p => p.CanWrite && p.GetCustomAttributes(typeof(RequiredAttribute), true).Any()); var missings = requiredProps.Where(p => !evaluatedTaskParams.Any(tp => tp.Key.Equals(p.Name, StringComparison.OrdinalIgnoreCase))); if (missings.Any()) { throw new InvalidOperationException(string.Format("Task {0} of type {1} is used without specifying mandatory property: {2}", taskInstance.Name, task.GetType(), string.Join(", ", missings.Select(p => p.Name).ToArray()))); } foreach (var p in evaluatedTaskParams) { switch (p.Key.ToLower()) { case "condition": case "continueonerror": continue; } var prop = task.GetType().GetProperty(p.Key); if (prop == null) { throw new InvalidOperationException(string.Format("Task {0} does not have property {1}", taskInstance.Name, p.Key)); } if (!prop.CanWrite) { throw new InvalidOperationException(string.Format("Task {0} has property {1} but it is read-only.", taskInstance.Name, p.Key)); } if (string.IsNullOrEmpty(p.Value) && !requiredProps.Contains(prop)) { continue; } try { prop.SetValue(task, ConvertTo(p.Value, prop.PropertyType, evaluator), null); } catch (Exception ex) { throw new InvalidOperationException(string.Format("Failed to convert '{0}' for property '{1}' of type {2}", p.Value, prop.Name, prop.PropertyType), ex); } } // Do execute task. bool taskSuccess = false; event_source.FireTaskStarted(this, new TaskStartedEventArgs("Task Started", null, project.FullPath, taskInstance.FullPath, taskInstance.Name)); try { taskSuccess = task.Execute(); if (!taskSuccess) { targetResult.Failure(null); if (!ContinueOnError) { return(false); } } else { // Evaluate task output properties and items. foreach (var to in taskInstance.Outputs) { if (!project.EvaluateCondition(to.Condition)) { continue; } var toItem = to as ProjectTaskOutputItemInstance; var toProp = to as ProjectTaskOutputPropertyInstance; string taskParameter = toItem != null ? toItem.TaskParameter : toProp.TaskParameter; var pi = task.GetType().GetProperty(taskParameter); if (pi == null) { throw new InvalidOperationException(string.Format("Task {0} does not have property {1} specified as TaskParameter", taskInstance.Name, toItem.TaskParameter)); } if (!pi.CanRead) { throw new InvalidOperationException(string.Format("Task {0} has property {1} specified as TaskParameter, but it is write-only", taskInstance.Name, toItem.TaskParameter)); } var value = pi.GetValue(task, null); var valueString = ConvertFrom(value); if (toItem != null) { LogMessageEvent(new BuildMessageEventArgs(string.Format("Output Item {0} from TaskParameter {1}: {2}", toItem.ItemType, toItem.TaskParameter, valueString), null, null, MessageImportance.Low)); Action <ITaskItem> addItem = i => { var metadata = new ArrayList(i.MetadataNames).ToArray().Cast <string> ().Select(n => new KeyValuePair <string, string> (n, i.GetMetadata(n))); args.Project.AddItem(toItem.ItemType, i.ItemSpec, metadata); }; var taskItemArray = value as ITaskItem []; if (taskItemArray != null) { foreach (var ti in taskItemArray) { addItem(ti); } } else { var taskItem = value as ITaskItem; if (taskItem != null) { addItem(taskItem); } else { foreach (var item in valueString.Split(';')) { args.Project.AddItem(toItem.ItemType, item); } } } } else { LogMessageEvent(new BuildMessageEventArgs(string.Format("Output Property {0} from TaskParameter {1}: {2}", toProp.PropertyName, toProp.TaskParameter, valueString), null, null, MessageImportance.Low)); args.Project.SetProperty(toProp.PropertyName, valueString); } } } } finally { event_source.FireTaskFinished(this, new TaskFinishedEventArgs("Task Finished", null, project.FullPath, taskInstance.FullPath, taskInstance.Name, taskSuccess)); } return(true); }
// FIXME: Exception should be caught at caller site. bool DoBuildTarget(ProjectTargetInstance target, TargetResult targetResult, InternalBuildArguments args) { var request = submission.BuildRequest; // Here we check cancellation (only after TargetStarted event). if (args.CheckCancel()) { targetResult.Failure(new BuildAbortedException("Build has canceled")); return(false); } try { foreach (var child in target.Children) { // Evaluate additional target properties var tp = child as ProjectPropertyGroupTaskInstance; if (tp != null) { if (!args.Project.EvaluateCondition(tp.Condition)) { continue; } foreach (var p in tp.Properties) { if (!args.Project.EvaluateCondition(p.Condition)) { continue; } var value = args.Project.ExpandString(p.Value); project.SetProperty(p.Name, value); } continue; } var ii = child as ProjectItemGroupTaskInstance; if (ii != null) { if (!args.Project.EvaluateCondition(ii.Condition)) { continue; } foreach (var item in ii.Items) { if (!args.Project.EvaluateCondition(item.Condition)) { continue; } project.AddItem(item.ItemType, project.ExpandString(item.Include)); } continue; } var task = child as ProjectTaskInstance; if (task != null) { current_task = task; if (!args.Project.EvaluateCondition(task.Condition)) { LogMessageEvent(new BuildMessageEventArgs(string.Format("Task '{0}' was skipped because condition '{1}' wasn't met.", task.Name, task.Condition), null, null, MessageImportance.Low)); continue; } if (!RunBuildTask(target, task, targetResult, args)) { return(false); } continue; } var onError = child as ProjectOnErrorInstance; if (onError != null) { continue; // evaluated under catch clause. } throw new NotSupportedException(string.Format("Unexpected Target element children \"{0}\"", child.GetType())); } } catch (Exception ex) { // fallback task specified by OnError element foreach (var c in target.Children.OfType <ProjectOnErrorInstance> ()) { if (!args.Project.EvaluateCondition(c.Condition)) { continue; } foreach (var fallbackTarget in project.ExpandString(c.ExecuteTargets).Split(';')) { BuildTargetByName(fallbackTarget, args); } } int line = target.Location != null ? target.Location.Line : 0; int col = target.Location != null ? target.Location.Column : 0; LogErrorEvent(new BuildErrorEventArgs(null, null, target.FullPath, line, col, 0, 0, ex.Message, null, null)); targetResult.Failure(ex); return(false); } return(true); }
/// <summary> /// Marks this element as dirty. /// </summary> internal override void MarkDirty(string reason, string param) { base.MarkDirty(reason, param); TargetInstance = null; }
public void AddTarget(ProjectTargetInstance target) { throw new NotSupportedException(); }
/// <summary> /// Parse a build.proj file, that already has all parsed dependent projects. /// Initially checks that build.proj file exists and had a newer modification time compared to the project file. /// </summary> private void ParseBuildProj() { try { if (_msbuildProj == null) { return; } // build.proj exists? string buildProjFile = Path.Combine(Path.GetDirectoryName(_msbuildProj.FullPath), "build.proj"); if (!File.Exists(buildProjFile)) { return; } // build.proj is newer than the project file? if (File.GetLastWriteTime(buildProjFile) < File.GetLastWriteTime(_msbuildProj.FullPath)) { return; } // Parse it! _allReferences = new List <string>(); _projReferences = new List <string>(); Project buildProj = new Project(buildProjFile); ProjectTargetInstance tgt = buildProj.Targets["Build"]; if (tgt == null) { return; } foreach (ProjectTaskInstance tsk in tgt.Tasks) { if (tsk.Name.Equals("MSBuild")) { if (tsk.Parameters.Keys.Contains("Projects")) { // Once a build.proj includes our project we know that subsequent project depend on us. string p = tsk.Parameters["Projects"]; if (Path.GetFileName(p).Equals(Path.GetFileName(_msbuildProj.FullPath), StringComparison.OrdinalIgnoreCase)) { break; } _allReferences.Add(p); AddProjectReference(p); using (ParseProject po = new ParseProject(p)) { _allReferences.AddRange(po.AllReferences); AddProjectReferences(po.ProjectReferences); } } } } } catch (Exception ex) { ErrorManager.DebugF("Failed parsing build.proj: {0}", ex.Message); _allReferences = null; _projReferences = null; return; } }
public TargetDescriptor(ProjectTargetInstance target) { _target = target; }
/// <summary> /// Parses the input and output files for copy tasks of given target. /// </summary> private static void ParseCopyTask( ProjectTargetInstance target, ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { // Get all Copy tasks from targets. List <ProjectTaskInstance> tasks = target.Tasks .Where(task => string.Equals(task.Name, CopyTaskName, StringComparison.Ordinal)) .ToList(); if (tasks.Any() && projectInstance.EvaluateConditionCarefully(target.Condition)) { foreach (ProjectTaskInstance task in tasks) { if (projectInstance.EvaluateConditionCarefully(task.Condition)) { var inputs = new FileExpressionList( task.Parameters[CopyTaskSourceFiles], projectInstance, task); if (inputs.NumExpressions == 0) { continue; } foreach (var file in inputs.DedupedFiles) { predictionReporter.ReportInputFile(file); } bool hasDestinationFolder = task.Parameters.TryGetValue( CopyTaskDestinationFolder, out string destinationFolder); bool hasDestinationFiles = task.Parameters.TryGetValue( CopyTaskDestinationFiles, out string destinationFiles); if (hasDestinationFiles || hasDestinationFolder) { // Having both is an MSBuild violation, which it will complain about. if (hasDestinationFolder && hasDestinationFiles) { continue; } string destination = destinationFolder ?? destinationFiles; var outputs = new FileExpressionList(destination, projectInstance, task); // When using batch tokens, the user should specify exactly one total token, and it must appear in both the input and output. // Doing otherwise should be a BuildCop error. If not using batch tokens, then any number of other tokens is fine. if ((outputs.NumBatchExpressions == 1 && outputs.NumExpressions == 1 && inputs.NumBatchExpressions == 1 && inputs.NumExpressions == 1) || (outputs.NumBatchExpressions == 0 && inputs.NumBatchExpressions == 0)) { ProcessOutputs(inputs, outputs, hasDestinationFolder, predictionReporter); } else { // Ignore case we cannot handle. } } else { // Ignore malformed case. } } } } }
internal ProjectTargetElement GetTargetElement(ProjectTargetInstance value) { var importTarget = Project.Imports.Where(im => im.ImportedProject.FullPath == value.FullPath).First(); return(importTarget.ImportedProject.Targets.Where(t => t.Name == value.Name).First()); }
/// <summary> /// Log that a target has started /// </summary> internal TargetLoggingContext LogTargetBatchStarted(string projectFullPath, ProjectTargetInstance target, string parentTargetName, TargetBuiltReason buildReason) { ErrorUtilities.VerifyThrow(this.IsValid, "invalid"); return(new TargetLoggingContext(this, projectFullPath, target, parentTargetName, buildReason)); }
public static IllegalProjectFileElement FromTarget(ProjectTargetInstance target) { return(new IllegalProjectFileElement(new TargetDescriptor(target))); }