46 changed files with 663 additions and 581 deletions
@ -1,18 +0,0 @@
@@ -1,18 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Project.Commands; |
||||
|
||||
namespace ICSharpCode.UnitTesting |
||||
{ |
||||
public class UnitTestBuildProjectFactory : IBuildProjectFactory |
||||
{ |
||||
public BuildProject CreateBuildProjectBeforeTestRun(IEnumerable<IBuildable> projects) |
||||
{ |
||||
return new BuildProjectBeforeExecute(new MultipleProjectBuildable(projects)); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.ComponentModel; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Project |
||||
{ |
||||
public enum BuildDetection |
||||
{ |
||||
[Description("${res:Dialog.Options.IDEOptions.ProjectAndSolutionOptions.WhenRunning.DoNotBuild}")] |
||||
DoNotBuild, |
||||
[Description("${res:Dialog.Options.IDEOptions.ProjectAndSolutionOptions.WhenRunning.BuildOnlyModified}")] |
||||
BuildOnlyModified, |
||||
[Description("${res:Dialog.Options.IDEOptions.ProjectAndSolutionOptions.WhenRunning.BuildModifiedAndDependent}")] |
||||
BuildModifiedAndDependent, |
||||
[Description("${res:Dialog.Options.IDEOptions.ProjectAndSolutionOptions.WhenRunning.RegularBuild}")] |
||||
RegularBuild |
||||
} |
||||
} |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Project |
||||
{ |
||||
public class BuildEventArgs : EventArgs |
||||
{ |
||||
/// <summary>
|
||||
/// The projects to be built.
|
||||
/// </summary>
|
||||
public readonly IReadOnlyList<IProject> Projects; |
||||
|
||||
/// <summary>
|
||||
/// The build options.
|
||||
/// </summary>
|
||||
public readonly BuildOptions Options; |
||||
|
||||
/// <summary>
|
||||
/// Gets the build results.
|
||||
/// This property is null for build started events.
|
||||
/// </summary>
|
||||
public readonly BuildResults Results; |
||||
|
||||
public BuildEventArgs(IReadOnlyList<IProject> projects, BuildOptions options) |
||||
: this(projects, options, null) |
||||
{ |
||||
} |
||||
|
||||
public BuildEventArgs(IReadOnlyList<IProject> projects, BuildOptions options, BuildResults results) |
||||
{ |
||||
if (projects == null) |
||||
throw new ArgumentNullException("projects"); |
||||
if (options == null) |
||||
throw new ArgumentNullException("options"); |
||||
this.Projects = projects; |
||||
this.Options = options; |
||||
this.Results = results; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Threading.Tasks; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Project |
||||
{ |
||||
/// <summary>
|
||||
/// The service interface for accessing the build engine.
|
||||
/// The build engine is responsible for constructing a dependency graph
|
||||
/// between the <see cref="IBuildable"/>s, performing a topological sort
|
||||
/// and scheduling the actual build.
|
||||
/// </summary>
|
||||
[SDService] |
||||
public interface IBuildService |
||||
{ |
||||
/// <summary>
|
||||
/// Builds the specified projects.
|
||||
/// If tests are already running, the existing run is cancelled.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The build progress will be shown in the SharpDevelop UI;
|
||||
/// and the build can be cancelled by the user.
|
||||
/// This method can only be used on the main thread.
|
||||
/// </remarks>
|
||||
Task<BuildResults> BuildAsync(IEnumerable<IProject> projects, BuildOptions options); |
||||
|
||||
Task<BuildResults> BuildAsync(IProject project, BuildOptions options); |
||||
Task<BuildResults> BuildAsync(Solution solution, BuildOptions options); |
||||
|
||||
/// <summary>
|
||||
/// Raised when a build is started.
|
||||
/// </summary>
|
||||
/// <remarks>This event always occurs on the main thread.</remarks>
|
||||
event EventHandler<BuildEventArgs> BuildStarted; |
||||
|
||||
/// <summary>
|
||||
/// Raised when a build is finished.
|
||||
/// </summary>
|
||||
/// <remarks>This event always occurs on the main thread.</remarks>
|
||||
event EventHandler<BuildEventArgs> BuildFinished; |
||||
|
||||
/// <summary>
|
||||
/// Gets whether a build is currently running.
|
||||
/// </summary>
|
||||
bool IsBuilding { get; } |
||||
|
||||
/// <summary>
|
||||
/// Aborts the current build.
|
||||
/// This method has no effect if no build is running.
|
||||
/// </summary>
|
||||
void CancelBuild(); |
||||
|
||||
/// <summary>
|
||||
/// Performs a build in the background (not visible in the UI).
|
||||
/// </summary>
|
||||
/// <param name="buildable">The root buildable</param>
|
||||
/// <param name="options">The build options that should be used</param>
|
||||
/// <param name="buildFeedbackSink">The build feedback sink that receives the build output.</param>
|
||||
/// <param name="progressMonitor">Progress monitor used to report progress about this build.</param>
|
||||
/// <remarks>
|
||||
/// This method does not set <see cref="IsBuilding"/> and cannot be cancelled using
|
||||
/// <see cref="CancelBuild()"/>.
|
||||
/// Cancellation is possible using the progress monitor's cancellation token, but
|
||||
/// will not cause an <see cref="TaskCanceledException"/> - instead, the build results
|
||||
/// will use <c>BuildResultCode.Cancelled</c>.
|
||||
/// It does not raise the <see cref="BuildStarted"/>/<see cref="BuildFinished"/> events.
|
||||
/// This method is thread-safe, and multiple background builds can run concurrently.
|
||||
/// </remarks>
|
||||
Task<BuildResults> BuildInBackgroundAsync(IBuildable buildable, BuildOptions options, IBuildFeedbackSink buildFeedbackSink, IProgressMonitor progressMonitor); |
||||
} |
||||
} |
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Threading.Tasks; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Project |
||||
{ |
||||
/// <summary>
|
||||
/// A project or solution.
|
||||
/// The IBuildable interface members are thread-safe.
|
||||
/// </summary>
|
||||
public interface IBuildable |
||||
{ |
||||
/// <summary>
|
||||
/// Gets the list of projects on which this project depends.
|
||||
/// This method is thread-safe.
|
||||
/// </summary>
|
||||
IEnumerable<IBuildable> GetBuildDependencies(ProjectBuildOptions buildOptions); |
||||
|
||||
/// <summary>
|
||||
/// Starts building the project using the specified options.
|
||||
/// This member must be implemented thread-safe.
|
||||
/// </summary>
|
||||
Task<bool> BuildAsync(ProjectBuildOptions options, IBuildFeedbackSink feedbackSink, IProgressMonitor progressMonitor); |
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the buildable item.
|
||||
/// This property is thread-safe.
|
||||
/// </summary>
|
||||
string Name { get; } |
||||
|
||||
/// <summary>
|
||||
/// Creates the project-specific build options.
|
||||
/// This member must be implemented thread-safe.
|
||||
/// </summary>
|
||||
/// <param name="options">The global build options.</param>
|
||||
/// <param name="isRootBuildable">Specifies whether this project is the main buildable item.
|
||||
/// The root buildable is the buildable for which <see cref="BuildOptions.ProjectTarget"/> and <see cref="BuildOptions.ProjectAdditionalProperties"/> apply.
|
||||
/// The dependencies of that root buildable are the non-root buildables.</param>
|
||||
/// <returns>The project-specific build options.</returns>
|
||||
ProjectBuildOptions CreateProjectBuildOptions(BuildOptions options, bool isRootBuildable); |
||||
} |
||||
} |
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Project |
||||
{ |
||||
/// <summary>
|
||||
/// Specifies options for building a single project.
|
||||
/// </summary>
|
||||
public class ProjectBuildOptions |
||||
{ |
||||
BuildTarget target; |
||||
IDictionary<string, string> properties = new SortedList<string, string>(); |
||||
|
||||
public BuildTarget Target { |
||||
get { return target; } |
||||
} |
||||
|
||||
public IDictionary<string, string> Properties { |
||||
get { return properties; } |
||||
} |
||||
|
||||
public ProjectBuildOptions(BuildTarget target) |
||||
{ |
||||
this.target = target; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Specifies the project configuration used for the build.
|
||||
/// </summary>
|
||||
public string Configuration { get; set; } |
||||
|
||||
/// <summary>
|
||||
/// Specifies the project platform used for the build.
|
||||
/// </summary>
|
||||
public string Platform { get; set; } |
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets the verbosity of build output.
|
||||
/// </summary>
|
||||
public BuildOutputVerbosity BuildOutputVerbosity { get; set; } |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,117 @@
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
|
||||
using ICSharpCode.Core; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Project |
||||
{ |
||||
sealed class BuildService : IBuildService |
||||
{ |
||||
readonly BuildModifiedProjectsOnlyService buildModifiedProjectsOnly; |
||||
|
||||
public BuildService() |
||||
{ |
||||
this.buildModifiedProjectsOnly = new BuildModifiedProjectsOnlyService(this); |
||||
} |
||||
|
||||
public event EventHandler<BuildEventArgs> BuildStarted; |
||||
public event EventHandler<BuildEventArgs> BuildFinished; |
||||
|
||||
CancellationTokenSource guiBuildCancellation; |
||||
|
||||
public bool IsBuilding { |
||||
get { return guiBuildCancellation != null; } |
||||
} |
||||
|
||||
public void CancelBuild() |
||||
{ |
||||
if (guiBuildCancellation != null) |
||||
guiBuildCancellation.Cancel(); |
||||
} |
||||
|
||||
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(); |
||||
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(TaskService.BuildMessageViewCategory, SD.StatusBar); |
||||
var results = await BuildInBackgroundAsync(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; |
||||
} |
||||
} |
||||
|
||||
public Task<BuildResults> BuildAsync(IProject project, BuildOptions options) |
||||
{ |
||||
if (project != null) |
||||
return BuildAsync(new[] { project }, options); |
||||
else |
||||
return Task.FromResult(new BuildResults { Result = BuildResultCode.Error }); |
||||
} |
||||
|
||||
public Task<BuildResults> BuildAsync(Solution solution, BuildOptions options) |
||||
{ |
||||
if (solution != null) |
||||
return BuildAsync(solution.Projects, options); |
||||
else |
||||
return Task.FromResult(new BuildResults { Result = BuildResultCode.Error }); |
||||
} |
||||
|
||||
public Task<BuildResults> BuildInBackgroundAsync(IBuildable buildable, BuildOptions options, IBuildFeedbackSink buildFeedbackSink, IProgressMonitor progressMonitor) |
||||
{ |
||||
return BuildEngine.BuildAsync(buildable, options, buildFeedbackSink, progressMonitor); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.Linq; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Project |
||||
{ |
||||
/// <summary>
|
||||
/// This error message sink is used for GUI builds.
|
||||
/// </summary>
|
||||
sealed class UIBuildFeedbackSink : IBuildFeedbackSink |
||||
{ |
||||
MessageViewCategory messageView; |
||||
IStatusBarService statusBarService; |
||||
|
||||
public UIBuildFeedbackSink(MessageViewCategory messageView, IStatusBarService statusBarService) |
||||
{ |
||||
Debug.Assert(messageView != null); |
||||
Debug.Assert(statusBarService != null); |
||||
|
||||
this.messageView = messageView; |
||||
this.statusBarService = statusBarService; |
||||
} |
||||
|
||||
public void ReportError(BuildError error) |
||||
{ |
||||
WorkbenchSingleton.SafeThreadAsyncCall( |
||||
delegate { |
||||
TaskService.Add(new SDTask(error)); |
||||
}); |
||||
} |
||||
|
||||
public void ReportMessage(string message) |
||||
{ |
||||
messageView.AppendLine(message); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue