Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortherzok <marius.ungureanu@xamarin.com>2018-02-14 13:56:58 +0300
committertherzok <marius.ungureanu@xamarin.com>2018-02-14 14:40:22 +0300
commit5d36aea55cb4174d8f9d94fd4c4d081a4e991348 (patch)
treeca5408f3f367778c829dfbfd352c87d8ac4a04bf
parentd70128a9c6e7cbd449ff8a1c6d6df945de228b52 (diff)
[MSBuild] Parallelize actual MSBuild builderparallel-msbuild
Removed a few forced re-evaluation calls. CreateProjectInstance already forces a re-evaluation if necessary. The idea behind this is to make use of internal functionality of MSBuild BuildManager to get builds running. The only thing we cannot touch in parallel is the actual Project in MSBuild. But, creating after ProjectInstance we can safely execute a submission asynchronously, as all the details inside the ProjectInstance are immutable. So, on the STAThread, we need to setup the project and create the project instance (which will re-evaluate if necessary). The actual target run can be done async which we do via ExecuteAsync. Then, the caller will block on the MRE we set via submission. To actually be executed in parallel, we need to increase the MaxNodeCount. That is currently commented out, as MSBuild itself pinvokes CreateProcess which is a Windows-only method.
-rw-r--r--main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.v4.0.cs110
1 files changed, 62 insertions, 48 deletions
diff --git a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.v4.0.cs b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.v4.0.cs
index d36f780c40..558996de54 100644
--- a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.v4.0.cs
+++ b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild/ProjectBuilder.v4.0.cs
@@ -36,7 +36,8 @@ using System.Linq;
using Microsoft.Build.Logging;
using Microsoft.Build.Execution;
using System.Xml;
-
+using System.Threading;
+
namespace MonoDevelop.Projects.MSBuild
{
partial class ProjectBuilder
@@ -53,6 +54,8 @@ namespace MonoDevelop.Projects.MSBuild
Refresh ();
}
+ static List<BuildSubmission> buildSubmissions = new List<BuildSubmission> ();
+
public MSBuildResult Run (
ProjectConfigurationInfo[] configurations, IEngineLogWriter logWriter, MSBuildVerbosity verbosity,
string[] runTargets, string[] evaluateItems, string[] evaluateProperties, Dictionary<string,string> globalProperties, int taskId)
@@ -61,12 +64,12 @@ namespace MonoDevelop.Projects.MSBuild
throw new ArgumentException ("runTargets is empty");
MSBuildResult result = null;
+ ManualResetEvent ev = new ManualResetEvent (false);
BuildEngine.RunSTA (taskId, delegate {
Project project = null;
Dictionary<string, string> originalGlobalProperties = null;
-
- MSBuildLoggerAdapter loggerAdapter;
+ MSBuildLoggerAdapter loggerAdapter = null;
if (buildEngine.BuildOperationStarted) {
loggerAdapter = buildEngine.StartProjectSessionBuild (logWriter);
@@ -85,37 +88,51 @@ namespace MonoDevelop.Projects.MSBuild
foreach (var p in globalProperties)
project.SetGlobalProperty (p.Key, p.Value);
}
- project.ReevaluateIfNecessary ();
}
// Building the project will create items and alter properties, so we use a new instance
var pi = project.CreateProjectInstance ();
- Build (pi, runTargets, loggerAdapter.Loggers);
+ var submission = Build (pi, runTargets, loggerAdapter.Loggers);
- result = new MSBuildResult (loggerAdapter.BuildResult.ToArray ());
+ submission.ExecuteAsync (sm => {
+ result = new MSBuildResult (loggerAdapter.BuildResult.ToArray ());
- if (evaluateProperties != null) {
- foreach (var name in evaluateProperties) {
- var prop = pi.GetProperty (name);
- result.Properties [name] = prop != null? prop.EvaluatedValue : null;
+ if (evaluateProperties != null) {
+ foreach (var name in evaluateProperties) {
+ var prop = pi.GetProperty (name);
+ result.Properties [name] = prop != null ? prop.EvaluatedValue : null;
+ }
}
- }
- if (evaluateItems != null) {
- foreach (var name in evaluateItems) {
- var grp = pi.GetItems (name);
- var list = new List<MSBuildEvaluatedItem> ();
- foreach (var item in grp) {
- var evItem = new MSBuildEvaluatedItem (name, UnescapeString (item.EvaluatedInclude));
- foreach (var metadataName in item.MetadataNames) {
- evItem.Metadata [metadataName] = UnescapeString (item.GetMetadataValue (metadataName));
+ if (evaluateItems != null) {
+ foreach (var name in evaluateItems) {
+ var grp = pi.GetItems (name);
+ var list = new List<MSBuildEvaluatedItem> ();
+ foreach (var item in grp) {
+ var evItem = new MSBuildEvaluatedItem (name, UnescapeString (item.EvaluatedInclude));
+ foreach (var metadataName in item.MetadataNames) {
+ evItem.Metadata [metadataName] = UnescapeString (item.GetMetadataValue (metadataName));
+ }
+ list.Add (evItem);
}
- list.Add (evItem);
+ result.Items [name] = list.ToArray ();
}
- result.Items[name] = list.ToArray ();
}
- }
+ ev.Set ();
+
+ lock (buildSubmissions) {
+ buildSubmissions.Remove (submission);
+
+ if (buildSubmissions.Count == 0 && !buildEngine.BuildOperationStarted)
+ BuildManager.DefaultBuildManager.EndBuild ();
+ }
+
+ if (buildEngine.BuildOperationStarted)
+ buildEngine.EndProjectSessionBuild ();
+ else
+ loggerAdapter.Dispose ();
+ }, null);
} catch (Microsoft.Build.Exceptions.InvalidProjectFileException ex) {
var r = new MSBuildTargetResult (
file, false, ex.ErrorSubcategory, ex.ErrorCode, ex.ProjectFile,
@@ -124,20 +141,17 @@ namespace MonoDevelop.Projects.MSBuild
loggerAdapter.LogWriteLine (r.ToString ());
result = new MSBuildResult (new [] { r });
} finally {
- if (buildEngine.BuildOperationStarted)
- buildEngine.EndProjectSessionBuild ();
- else
- loggerAdapter.Dispose ();
-
if (project != null && globalProperties != null) {
foreach (var p in globalProperties)
project.RemoveGlobalProperty (p.Key);
foreach (var p in originalGlobalProperties)
project.SetGlobalProperty (p.Key, p.Value);
- project.ReevaluateIfNecessary ();
}
}
});
+
+ ev.WaitOne ();
+
return result;
}
@@ -193,15 +207,12 @@ namespace MonoDevelop.Projects.MSBuild
}
}
- bool reevaluate = false;
-
if (p.GetPropertyValue ("Configuration") != configuration || (p.GetPropertyValue ("Platform") ?? "") != (platform ?? "")) {
p.SetGlobalProperty ("Configuration", configuration);
if (!string.IsNullOrEmpty (platform))
p.SetGlobalProperty ("Platform", platform);
else
p.RemoveGlobalProperty ("Platform");
- reevaluate = true;
}
// The CurrentSolutionConfigurationContents property only needs to be set once
@@ -210,12 +221,8 @@ namespace MonoDevelop.Projects.MSBuild
if (!buildEngine.BuildOperationStarted && this.file == file && p.GetPropertyValue ("CurrentSolutionConfigurationContents") != slnConfigContents) {
p.SetGlobalProperty ("CurrentSolutionConfigurationContents", slnConfigContents);
- reevaluate = true;
}
- if (reevaluate)
- p.ReevaluateIfNecessary ();
-
return p;
}
@@ -223,20 +230,27 @@ namespace MonoDevelop.Projects.MSBuild
/// <summary>
/// Builds a list of targets with the specified loggers.
/// </summary>
- internal void Build (ProjectInstance pi, string [] targets, IEnumerable<ILogger> loggers)
+ internal BuildSubmission Build (ProjectInstance pi, string [] targets, IEnumerable<ILogger> loggers)
{
- BuildResult results;
-
- if (!buildEngine.BuildOperationStarted) {
- BuildParameters parameters = new BuildParameters (engine);
- parameters.ResetCaches = false;
- parameters.EnableNodeReuse = true;
- BuildRequestData data = new BuildRequestData (pi, targets, parameters.HostServices);
- parameters.Loggers = loggers;
- results = BuildManager.DefaultBuildManager.Build (parameters, data);
- } else {
- BuildRequestData data = new BuildRequestData (pi, targets);
- results = BuildManager.DefaultBuildManager.BuildRequest (data);
+ BuildRequestData data;
+ lock (buildSubmissions) {
+ if (buildSubmissions.Count == 0 && !buildEngine.BuildOperationStarted) {
+ BuildParameters parameters = new BuildParameters (engine);
+ parameters.ResetCaches = false;
+ parameters.EnableNodeReuse = true;
+
+ // Uncomment this when MSBuild supports parallel builds on Mono.
+ //parameters.MaxNodeCount = 8;
+
+ BuildManager.DefaultBuildManager.BeginBuild (parameters);
+ data = new BuildRequestData (pi, targets, parameters.HostServices);
+ parameters.Loggers = loggers;
+ } else
+ data = new BuildRequestData (pi, targets);
+
+ var submission = BuildManager.DefaultBuildManager.PendBuildRequest (data);;
+ buildSubmissions.Add (submission);
+ return submission;
}
}
}