/// <summary> /// Starts to run a build. /// </summary> /// <param name="project">The project/solution to build</param> /// <param name="options">The build options that should be used</param> /// <param name="realtimeBuildFeedbackSink">The build feedback sink that receives the build output. /// The output is nearly sent "as it comes in": sometimes output must wait because the BuildEngine /// will ensure that output from two projects building in parallel isn't interleaved.</param> /// <param name="progressMonitor">The progress monitor that receives build progress. The monitor will be disposed /// when the build completes.</param> public static void StartBuild(IBuildable project, BuildOptions options, IBuildFeedbackSink realtimeBuildFeedbackSink) { if (project == null) { throw new ArgumentNullException("solution"); } if (options == null) { throw new ArgumentNullException("options"); } Solution solution = project.ParentSolution; if (solution == null) { throw new ArgumentException("project.ParentSolution must not be null", "project"); } if (string.IsNullOrEmpty(options.SolutionConfiguration)) { options.SolutionConfiguration = solution.Preferences.ActiveConfiguration; } if (string.IsNullOrEmpty(options.SolutionPlatform)) { options.SolutionPlatform = solution.Preferences.ActivePlatform; } BuildEngine engine = new BuildEngine(options, project); engine.buildStart = DateTime.Now; engine.combinedBuildFeedbackSink = realtimeBuildFeedbackSink; engine.progressMonitor = realtimeBuildFeedbackSink.ProgressMonitor; try { engine.rootNode = engine.CreateBuildGraph(project); } catch (CyclicDependencyException ex) { if (ex.Project1 != null && ex.Project2 != null) { engine.results.Add(new BuildError(null, "Cyclic dependency between " + ex.Project1.Name + " and " + ex.Project2.Name)); } else { engine.results.Add(new BuildError(null, "Cyclic dependency")); } engine.results.Result = BuildResultCode.BuildFileError; engine.ReportDone(); return; } engine.workersToStart = options.ParallelProjectCount; if (engine.workersToStart < 1) { engine.workersToStart = 1; } engine.cancellationRegistration = engine.progressMonitor.CancellationToken.Register(engine.BuildCancelled); engine.ReportMessageLine("${res:MainWindow.CompilerMessages.BuildStarted}"); engine.StartBuildProjects(); engine.UpdateProgressTaskName(); }
/// <summary> /// Starts to run a build. /// </summary> /// <param name="project">The project/solution to build</param> /// <param name="options">The build options that should be used</param> /// <param name="buildFeedbackSink">The build feedback sink that receives the build output. /// The output is nearly sent "as it comes in": sometimes output must wait because the BuildEngine /// will ensure that output from two projects building in parallel isn't interleaved.</param> /// <param name="progressMonitor">The progress monitor that receives build progress. The monitor will be disposed /// when the build completes.</param> public static Task <BuildResults> BuildAsync(IBuildable project, BuildOptions options, IBuildFeedbackSink buildFeedbackSink, IProgressMonitor progressMonitor) { if (project == null) { throw new ArgumentNullException("project"); } if (options == null) { throw new ArgumentNullException("options"); } BuildEngine engine = new BuildEngine(options, project); engine.buildStart = DateTime.Now; engine.combinedBuildFeedbackSink = buildFeedbackSink; engine.progressMonitor = progressMonitor; try { engine.rootNode = engine.CreateBuildGraph(project); } catch (CyclicDependencyException ex) { BuildError error; if (ex.Project1 != null && ex.Project2 != null) { error = new BuildError(null, "Cyclic dependency between " + ex.Project1.Name + " and " + ex.Project2.Name); } else { error = new BuildError(null, "Cyclic dependency"); } engine.results.Add(error); if (engine.combinedBuildFeedbackSink != null) { engine.combinedBuildFeedbackSink.ReportError(error); engine.combinedBuildFeedbackSink.ReportMessage(error.ToRichText()); } engine.results.Result = BuildResultCode.BuildFileError; engine.ReportDone(); return(engine.tcs.Task); } engine.workersToStart = options.ParallelProjectCount; if (engine.workersToStart < 1) { engine.workersToStart = 1; } engine.cancellationRegistration = engine.progressMonitor.CancellationToken.Register(engine.BuildCancelled); engine.ReportMessageLine("${res:MainWindow.CompilerMessages.BuildStarted}"); engine.StartBuildProjects(); engine.UpdateProgressTaskName(); return(engine.tcs.Task); }
public static void CloseSolution() { // If a build is running, cancel it. // If we would let a build run but unload the MSBuild projects, the next project.StartBuild call // could cause an exception. BuildEngine.CancelGuiBuild(); if (openSolution != null) { CurrentProject = null; OnSolutionClosing(new SolutionEventArgs(openSolution)); openSolution.Dispose(); openSolution = null; OnSolutionClosed(EventArgs.Empty); } }
/// <summary> /// Closes the solution: cancels build, clears solution data, fires the SolutionClosing and SolutionClosed events. /// <remarks> /// Before invoking this method, one should check if the closing was canceled (<see cref="IsClosingCanceled"/>), /// save solution and project data (e.g. files, bookmarks), then invoke CloseSolution(). /// </remarks> /// </summary> internal static void CloseSolution() { // If a build is running, cancel it. // If we would let a build run but unload the MSBuild projects, the next project.StartBuild call // could cause an exception. BuildEngine.CancelGuiBuild(); if (openSolution != null) { CurrentProject = null; OnSolutionClosing(new SolutionEventArgs(openSolution)); openSolution.Dispose(); openSolution = null; ParserService.OnSolutionClosed(); OnSolutionClosed(EventArgs.Empty); CommandManager.InvalidateRequerySuggested(); } }
/// <summary> /// Starts to run a build. /// </summary> /// <param name="project">The project/solution to build</param> /// <param name="options">The build options that should be used</param> /// <param name="buildFeedbackSink">The build feedback sink that receives the build output. /// The output is nearly sent "as it comes in": sometimes output must wait because the BuildEngine /// will ensure that output from two projects building in parallel isn't interleaved.</param> /// <param name="progressMonitor">The progress monitor that receives build progress. The monitor will be disposed /// when the build completes.</param> public static Task<BuildResults> BuildAsync(IBuildable project, BuildOptions options, IBuildFeedbackSink buildFeedbackSink, IProgressMonitor progressMonitor) { if (project == null) throw new ArgumentNullException("project"); if (options == null) throw new ArgumentNullException("options"); BuildEngine engine = new BuildEngine(options, project); engine.buildStart = DateTime.Now; engine.combinedBuildFeedbackSink = buildFeedbackSink; engine.progressMonitor = progressMonitor; try { engine.rootNode = engine.CreateBuildGraph(project); } catch (CyclicDependencyException ex) { BuildError error; if (ex.Project1 != null && ex.Project2 != null) error = new BuildError(null, "Cyclic dependency between " + ex.Project1.Name + " and " + ex.Project2.Name); else error = new BuildError(null, "Cyclic dependency"); engine.results.Add(error); if (engine.combinedBuildFeedbackSink != null) { engine.combinedBuildFeedbackSink.ReportError(error); engine.combinedBuildFeedbackSink.ReportMessage(error.ToRichText()); } engine.results.Result = BuildResultCode.BuildFileError; engine.ReportDone(); return engine.tcs.Task; } engine.workersToStart = options.ParallelProjectCount; if (engine.workersToStart < 1) engine.workersToStart = 1; engine.cancellationRegistration = engine.progressMonitor.CancellationToken.Register(engine.BuildCancelled); engine.ReportMessageLine("${res:MainWindow.CompilerMessages.BuildStarted}"); engine.StartBuildProjects(); engine.UpdateProgressTaskName(); return engine.tcs.Task; }
public BuildNode(BuildEngine engine, IBuildable project) { this.engine = engine; this.project = project; }
/// <summary> /// Starts to run a build. /// </summary> /// <param name="project">The project/solution to build</param> /// <param name="options">The build options that should be used</param> /// <param name="realtimeBuildFeedbackSink">The build feedback sink that receives the build output. /// The output is nearly sent "as it comes in": sometimes output must wait because the BuildEngine /// will ensure that output from two projects building in parallel isn't interleaved.</param> /// <param name="progressMonitor">The progress monitor that receives build progress. The monitor will be disposed /// when the build completes.</param> public static void StartBuild(IBuildable project, BuildOptions options, IBuildFeedbackSink realtimeBuildFeedbackSink) { if (project == null) throw new ArgumentNullException("solution"); if (options == null) throw new ArgumentNullException("options"); Solution solution = project.ParentSolution; if (solution == null) throw new ArgumentException("project.ParentSolution must not be null", "project"); if (string.IsNullOrEmpty(options.SolutionConfiguration)) options.SolutionConfiguration = solution.Preferences.ActiveConfiguration; if (string.IsNullOrEmpty(options.SolutionPlatform)) options.SolutionPlatform = solution.Preferences.ActivePlatform; BuildEngine engine = new BuildEngine(options, project); engine.buildStart = DateTime.Now; engine.combinedBuildFeedbackSink = realtimeBuildFeedbackSink; engine.progressMonitor = realtimeBuildFeedbackSink.ProgressMonitor; try { engine.rootNode = engine.CreateBuildGraph(project); } catch (CyclicDependencyException ex) { if (ex.Project1 != null && ex.Project2 != null) engine.results.Add(new BuildError(null, "Cyclic dependency between " + ex.Project1.Name + " and " + ex.Project2.Name)); else engine.results.Add(new BuildError(null, "Cyclic dependency")); engine.results.Result = BuildResultCode.BuildFileError; engine.ReportDone(); return; } engine.workersToStart = options.ParallelProjectCount; if (engine.workersToStart < 1) engine.workersToStart = 1; engine.cancellationRegistration = engine.progressMonitor.CancellationToken.Register(engine.BuildCancelled); engine.ReportMessageLine("${res:MainWindow.CompilerMessages.BuildStarted}"); engine.StartBuildProjects(); engine.UpdateProgressTaskName(); }
public async Task <BuildResults> BuildAsync(IEnumerable <IProject> projects, BuildOptions options) { if (projects == null) { throw new ArgumentNullException("projects"); } if (options == null) { throw new ArgumentNullException("options"); } SD.MainThread.VerifyAccess(); if (guiBuildCancellation != null) { BuildResults results = new BuildResults(); SD.StatusBar.SetMessage(ResourceService.GetString("MainWindow.CompilerMessages.MSBuildAlreadyRunning")); BuildError error = new BuildError(null, ResourceService.GetString("MainWindow.CompilerMessages.MSBuildAlreadyRunning")); results.Add(error); TaskService.Add(new SDTask(error)); results.Result = BuildResultCode.MSBuildAlreadyRunning; return(results); } var projectsList = projects.ToList(); guiBuildCancellation = new CancellationTokenSource(); try { using (var progressMonitor = SD.StatusBar.CreateProgressMonitor(guiBuildCancellation.Token)) { if (BuildStarted != null) { BuildStarted(this, new BuildEventArgs(projectsList, options)); } var trackedFeature = SD.AnalyticsMonitor.TrackFeature("ICSharpCode.SharpDevelop.Project.BuildEngine.Build"); SD.StatusBar.SetMessage(StringParser.Parse("${res:MainWindow.CompilerMessages.BuildVerb}...")); IBuildable buildable; if (projectsList.Count == 1) { buildable = projectsList[0]; } else { buildable = new MultipleProjectBuildable(projectsList); } buildable = buildModifiedProjectsOnly.WrapBuildable(buildable, options.BuildDetection); var sink = new UIBuildFeedbackSink(SD.OutputPad.BuildCategory, SD.StatusBar); // Actually run the build: var results = await BuildEngine.BuildAsync(buildable, options, sink, progressMonitor); string message; if (results.Result == BuildResultCode.Cancelled) { message = "${res:MainWindow.CompilerMessages.BuildCancelled}"; } else { if (results.Result == BuildResultCode.Success) { message = "${res:MainWindow.CompilerMessages.BuildFinished}"; } else { message = "${res:MainWindow.CompilerMessages.BuildFailed}"; } if (results.ErrorCount > 0) { message += " " + results.ErrorCount + " error(s)"; } if (results.WarningCount > 0) { message += " " + results.WarningCount + " warning(s)"; } } SD.StatusBar.SetMessage(message); trackedFeature.EndTracking(); if (BuildFinished != null) { BuildFinished(this, new BuildEventArgs(projectsList, options, results)); } return(results); } } finally { guiBuildCancellation = null; } }
public Task <BuildResults> BuildInBackgroundAsync(IBuildable buildable, BuildOptions options, IBuildFeedbackSink buildFeedbackSink, IProgressMonitor progressMonitor) { return(BuildEngine.BuildAsync(buildable, options, buildFeedbackSink, progressMonitor)); }