Example #1
0
        void BuildProject(InternalBuildArguments args)
        {
            var request    = submission.BuildRequest;
            var parameters = submission.BuildManager.OngoingBuildParameters;

            this.project = args.Project;

            string directoryBackup = Directory.GetCurrentDirectory();

            Directory.SetCurrentDirectory(project.Directory);
            event_source.FireBuildStarted(this, new BuildStartedEventArgs("Build Started", null, DateTime.Now));

            try {
                var initialGlobalPropertiesFormatted = "Initial Global Properties:\n" + string.Join(Environment.NewLine, project.Properties.OrderBy(p => p.Name).Where(p => p.IsImmutable).Select(p => string.Format("{0} = {1}", p.Name, p.EvaluatedValue)).ToArray());
                LogMessageEvent(new BuildMessageEventArgs(initialGlobalPropertiesFormatted, null, null, MessageImportance.Low));
                var initialProjectPropertiesFormatted = "Initial Project Properties:\n" + string.Join(Environment.NewLine, project.Properties.OrderBy(p => p.Name).Where(p => !p.IsImmutable).Select(p => string.Format("{0} = {1}", p.Name, p.EvaluatedValue)).ToArray());
                LogMessageEvent(new BuildMessageEventArgs(initialProjectPropertiesFormatted, null, null, MessageImportance.Low));
                var initialItemsFormatted = "Initial Items:\n" + string.Join(Environment.NewLine, project.Items.OrderBy(i => i.ItemType).Select(i => string.Format("{0} : {1}", i.ItemType, i.EvaluatedInclude)).ToArray());
                LogMessageEvent(new BuildMessageEventArgs(initialItemsFormatted, null, null, MessageImportance.Low));

                // null targets -> success. empty targets -> success(!)
                foreach (var targetName in (request.ProjectInstance.InitialTargets).Where(t => t != null))
                {
                    BuildTargetByName(targetName, args);
                }
                if (request.TargetNames == null)
                {
                    args.Result.OverallResult = args.CheckCancel() ? BuildResultCode.Failure : args.Result.ResultsByTarget.Any(p => p.Value.ResultCode == TargetResultCode.Failure) ? BuildResultCode.Failure : BuildResultCode.Success;
                }
                else
                {
                    foreach (var targetName in (args.TargetNames ?? request.TargetNames).Where(t => t != null))
                    {
                        if (!BuildTargetByName(targetName, args))
                        {
                            break;
                        }
                    }

                    // FIXME: check .NET behavior, whether cancellation always results in failure.
                    args.Result.OverallResult = args.CheckCancel() ? BuildResultCode.Failure : args.Result.ResultsByTarget.Any(p => p.Value.ResultCode == TargetResultCode.Failure) ? BuildResultCode.Failure : BuildResultCode.Success;
                }
            } catch (Exception ex) {
                args.Result.OverallResult = BuildResultCode.Failure;
                LogErrorEvent(new BuildErrorEventArgs(null, null, project.FullPath, 0, 0, 0, 0, "Unhandled exception occured during a build", null, null));
                LogMessageEvent(new BuildMessageEventArgs("Exception details: " + ex, null, null, MessageImportance.Low));
                throw;                 // BuildSubmission re-catches this.
            } finally {
                event_source.FireBuildFinished(this, new BuildFinishedEventArgs("Build Finished.", null, args.Result.OverallResult == BuildResultCode.Success, DateTime.Now));
                Directory.SetCurrentDirectory(directoryBackup);
            }
        }
Example #2
0
        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);
        }
Example #3
0
        // 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);
        }
Example #4
0
        bool BuildTargetByName(string targetName, InternalBuildArguments args)
        {
            var request    = submission.BuildRequest;
            var parameters = submission.BuildManager.OngoingBuildParameters;
            ProjectTargetInstance target;
            TargetResult          dummyResult;

            if (args.Result.ResultsByTarget.TryGetValue(targetName, out dummyResult) && dummyResult.ResultCode == TargetResultCode.Success)
            {
                LogMessageEvent(new BuildMessageEventArgs(string.Format("Target '{0}' was skipped because it was already built successfully.", targetName), null, null, MessageImportance.Low));
                return(true);                // do not add result.
            }

            var targetResult = new TargetResult();

            // null key is allowed and regarded as blind success(!) (as long as it could retrieve target)
            if (!request.ProjectInstance.Targets.TryGetValue(targetName, out target))
            {
                // FIXME: from MSBuild.exe it is given MSB4057. Can we assign a number too?
                throw new InvalidOperationException(string.Format("target '{0}' was not found in project '{1}'", targetName, project.FullPath));
            }
            else if (!args.Project.EvaluateCondition(target.Condition))
            {
                LogMessageEvent(new BuildMessageEventArgs(string.Format("Target '{0}' was skipped because condition '{1}' was not met.", target.Name, target.Condition), null, null, MessageImportance.Low));
                targetResult.Skip();
            }
            else
            {
                // process DependsOnTargets first.
                foreach (var dep in project.ExpandString(target.DependsOnTargets).Split(';').Select(s => s.Trim()).Where(s => !string.IsNullOrEmpty(s)))
                {
                    LogMessageEvent(new BuildMessageEventArgs(string.Format("Target '{0}' depends on '{1}'.", target.Name, dep), null, null, MessageImportance.Low));
                    if (!BuildTargetByName(dep, args))
                    {
                        LogMessageEvent(new BuildMessageEventArgs(string.Format("Quit target '{0}', as dependency target '{1}' has failed.", target.Name, dep), null, null, MessageImportance.Low));
                        return(false);
                    }
                }

                Func <string, ITaskItem> creator = s => new TargetOutputTaskItem()
                {
                    ItemSpec = s
                };

                event_source.FireTargetStarted(this, new TargetStartedEventArgs("Target Started", null, target.Name, project.FullPath, target.FullPath));
                try {
                    // FIXME: examine in which scenario Inputs/Outputs inconsistency results in errors. Now it rather prevents csproj build.

                    /*if (!string.IsNullOrEmpty (target.Inputs) != !string.IsNullOrEmpty (target.Outputs)) {
                     *      targetResult.Failure (new InvalidProjectFileException (target.Location, null, string.Format ("Target {0} has mismatching Inputs and Outputs specification. When one is specified, another one has to be specified too.", targetName), null, null, null));
                     * } else*/{
                        bool skip = false;
                        if (!string.IsNullOrEmpty(target.Inputs))
                        {
                            var inputs = args.Project.GetAllItems(target.Inputs, string.Empty, creator, creator, s => true, (t, s) => {
                            });
                            if (!inputs.Any())
                            {
                                LogMessageEvent(new BuildMessageEventArgs(string.Format("Target '{0}' was skipped because there is no input.", target.Name), null, null, MessageImportance.Low));
                                skip = true;
                            }
                            else
                            {
                                var outputs      = args.Project.GetAllItems(target.Outputs, string.Empty, creator, creator, s => true, (t, s) => {
                                });
                                var needsUpdates = GetOlderOutputsThanInputs(inputs, outputs).FirstOrDefault();
                                if (needsUpdates != null)
                                {
                                    LogMessageEvent(new BuildMessageEventArgs(string.Format("Target '{0}' needs to be built because new output {1} is needed.", target.Name, needsUpdates.ItemSpec), null, null, MessageImportance.Low));
                                }
                                else
                                {
                                    LogMessageEvent(new BuildMessageEventArgs(string.Format("Target '{0}' was skipped because all the outputs are newer than all the inputs.", target.Name), null, null, MessageImportance.Low));
                                    skip = true;
                                }
                            }
                        }
                        if (skip)
                        {
                            targetResult.Skip();
                        }
                        else
                        {
                            if (DoBuildTarget(target, targetResult, args))
                            {
                                var items = args.Project.GetAllItems(target.Outputs, string.Empty, creator, creator, s => true, (t, s) => {
                                });
                                targetResult.Success(items);
                            }
                        }
                    }
                } finally {
                    event_source.FireTargetFinished(this, new TargetFinishedEventArgs("Target Finished", null, targetName, project.FullPath, target.FullPath, targetResult.ResultCode != TargetResultCode.Failure));
                }
            }
            args.AddTargetResult(targetName, targetResult);

            return(targetResult.ResultCode != TargetResultCode.Failure);
        }
Example #5
0
		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> ();
			#if NET_4_5
			factoryIdentityParameters ["MSBuildRuntime"] = taskInstance.MSBuildRuntime;
			factoryIdentityParameters ["MSBuildArchitecture"] = taskInstance.MSBuildArchitecture;
			#endif
			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;
		}
Example #6
0
		// 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;
		}
Example #7
0
		bool BuildTargetByName (string targetName, InternalBuildArguments args)
		{
			var request = submission.BuildRequest;
			var parameters = submission.BuildManager.OngoingBuildParameters;
			ProjectTargetInstance target;
			TargetResult dummyResult;

			if (args.Result.ResultsByTarget.TryGetValue (targetName, out dummyResult) && dummyResult.ResultCode == TargetResultCode.Success) {
				LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because it was already built successfully.", targetName), null, null, MessageImportance.Low));
				return true; // do not add result.
			}
			
			var targetResult = new TargetResult ();

			// null key is allowed and regarded as blind success(!) (as long as it could retrieve target)
			if (!request.ProjectInstance.Targets.TryGetValue (targetName, out target))
				// FIXME: from MSBuild.exe it is given MSB4057. Can we assign a number too?
				throw new InvalidOperationException (string.Format ("target '{0}' was not found in project '{1}'", targetName, project.FullPath));
			else if (!args.Project.EvaluateCondition (target.Condition)) {
				LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because condition '{1}' was not met.", target.Name, target.Condition), null, null, MessageImportance.Low));
				targetResult.Skip ();
			} else {
				// process DependsOnTargets first.
				foreach (var dep in project.ExpandString (target.DependsOnTargets).Split (';').Select (s => s.Trim ()).Where (s => !string.IsNullOrEmpty (s))) {
					LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' depends on '{1}'.", target.Name, dep), null, null, MessageImportance.Low));
					if (!BuildTargetByName (dep, args)) {
						LogMessageEvent (new BuildMessageEventArgs (string.Format ("Quit target '{0}', as dependency target '{1}' has failed.", target.Name, dep), null, null, MessageImportance.Low));
						return false;
					}
				}
				
				Func<string,ITaskItem> creator = s => new TargetOutputTaskItem () { ItemSpec = s };
			
				event_source.FireTargetStarted (this, new TargetStartedEventArgs ("Target Started", null, target.Name, project.FullPath, target.FullPath));
				try {
					// FIXME: examine in which scenario Inputs/Outputs inconsistency results in errors. Now it rather prevents csproj build.
					/*if (!string.IsNullOrEmpty (target.Inputs) != !string.IsNullOrEmpty (target.Outputs)) {
						targetResult.Failure (new InvalidProjectFileException (target.Location, null, string.Format ("Target {0} has mismatching Inputs and Outputs specification. When one is specified, another one has to be specified too.", targetName), null, null, null));
					} else*/ {
						bool skip = false;
						if (!string.IsNullOrEmpty (target.Inputs)) {
							var inputs = args.Project.GetAllItems (target.Inputs, string.Empty, creator, creator, s => true, (t, s) => {
							});
							if (!inputs.Any ()) {
								LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because there is no input.", target.Name), null, null, MessageImportance.Low));
								skip = true;
							} else {
								var outputs = args.Project.GetAllItems (target.Outputs, string.Empty, creator, creator, s => true, (t, s) => {
								});
								var needsUpdates = GetOlderOutputsThanInputs (inputs, outputs).FirstOrDefault ();
								if (needsUpdates != null)
									LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' needs to be built because new output {1} is needed.", target.Name, needsUpdates.ItemSpec), null, null, MessageImportance.Low));
								else {
									LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because all the outputs are newer than all the inputs.", target.Name), null, null, MessageImportance.Low));
									skip = true;
								}
							}
						}
						if (skip) {
							targetResult.Skip ();
						} else {
							if (DoBuildTarget (target, targetResult, args)) {
								var items = args.Project.GetAllItems (target.Outputs, string.Empty, creator, creator, s => true, (t, s) => {
								});
								targetResult.Success (items);
							}
						}
					}
				} finally {
					event_source.FireTargetFinished (this, new TargetFinishedEventArgs ("Target Finished", null, targetName, project.FullPath, target.FullPath, targetResult.ResultCode != TargetResultCode.Failure));
				}
			}
			args.AddTargetResult (targetName, targetResult);
			
			return targetResult.ResultCode != TargetResultCode.Failure;
		}
Example #8
0
		void BuildProject (InternalBuildArguments args)
		{
			var request = submission.BuildRequest;
			var parameters = submission.BuildManager.OngoingBuildParameters;
			this.project = args.Project;

			string directoryBackup = Directory.GetCurrentDirectory ();
			Directory.SetCurrentDirectory (project.Directory);
			event_source.FireBuildStarted (this, new BuildStartedEventArgs ("Build Started", null, DateTime.Now));
			
			try {
				
				var initialGlobalPropertiesFormatted = "Initial Global Properties:\n" + string.Join (Environment.NewLine, project.Properties.OrderBy (p => p.Name).Where (p => p.IsImmutable).Select (p => string.Format ("{0} = {1}", p.Name, p.EvaluatedValue)).ToArray ());
				LogMessageEvent (new BuildMessageEventArgs (initialGlobalPropertiesFormatted, null, null, MessageImportance.Low));
				var initialProjectPropertiesFormatted = "Initial Project Properties:\n" + string.Join (Environment.NewLine, project.Properties.OrderBy (p => p.Name).Where (p => !p.IsImmutable).Select (p => string.Format ("{0} = {1}", p.Name, p.EvaluatedValue)).ToArray ());
				LogMessageEvent (new BuildMessageEventArgs (initialProjectPropertiesFormatted, null, null, MessageImportance.Low));
				var initialItemsFormatted = "Initial Items:\n" + string.Join (Environment.NewLine, project.Items.OrderBy (i => i.ItemType).Select (i => string.Format ("{0} : {1}", i.ItemType, i.EvaluatedInclude)).ToArray ());
				LogMessageEvent (new BuildMessageEventArgs (initialItemsFormatted, null, null, MessageImportance.Low));
				
				// null targets -> success. empty targets -> success(!)
				foreach (var targetName in (request.ProjectInstance.InitialTargets).Where (t => t != null))
					BuildTargetByName (targetName, args);
				if (request.TargetNames == null)
					args.Result.OverallResult = args.CheckCancel () ? BuildResultCode.Failure : args.Result.ResultsByTarget.Any (p => p.Value.ResultCode == TargetResultCode.Failure) ? BuildResultCode.Failure : BuildResultCode.Success;
				else {
					foreach (var targetName in (args.TargetNames ?? request.TargetNames).Where (t => t != null)) {
						if (!BuildTargetByName (targetName, args))
							break;
					}
			
					// FIXME: check .NET behavior, whether cancellation always results in failure.
					args.Result.OverallResult = args.CheckCancel () ? BuildResultCode.Failure : args.Result.ResultsByTarget.Any (p => p.Value.ResultCode == TargetResultCode.Failure) ? BuildResultCode.Failure : BuildResultCode.Success;
				}
			} catch (Exception ex) {
				args.Result.OverallResult = BuildResultCode.Failure;
				LogErrorEvent (new BuildErrorEventArgs (null, null, project.FullPath, 0, 0, 0, 0, "Unhandled exception occured during a build", null, null));
				LogMessageEvent (new BuildMessageEventArgs ("Exception details: " + ex, null, null, MessageImportance.Low));
				throw; // BuildSubmission re-catches this.
			} finally {
				event_source.FireBuildFinished (this, new BuildFinishedEventArgs ("Build Finished.", null, args.Result.OverallResult == BuildResultCode.Success, DateTime.Now));
				Directory.SetCurrentDirectory (directoryBackup);
			}
		}
Example #9
0
		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;
			}
			
			var propsToRestore = new Dictionary<string,string> ();
			var itemsToRemove = new List<ProjectItemInstance> ();
			try {
				// Evaluate additional target properties
				foreach (var c in target.Children.OfType<ProjectPropertyGroupTaskInstance> ()) {
					if (!args.Project.EvaluateCondition (c.Condition))
						continue;
					foreach (var p in c.Properties) {
						if (!args.Project.EvaluateCondition (p.Condition))
							continue;
						var value = args.Project.ExpandString (p.Value);
						propsToRestore.Add (p.Name, project.GetPropertyValue (value));
						project.SetProperty (p.Name, value);
					}
				}
				
				// Evaluate additional target items
				foreach (var c in target.Children.OfType<ProjectItemGroupTaskInstance> ()) {
					if (!args.Project.EvaluateCondition (c.Condition))
						continue;
					foreach (var item in c.Items) {
						if (!args.Project.EvaluateCondition (item.Condition))
							continue;
						Func<string,ProjectItemInstance> creator = i => new ProjectItemInstance (project, item.ItemType, item.Metadata.Select (m => new KeyValuePair<string,string> (m.Name, m.Value)), i);
						foreach (var ti in project.GetAllItems (item.Include, item.Exclude, creator, creator, s => s == item.ItemType, (ti, s) => ti.SetMetadata ("RecurseDir", s)))
							itemsToRemove.Add (ti);
					}
				}
				
				foreach (var c in target.Children.OfType<ProjectOnErrorInstance> ()) {
					if (!args.Project.EvaluateCondition (c.Condition))
						continue;
					throw new NotImplementedException ();
				}
				
				// run tasks
				foreach (var ti in target.Children.OfType<ProjectTaskInstance> ()) {
					current_task = ti;
					if (!args.Project.EvaluateCondition (ti.Condition)) {
						LogMessageEvent (new BuildMessageEventArgs (string.Format ("Task '{0}' was skipped because condition '{1}' wasn't met.", ti.Name, ti.Condition), null, null, MessageImportance.Low));
						continue;
					}
					if (!RunBuildTask (target, ti, targetResult, args))
						return false;
				}
			} finally {
				// restore temporary property state to the original state.
				foreach (var p in propsToRestore) {
					if (p.Value == string.Empty)
						project.RemoveProperty (p.Key);
					else
						project.SetProperty (p.Key, p.Value);
				}
				foreach (var item in itemsToRemove)
					project.RemoveItem (item);
			}
			return true;
		}