New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow MSBuildWorkspace to output a binary log #42319
Changes from 10 commits
4980272
3d641d8
dc48489
12c9715
827eb12
e65f144
49ccccb
997e5db
20c6a60
e134698
85471fe
f5fbec2
975b649
3942482
11b67ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,14 +2,18 @@ | |
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
# nullable enable | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using System.Xml; | ||
using Microsoft.Build.Framework; | ||
using Microsoft.CodeAnalysis.MSBuild.Logging; | ||
using Roslyn.Utilities; | ||
using MSB = Microsoft.Build; | ||
|
@@ -57,9 +61,9 @@ internal class ProjectBuildManager | |
}.ToImmutableDictionary(); | ||
|
||
private readonly ImmutableDictionary<string, string> _additionalGlobalProperties; | ||
|
||
private MSB.Evaluation.ProjectCollection _batchBuildProjectCollection; | ||
private MSBuildDiagnosticLogger _batchBuildLogger; | ||
private readonly ILogger? _msbuildLogger; | ||
private MSB.Evaluation.ProjectCollection? _batchBuildProjectCollection; | ||
private MSBuildDiagnosticLogger? _batchBuildLogger; | ||
private bool _batchBuildStarted; | ||
|
||
~ProjectBuildManager() | ||
|
@@ -70,22 +74,23 @@ internal class ProjectBuildManager | |
} | ||
} | ||
|
||
public ProjectBuildManager(ImmutableDictionary<string, string> additionalGlobalProperties) | ||
public ProjectBuildManager(ImmutableDictionary<string, string> additionalGlobalProperties, ILogger? msbuildLogger = null) | ||
{ | ||
_additionalGlobalProperties = additionalGlobalProperties ?? ImmutableDictionary<string, string>.Empty; | ||
_msbuildLogger = msbuildLogger; | ||
} | ||
|
||
private ImmutableDictionary<string, string> AllGlobalProperties | ||
=> s_defaultGlobalProperties.AddRange(_additionalGlobalProperties); | ||
|
||
private static async Task<(MSB.Evaluation.Project project, DiagnosticLog log)> LoadProjectAsync( | ||
string path, MSB.Evaluation.ProjectCollection projectCollection, CancellationToken cancellationToken) | ||
private static async Task<(MSB.Evaluation.Project? project, DiagnosticLog log)> LoadProjectAsync( | ||
string path, MSB.Evaluation.ProjectCollection? projectCollection, CancellationToken cancellationToken) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When could projectCollection ever be null? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. its nulled out and re-allocated at the start of each Start/End build. so it can easily be null if things are ever called slightly out of order. How does roslyn typically handle complex lifetimes like this that the compiler can't track? I was inclined to say that if your object has a complex lifetime beyond some kind of In reply to: 401260471 [](ancestors = 401260471) |
||
{ | ||
var log = new DiagnosticLog(); | ||
|
||
try | ||
{ | ||
var loadedProjects = projectCollection.GetLoadedProjects(path); | ||
var loadedProjects = projectCollection?.GetLoadedProjects(path); | ||
if (loadedProjects != null && loadedProjects.Count > 0) | ||
{ | ||
Debug.Assert(loadedProjects.Count == 1); | ||
|
@@ -115,7 +120,7 @@ public ProjectBuildManager(ImmutableDictionary<string, string> additionalGlobalP | |
} | ||
} | ||
|
||
public Task<(MSB.Evaluation.Project project, DiagnosticLog log)> LoadProjectAsync( | ||
public Task<(MSB.Evaluation.Project? project, DiagnosticLog log)> LoadProjectAsync( | ||
string path, CancellationToken cancellationToken) | ||
{ | ||
if (_batchBuildStarted) | ||
|
@@ -137,7 +142,7 @@ public ProjectBuildManager(ImmutableDictionary<string, string> additionalGlobalP | |
} | ||
} | ||
|
||
public async Task<string> TryGetOutputFilePathAsync( | ||
public async Task<string?> TryGetOutputFilePathAsync( | ||
string path, CancellationToken cancellationToken) | ||
{ | ||
Debug.Assert(_batchBuildStarted); | ||
|
@@ -150,7 +155,7 @@ public ProjectBuildManager(ImmutableDictionary<string, string> additionalGlobalP | |
|
||
public bool BatchBuildStarted => _batchBuildStarted; | ||
|
||
public void StartBatchBuild(IDictionary<string, string> globalProperties = null) | ||
public void StartBatchBuild(IDictionary<string, string>? globalProperties = null) | ||
{ | ||
if (_batchBuildStarted) | ||
{ | ||
|
@@ -160,15 +165,16 @@ public void StartBatchBuild(IDictionary<string, string> globalProperties = null) | |
globalProperties = globalProperties ?? ImmutableDictionary<string, string>.Empty; | ||
var allProperties = s_defaultGlobalProperties.AddRange(globalProperties); | ||
_batchBuildProjectCollection = new MSB.Evaluation.ProjectCollection(allProperties); | ||
|
||
_batchBuildLogger = new MSBuildDiagnosticLogger() | ||
{ | ||
Verbosity = MSB.Framework.LoggerVerbosity.Normal | ||
}; | ||
|
||
var buildParameters = new MSB.Execution.BuildParameters(_batchBuildProjectCollection) | ||
{ | ||
Loggers = new MSB.Framework.ILogger[] { _batchBuildLogger } | ||
Loggers = _msbuildLogger is null | ||
? (new MSB.Framework.ILogger[] { _batchBuildLogger }) | ||
: (new MSB.Framework.ILogger[] { _batchBuildLogger, _msbuildLogger }) | ||
}; | ||
|
||
MSB.Execution.BuildManager.DefaultBuildManager.BeginBuild(buildParameters); | ||
|
@@ -186,7 +192,7 @@ public void EndBatchBuild() | |
MSB.Execution.BuildManager.DefaultBuildManager.EndBuild(); | ||
|
||
// unload project so collection will release global strings | ||
_batchBuildProjectCollection.UnloadAllProjects(); | ||
_batchBuildProjectCollection?.UnloadAllProjects(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
_batchBuildProjectCollection = null; | ||
_batchBuildLogger = null; | ||
_batchBuildStarted = false; | ||
|
@@ -219,7 +225,7 @@ public void EndBatchBuild() | |
} | ||
} | ||
|
||
_batchBuildLogger.SetProjectAndLog(projectInstance.FullPath, log); | ||
_batchBuildLogger?.SetProjectAndLog(projectInstance.FullPath, log); | ||
|
||
var buildRequestData = new MSB.Execution.BuildRequestData(projectInstance, targets); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed this earlier, is it intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I get yelled at if I add spaces to the usings so this is an implicit style that wasn't captured in the editorcofig. I see no place where separators in usings exist for roslyn