.NET 11 Preview 5 includes new MSBuild features & enhancements:
- Multithreaded builds can be enabled from the environment
- MSBuild evaluation and item filtering are faster
- Binary log replay handles older logs
- MSBuild runs on Haiku
These features continue the .NET 11 work on Multithreaded execution, logging, and evaluation performance.
MSBuild now supports MSBUILDFORCEMULTITHREADED=1, an environment-variable equivalent of the -multiThreaded / -mt command-line switch (dotnet/msbuild #13662). This helps CI systems, IDEs, and wrapper scripts opt in to multithreaded builds when they cannot easily add a command-line switch.
set MSBUILDFORCEMULTITHREADED=1
dotnet build MySolution.slnPreview 5 also moves more in-box tasks onto the multithreaded execution model. These tasks now use the task environment for project-relative paths instead of relying on process-wide current-directory state:
AssignProjectConfiguration(dotnet/msbuild #13615)GetAssemblyIdentity(dotnet/msbuild #13588)GetInstalledSDKLocations(dotnet/msbuild #13564)- Manifest tasks, including
GenerateApplicationManifest,GenerateDeploymentManifest,ResolveManifestFiles,AddToWin32Manifest,UpdateManifest, andCreateManifestResourceName(dotnet/msbuild #13177) ResolveAssemblyReference(dotnet/msbuild #13319)
Multithreaded builds at this point should be completely compatible - meaning they should build the same way and produce the same outputs as multi-process builds today - but we continue to expect them to be slower than multiprocess builds due to increased usage of processes for Task isolation, which requires more communication overhead. We expect this gap to narrow as we continue to enlighten built-in Tasks.
MSBuild's escaping helpers now allocate less and run faster in evaluation-heavy workloads (dotnet/msbuild #13426). EscapingUtilities.Escape and EscapingUtilities.UnescapeAll are used throughout property and item evaluation. In the PR benchmarks on .NET 10.0, Escape_NoSpecialChars improved from 17.96 ns to 5.37 ns, Escape_FewSpecialChars improved from 191.8 ns to 84.9 ns, and UnescapeAll_InvalidEscapeSequences dropped its allocation from 48 B to 0 B.
Item filtering also returns to linear behavior for large item sets with many batched removes (dotnet/msbuild #13688). This fixes a regression seen in QtMsBuild C++ projects where builds with tens of thousands of items could spend hours in Lookup.GetItems. The result construction path is back to O(N + A + M) instead of O((N + A) x M) for the affected pattern.
Command-line binary log replay now replays older MSBuild logs instead of rejecting them completely when the log version is lower than the current tool version (dotnet/msbuild #13608). MSBuild skips entries it cannot understand and prints the version warning after replay, so older .binlog files still provide the events that are compatible with the current replay engine.
dotnet msbuild -bl:build.binlog MyProject.csproj
dotnet msbuild build.binlogMSBuild now recognizes Haiku as a Unix-like operating system (dotnet/msbuild #13607). This lets MSBuild choose the same shared Unix paths as Linux and macOS, such as invoking .sh scripts instead of .cmd scripts when it runs on Haiku.
Thank you @trungnt2910 for this contribution!
- Build engine
BuildManager.ShutdownAllNodes()now finds AppHost-launched worker nodes, sodotnet build-server shutdowncan clean upMSBuild.exenodes started by adotnet-hosted build (dotnet/msbuild #13511).- MSBuild no longer uses WMI to scan command lines while identifying worker processes on Windows, removing latency on machines with many
dotnetprocesses (dotnet/msbuild #13610).
- Logging
- Terminal Logger no longer opts in to task input logging that it does not consume, avoiding serialization of large task parameter payloads on every task invocation (dotnet/msbuild #13686).
- MSBuild prints the existing auto-response-file warning before
MSB1008when switches fromMSBuild.rsporDirectory.Build.rspcause multiple projects to be specified (dotnet/msbuild #13675).
- Project references
SkipNonexistentTargets="true"now propagates through generated metaprojects, so project-reference builds do not fail withMSB4057when the underlying project lacks the optional target (dotnet/msbuild #13650).
- Tasks
WriteLinesToFiletransactional overwrites now handle parallel writers that create the destination between the replace check and move operation (dotnet/msbuild #13477).- The
Copytask now retriesERROR_ACCESS_DENIEDon non-Windows instead of treating it as a Windows-style read-only-file failure (dotnet/msbuild #13479). UsingTask Runtime="NET"without an explicitArchitecturenow defaults to the OS architecture, matching thedotnethost MSBuild launches for .NET task hosts (dotnet/msbuild #13741).RestoreTasknow runs in a transient TaskHost when MSBuild server or multithreaded mode would otherwise let NuGet static state leak across invocations (dotnet/msbuild #13660).
Thank you contributors! ❤️