Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/dotnet4@4121 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
8 changed files with 343 additions and 97 deletions
@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using Microsoft.Build.Framework; |
||||
using System; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Project |
||||
{ |
||||
/// <summary>
|
||||
/// IEventSource implementation. Used to forward events to submission-specific loggers.
|
||||
/// </summary>
|
||||
sealed class EventSource : IEventSource, IEventRedirector |
||||
{ |
||||
public event BuildMessageEventHandler MessageRaised; |
||||
public event BuildErrorEventHandler ErrorRaised; |
||||
public event BuildWarningEventHandler WarningRaised; |
||||
public event BuildStartedEventHandler BuildStarted; |
||||
public event BuildFinishedEventHandler BuildFinished; |
||||
public event ProjectStartedEventHandler ProjectStarted; |
||||
public event ProjectFinishedEventHandler ProjectFinished; |
||||
public event TargetStartedEventHandler TargetStarted; |
||||
public event TargetFinishedEventHandler TargetFinished; |
||||
public event TaskStartedEventHandler TaskStarted; |
||||
public event TaskFinishedEventHandler TaskFinished; |
||||
public event CustomBuildEventHandler CustomEventRaised; |
||||
public event BuildStatusEventHandler StatusEventRaised; |
||||
|
||||
public event AnyEventHandler AnyEventRaised; |
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] |
||||
public void ForwardEvent(Microsoft.Build.Framework.BuildEventArgs e) |
||||
{ |
||||
if (e is BuildStatusEventArgs) { |
||||
if (e is TaskStartedEventArgs) { |
||||
if (TaskStarted != null) |
||||
TaskStarted(this, (TaskStartedEventArgs)e); |
||||
} else if (e is TaskFinishedEventArgs) { |
||||
if (TaskFinished != null) |
||||
TaskFinished(this, (TaskFinishedEventArgs)e); |
||||
} else if (e is TargetStartedEventArgs) { |
||||
if (TargetStarted != null) |
||||
TargetStarted(this, (TargetStartedEventArgs)e); |
||||
} else if (e is TargetFinishedEventArgs) { |
||||
if (TargetFinished != null) |
||||
TargetFinished(this, (TargetFinishedEventArgs)e); |
||||
} else if (e is ProjectStartedEventArgs) { |
||||
if (ProjectStarted != null) |
||||
ProjectStarted(this, (ProjectStartedEventArgs)e); |
||||
} else if (e is ProjectFinishedEventArgs) { |
||||
if (ProjectFinished != null) |
||||
ProjectFinished(this, (ProjectFinishedEventArgs)e); |
||||
} else if (e is BuildStartedEventArgs) { |
||||
if (BuildStarted != null) |
||||
BuildStarted(this, (BuildStartedEventArgs)e); |
||||
} else if (e is BuildFinishedEventArgs) { |
||||
if (BuildFinished != null) |
||||
BuildFinished(this, (BuildFinishedEventArgs)e); |
||||
} |
||||
if (StatusEventRaised != null) |
||||
StatusEventRaised(this, (BuildStatusEventArgs)e); |
||||
} else if (e is BuildMessageEventArgs) { |
||||
if (MessageRaised != null) |
||||
MessageRaised(this, (BuildMessageEventArgs)e); |
||||
} else if (e is BuildWarningEventArgs) { |
||||
if (WarningRaised != null) |
||||
WarningRaised(this, (BuildWarningEventArgs)e); |
||||
} else if (e is BuildErrorEventArgs) { |
||||
if (ErrorRaised != null) |
||||
ErrorRaised(this, (BuildErrorEventArgs)e); |
||||
} else if (e is CustomBuildEventArgs) { |
||||
if (CustomEventRaised != null) |
||||
CustomEventRaised(this, (CustomBuildEventArgs)e); |
||||
} |
||||
|
||||
if (AnyEventRaised != null) |
||||
AnyEventRaised(this, e); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,133 @@
@@ -0,0 +1,133 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using ICSharpCode.Core; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using Microsoft.Build.Execution; |
||||
using Microsoft.Build.Framework; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Project |
||||
{ |
||||
/// <summary>
|
||||
/// Manages parallel access to MSBuild.
|
||||
///
|
||||
/// MSBuild only allows a single BuildManager to build at one time, and loggers
|
||||
/// are specified globally for that BuildManager.
|
||||
/// This class allows
|
||||
/// </summary>
|
||||
public static class ParallelMSBuildManager |
||||
{ |
||||
#region Manage StartBuild/EndBuild of BuildManager.DefaultBuildManager
|
||||
static readonly object enableDisableLock = new object(); |
||||
static int enableCount; |
||||
|
||||
static void EnableBuildEngine() |
||||
{ |
||||
lock (enableDisableLock) { |
||||
if (enableCount == 0) { |
||||
BuildParameters parameters = new BuildParameters(); |
||||
parameters.Loggers = new ILogger[] { new CentralLogger() }; |
||||
BuildManager.DefaultBuildManager.BeginBuild(parameters); |
||||
} |
||||
enableCount++; |
||||
} |
||||
} |
||||
|
||||
static void DisableBuildEngine() |
||||
{ |
||||
lock (enableDisableLock) { |
||||
enableCount--; |
||||
if (enableCount == 0) { |
||||
BuildManager.DefaultBuildManager.EndBuild(); |
||||
BuildManager.DefaultBuildManager.ResetCaches(); |
||||
} |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
static readonly Dictionary<int, EventSource> submissionEventSourceMapping = new Dictionary<int, EventSource>(); |
||||
|
||||
/// <summary>
|
||||
/// Starts building.
|
||||
/// </summary>
|
||||
/// <param name="requestData">The requested build.</param>
|
||||
/// <param name="logger">The logger that received build output.</param>
|
||||
/// <param name="callback">Callback that is run when the build is complete</param>
|
||||
/// <returns>The build submission that was started.</returns>
|
||||
public static BuildSubmission StartBuild(BuildRequestData requestData, ILogger logger, BuildSubmissionCompleteCallback callback) |
||||
{ |
||||
EnableBuildEngine(); |
||||
try { |
||||
BuildSubmission submission = BuildManager.DefaultBuildManager.PendBuildRequest(requestData); |
||||
EventSource eventSource = new EventSource(); |
||||
if (logger != null) |
||||
logger.Initialize(eventSource); |
||||
lock (submissionEventSourceMapping) { |
||||
submissionEventSourceMapping.Add(submission.SubmissionId, eventSource); |
||||
} |
||||
// TODO: when will the logger be shut down?
|
||||
submission.ExecuteAsync(OnComplete, callback); |
||||
return submission; |
||||
} catch (Exception ex) { |
||||
LoggingService.Warn("Got exception starting build (exception will be rethrown)", ex); |
||||
DisableBuildEngine(); |
||||
throw; |
||||
} |
||||
} |
||||
|
||||
static void OnComplete(BuildSubmission submission) |
||||
{ |
||||
DisableBuildEngine(); |
||||
|
||||
lock (submissionEventSourceMapping) { |
||||
submissionEventSourceMapping.Remove(submission.SubmissionId); |
||||
} |
||||
BuildSubmissionCompleteCallback callback = submission.AsyncContext as BuildSubmissionCompleteCallback; |
||||
if (callback != null) |
||||
callback(submission); |
||||
} |
||||
|
||||
sealed class CentralLogger : INodeLogger, IEventRedirector |
||||
{ |
||||
public void Initialize(IEventSource eventSource, int nodeCount) |
||||
{ |
||||
Initialize(eventSource); |
||||
} |
||||
|
||||
public void Initialize(IEventSource eventSource) |
||||
{ |
||||
eventSource.AnyEventRaised += (sender, e) => ForwardEvent(e); |
||||
} |
||||
|
||||
public void Shutdown() |
||||
{ |
||||
} |
||||
|
||||
public string Parameters { get; set; } |
||||
public LoggerVerbosity Verbosity { get; set; } |
||||
|
||||
public void ForwardEvent(Microsoft.Build.Framework.BuildEventArgs e) |
||||
{ |
||||
if (e.BuildEventContext == null) { |
||||
if (e is BuildStartedEventArgs || e is BuildFinishedEventArgs) { |
||||
// these two don't have context set, so we cannot forward them
|
||||
// this isn't a problem because we know ourselves when we start/stop a build
|
||||
return; |
||||
} else { |
||||
throw new InvalidOperationException("BuildEventContext is null on " + e.ToString()); |
||||
} |
||||
} |
||||
IEventRedirector redirector; |
||||
lock (submissionEventSourceMapping) { |
||||
redirector = submissionEventSourceMapping[e.BuildEventContext.SubmissionId]; |
||||
} |
||||
redirector.ForwardEvent(e); |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue