Migrate 5 MSBuild tasks to IMultiThreadableTask (Group 2: Bundle, Deps, Config & Hosts)#52936
Migrate 5 MSBuild tasks to IMultiThreadableTask (Group 2: Bundle, Deps, Config & Hosts)#52936SimaTian wants to merge 3 commits intodotnet:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates a set of SDK MSBuild tasks to participate in MSBuild’s multithreaded task execution model by implementing IMultiThreadableTask, wiring in TaskEnvironment, and replacing relative-path I/O with TaskEnvironment.GetAbsolutePath(...). It also adds unit-test coverage and introduces .NET Framework-gated polyfills for the new MSBuild APIs.
Changes:
- Migrate 4 tasks to
IMultiThreadableTask+TaskEnvironmentand absolutize relevant paths (GenerateBundle,GenerateDepsFile,WriteAppConfigWithSupportedRuntime,ResolveAppHosts). - Mark
ShowPreviewMessageas multithreadable via[MSBuildMultiThreadableTask]. - Add unit tests + a
TaskEnvironmentHelperfor constructingTaskEnvironmentinstances in tests, plus.NET Framework-gated polyfill implementations.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Tasks/Microsoft.NET.Build.Tasks/GenerateBundle.cs | Implements IMultiThreadableTask and absolutizes OutputDir/bundle inputs via TaskEnvironment. |
| src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs | Implements IMultiThreadableTask and absolutizes DepsFilePath before writing. |
| src/Tasks/Microsoft.NET.Build.Tasks/WriteAppConfigWithSupportedRuntime.cs | Implements IMultiThreadableTask and absolutizes input/output app.config paths. |
| src/Tasks/Microsoft.NET.Build.Tasks/ResolveAppHosts.cs | Implements IMultiThreadableTask and absolutizes runtime graph + targeting pack root usage. |
| src/Tasks/Microsoft.NET.Build.Tasks/ShowPreviewMessage.cs | Adds [MSBuildMultiThreadableTask] attribute. |
| src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAGenerateBundleMultiThreading.cs | Adds tests asserting interface/attribute and a smoke path-resolution scenario. |
| src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAGenerateDepsFileMultiThreading.cs | Adds interface/attribute/property presence tests. |
| src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAWriteAppConfigWithSupportedRuntimeMultiThreading.cs | Adds tests validating TaskEnvironment-based input/output path resolution. |
| src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAResolveAppHostsMultiThreading.cs | Adds test validating TargetingPackRoot resolution via TaskEnvironment. |
| src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAShowPreviewMessageMultiThreading.cs | Adds test validating [MSBuildMultiThreadableTask] presence. |
| src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/TaskEnvironmentHelper.cs | Adds helper for constructing TaskEnvironment via reflection/DispatchProxy. |
| src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/TaskEnvironmentHelperTests.cs | Adds smoke tests for helper behavior and path resolution. |
| src/Tasks/Common/IMultiThreadableTask.cs | Adds .NET Framework-gated polyfill for IMultiThreadableTask. |
| src/Tasks/Common/TaskEnvironment.cs | Adds .NET Framework-gated polyfill for TaskEnvironment. |
| src/Tasks/Common/AbsolutePath.cs | Adds .NET Framework-gated polyfill for AbsolutePath. |
| src/Tasks/Common/ITaskEnvironmentDriver.cs | Adds .NET Framework-gated polyfill for the internal driver interface. |
| src/Tasks/Common/ProcessTaskEnvironmentDriver.cs | Adds .NET Framework-gated polyfill driver implementation. |
src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAGenerateBundleMultiThreading.cs
Show resolved
Hide resolved
6e816e5 to
5069549
Compare
SimaTian
left a comment
There was a problem hiding this comment.
Addressed all review comments:
-
TaskEnvironment internal -> public: Fixed in the polyfills PR (#52909). \TaskEnvironment\ is now \public sealed class.
-
AbsolutePath internal -> public: Fixed in the polyfills PR (#52909). \AbsolutePath\ is now \public readonly struct.
-
GenerateBundle test assertion: Added \NotBeOfType\ assertion to verify that OutputDir is absolutized via TaskEnvironment rather than used as a relative path.
Branch rebased on updated polyfills and force-pushed.
src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAGenerateDepsFileMultiThreading.cs
Outdated
Show resolved
Hide resolved
Deep Audit: Forbidden API Usage in Helper Functions (Group 2)Traced all helper functions and referenced libraries called by the 5 Group 2 tasks for hidden forbidden API usage that bypasses the 🔴 CRITICAL:
|
| Task | Status | Issues |
|---|---|---|
| GenerateBundle | ✅ Clean | None |
| GenerateDepsFile | 🔴 Issues | FrameworkReferenceResolver uses Environment.GetEnvironmentVariable; AssetsFilePath/RuntimeGraphPath not absolutized; ResolvedFile ctor has Path.GetFullPath (not hit in this path) |
| WriteAppConfig | ✅ Clean | None |
| ResolveAppHosts | ✅ Clean | None |
| ShowPreviewMessage | ✅ Clean | None |
Recommended actions:
- GenerateDepsFile: Absolutize
AssetsFilePathandRuntimeGraphPathbefore passing to helpers - FrameworkReferenceResolver: Needs
TaskEnvironmentparameter (cross-cutting — affects multiple tasks) - ResolvedFile 4-arg ctor: Replace
Path.GetFullPathwith caller-side absolutization (latent, not active in this path)
Fixes applied (248cb91)Resolved the forbidden API issues identified in the deep audit: 1.
|
...icrosoft.NET.Build.Tasks.UnitTests/GivenAWriteAppConfigWithSupportedRuntimeMultiThreading.cs
Outdated
Show resolved
Hide resolved
src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAGenerateBundleMultiThreading.cs
Outdated
Show resolved
Hide resolved
src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAResolveAppHostsMultiThreading.cs
Outdated
Show resolved
Hide resolved
src/Tasks/Microsoft.NET.Build.Tasks/WriteAppConfigWithSupportedRuntime.cs
Show resolved
Hide resolved
...icrosoft.NET.Build.Tasks.UnitTests/GivenAWriteAppConfigWithSupportedRuntimeMultiThreading.cs
Outdated
Show resolved
Hide resolved
47bb48b to
391a30e
Compare
Migrate GenerateDepsFile, GenerateBundle, ResolveAppHosts, ShowPreviewMessage, WriteAppConfigWithSupportedRuntime, and FrameworkReferenceResolver to use TaskEnvironment for path resolution. - Add [MSBuildMultiThreadableTask] attribute and IMultiThreadableTask - Use TaskEnvironment.GetAbsolutePath for relative path resolution - Add TaskTestEnvironment test infrastructure - Add multithreading and absolute-path tests
391a30e to
56f7474
Compare
| public static string GetDefaultReferenceAssembliesPath() | ||
| public static string GetDefaultReferenceAssembliesPath(TaskEnvironment taskEnvironment) | ||
| { | ||
| // Allow setting the reference assemblies path via an environment variable |
There was a problem hiding this comment.
DotNetReferenceAssembliesPathResolver.Resolve() bypasses TaskEnvironment and reads DOTNET_REFERENCE_ASSEMBLIES_PATH directly via Environment.GetEnvironmentVariable(). This is inconsistent with the rest of this method which correctly routes env var reads through taskEnvironment.
The fix would be to replace this call with taskEnvironment.GetEnvironmentVariable("DOTNET_REFERENCE_ASSEMBLIES_PATH") and optionally inline the Mono xbuild-frameworks path probing from the library source.
This is a pre-existing issue (not introduced by this PR), but worth tracking since we are already touching this method.
There was a problem hiding this comment.
Or so the copilot says. The issue is that the offending method is a part of the Runtime. Does this mean that we need to clone the method with all the issues that arise from this?
Changing the runtime method to be aware of our TaskEnvironment sounds like a really bad idea to me.
Also a grumpy note: no matter how much I poked and prodded the agents, this one I had to catch myself. They just ignored it as a safe call for some reason.
SimaTian
left a comment
There was a problem hiding this comment.
As good as I can force the copilot to make it.
There is one open question - what do we do about the Runtime dependency which accesses Environment Variable directly? Is it safe enough to risk it or do we need to clone the method?
GenerateDepsFile and WriteAppConfigWithSupportedRuntime tests were missing TaskEnvironment assignment, causing NullReferenceException when Execute() tried to resolve relative paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Path GetAbsolutePath throws on null/empty paths. RuntimeGraphPath can be empty when no runtime graph is needed. Add IsNullOrEmpty guard. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Migrate 5 MSBuild tasks to IMultiThreadableTask (Group 2: Bundle, Deps, Config & Hosts)
Context
This PR migrates 5 MSBuild tasks to support multithreaded execution by implementing
IMultiThreadableTask.Migrated Tasks
OutputDirandFilesToBundle[].ItemSpecviaTaskEnvironment.GetAbsolutePath()DepsFilePathbeforeFile.Create()OutputAppConfigFile.ItemSpecand input app.config pathRuntimeGraphPathandTargetingPackRootChanges Per Task
Each task receives:
[MSBuildMultiThreadableTask]attributeIMultiThreadableTaskinterface implementationTaskEnvironmentpropertyTaskEnvironment.GetAbsolutePath())New Test Files
GivenAGenerateBundleMultiThreading.csGivenAGenerateDepsFileMultiThreading.csGivenAWriteAppConfigWithSupportedRuntimeMultiThreading.csGivenAResolveAppHostsMultiThreading.csGivenAShowPreviewMessageMultiThreading.csTesting