Skip to content

Make Microsoft.Build.Tasks.CodeAnalysis AOT and single-file clean - #84335

Merged
333fred merged 7 commits into
dotnet:mainfrom
JeremyKuhne:msbuild-tasks-aot-single-file-clean
Jul 10, 2026
Merged

333fred merged 7 commits into
dotnet:mainfrom
JeremyKuhne:msbuild-tasks-aot-single-file-clean

Conversation

@JeremyKuhne

@JeremyKuhne JeremyKuhne commented Jun 30, 2026 •

Copy link
Copy Markdown
Member

A .NET copy of Microsoft.Build.Tasks.CodeAnalysis ships in the .NET SDK's Native AOT CLI, so the assembly must be clean for trimming, AOT, and single-file publishing.

This enables IsAotCompatible on the .NET build (which turns on the trim, AOT, and single-file analyzers) and resolves the resulting warnings. Most changes are annotations, dead-code guards, or a single scoped suppression; the one functional change is GetBuildTaskDirectory gaining an AOT-only resolution path (loose-file MSBuild behavior is unchanged).

Changes

  • Utilities.TryGetAssemblyPath - deleted. It was unused and relied on Assembly.CodeBase/Location.
  • csc.rsp / vbc.rsp lookups (Csc.cs, Vbc.cs) - wrapped in #if NETFRAMEWORK. They only run inside if (IsSdkFrameworkToCoreBridgeTask), which is compile-time false on .NET Core, so the Assembly.Location use there is dead code on the AOT target framework. Behavior is unchanged for the net472 bridge task.
  • ManagedToolTask.GetBuildTaskDirectory - resolves the build task directory (the anchor for the sibling bincore compiler) and keeps one scoped [UnconditionalSuppressMessage] for the unavoidable IL3000. In the normal loose-file MSBuild scenario the directory is Assembly.Location. In the partially-AOT SDK CLI that is empty and AppContext.BaseDirectory is the runtime muxer's install root, so the method first reads the versioned SDK directory the AOT host publishes as the Microsoft.DotNet.Sdk.Root AppContext value (per dotnet/sdk#55110) and appends the Roslyn subfolder. [RequiresAssemblyFiles] cannot be used because it would have to flow onto the sealed ToolTask overrides (GenerateFullPathToTool, GenerateCommandLineCommands, ToolName, ExecuteTool) whose base declarations are not annotated, which is itself an error (IL3003).
  • ReflectionUtilities - added the trim annotations required to clear the IL2057 / IL2070 errors the Correctness legs hit. This shared Contracts file is linked into the task assembly via Directory.Build.props, so its reflection helpers must be annotated once the trim analyzer is enabled.
  • FatalError.CopyHandlersTo - annotated [RequiresUnreferencedCode]. This shared Contracts file is globbed into the task assembly, and its reflection over the target type otherwise produces IL2026 / IL2075 once the trim analyzer is enabled.

Validation

Built with RunAnalyzers=true and confirmed 0 IL warnings / 0 errors on:

  • net10.0 (the AOT target)
  • net472
  • the net472 Microsoft.Build.Tasks.CodeAnalysis.Sdk bridge variant
Microsoft Reviewers: Open in CodeFlow

A .NET copy of this task assembly ships in the .NET SDK's Native AOT CLI, so it must be clean for trimming, AOT, and single-file publishing. Enable IsAotCompatible (which turns on the trim, AOT, and single-file analyzers) and resolve the resulting warnings.

- Delete the unused Utilities.TryGetAssemblyPath (it used Assembly.CodeBase/Location).

- Guard the framework-to-core bridge csc.rsp/vbc.rsp lookups with #if NETFRAMEWORK; they only run on .NET Framework MSBuild and are dead code on .NET Core.

- Scope-suppress the one unavoidable IL3000 in GetBuildTaskDirectory. Assembly.Location is required to locate the sibling compiler when loaded as loose files; single-file hosts fall back to AppContext.BaseDirectory and receive the compiler path out-of-band. [RequiresAssemblyFiles] cannot be used because it would flow onto the non-annotated ToolTask overrides (IL3003).

- Annotate FatalError.CopyHandlersTo with [RequiresUnreferencedCode]; this shared Contracts file is compiled into the task and its reflection otherwise produces IL2026/IL2075.
Copilot AI review requested due to automatic review settings June 30, 2026 01:28
@JeremyKuhne
JeremyKuhne requested a review from a team as a code owner June 30, 2026 01:28
@dotnet-policy-service dotnet-policy-service Bot added the Community The pull request was submitted by a contributor who is not a Microsoft employee. label Jun 30, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Microsoft.Build.Tasks.CodeAnalysis to be compatible with trimming, Native AOT, and single-file publishing scenarios by enabling the IsAotCompatible build setting for modern target frameworks and addressing the resulting IL linker/analyzer warnings via conditional compilation and targeted annotations/suppressions.

Changes:

  • Enabled IsAotCompatible (trim/AOT/single-file analyzers) for the .NET TFMs in the MSBuild task project.
  • Removed an unused helper (Utilities.TryGetAssemblyPath) that relied on Assembly.CodeBase/Location.
  • Guarded csc.rsp/vbc.rsp lookup logic behind #if NETFRAMEWORK, added a scoped IL3000 suppression + runtime fallback for single-file/AOT hosts, and annotated reflection-heavy handler-copying with RequiresUnreferencedCode.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Dependencies/Contracts/ErrorReporting/FatalError.cs Annotates CopyHandlersTo with RequiresUnreferencedCode (on .NET builds) to satisfy trim analyzer around reflection use.
src/Compilers/Core/MSBuildTask/Vbc.cs Wraps vbc.rsp lookup (via Assembly.Location) in #if NETFRAMEWORK to avoid single-file analyzer warnings on .NET.
src/Compilers/Core/MSBuildTask/Utilities.cs Removes unused TryGetAssemblyPath (and System.Reflection using) to avoid assembly-path APIs.
src/Compilers/Core/MSBuildTask/MSBuild/Microsoft.Build.Tasks.CodeAnalysis.csproj Enables IsAotCompatible for net8.0+ compatible TFMs (e.g., net10.0) while leaving net472 unaffected.
src/Compilers/Core/MSBuildTask/ManagedToolTask.cs Adds a scoped IL3000 suppression and makes GetBuildTaskDirectory robust for single-file/AOT (fallback to AppContext.BaseDirectory).
src/Compilers/Core/MSBuildTask/Csc.cs Wraps csc.rsp lookup (via Assembly.Location) in #if NETFRAMEWORK to avoid single-file analyzer warnings on .NET.

Comment thread src/Compilers/Core/MSBuildTask/MSBuild/Microsoft.Build.Tasks.CodeAnalysis.csproj Outdated
Comment thread src/Compilers/Core/MSBuildTask/Csc.cs
Comment thread src/Compilers/Core/MSBuildTask/ManagedToolTask.cs Outdated
Comment thread src/Compilers/Core/MSBuildTask/ManagedToolTask.cs Outdated
Comment thread src/Compilers/Core/MSBuildTask/ManagedToolTask.cs Outdated
ReflectionUtilities.cs is linked into the task via Directory.Build.props; its trim annotations are required to fix the IL2057/IL2070 errors the Correctness legs hit (it was wrongly omitted from the first commit).

Revert GetBuildTaskDirectory to its original throw-on-null behavior, keeping only the IL3000 suppression, so the change is purely analyzer cleanliness with no runtime behavior change.

Assert the bridge-only response-file branch is unreachable on .NET Core via Debug.Assert(false) in the #else (Csc.cs, Vbc.cs).

Gate IsAotCompatible on the TargetFramework matching NetRoslynSourceBuild (the .NET build) instead of an IsTargetFrameworkCompatible net8.0 floor, per review feedback.
@JeremyKuhne
JeremyKuhne marked this pull request as draft July 1, 2026 00:02
@JeremyKuhne

Copy link
Copy Markdown
Member Author

@jjonescz I've flipped this to draft until I fully rationalize the state coming from the muxer (dotnet.exe). I have dotnet/msbuild#14064 pending that I used the changes here to test with the SDK, but I think that I might be depending on the wrong directory info.

Under the partially-AOT .NET SDK CLI, Assembly.Location is empty and AppContext.BaseDirectory is the muxer's install root, so GetBuildTaskDirectory could not find the versioned SDK directory. It now reads the Microsoft.DotNet.Sdk.Root AppContext value that the AOT host publishes (dotnet/sdk#55110) before falling back to Assembly.Location for loose-file MSBuild deployments. Also clarifies the ManagedToolTask class/member doc comments and adds the class-hierarchy and on-disk-layout diagrams.
@JeremyKuhne
JeremyKuhne marked this pull request as ready for review July 9, 2026 18:00
Copilot AI review requested due to automatic review settings July 9, 2026 18:00
@JeremyKuhne JeremyKuhne closed this Jul 9, 2026
@JeremyKuhne JeremyKuhne reopened this Jul 9, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Comment thread src/Compilers/Core/MSBuildTask/ManagedToolTask.cs
Comment thread src/Compilers/Core/MSBuildTask/ManagedToolTask.cs
Comment thread src/Compilers/Core/MSBuildTask/ManagedToolTask.cs
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 18:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Comment thread src/Compilers/Core/MSBuildTask/ManagedToolTask.cs
…ildTaskDirectory

Verifies that GetBuildTaskDirectory (and GetToolDirectory) resolve from the Microsoft.DotNet.Sdk.Root AppContext value the AOT host publishes, appending the Roslyn subfolder. The test derives a ManagedToolTask to observe the resolved folders, runs in a non-parallel collection (the AppContext value is process-global), asserts the value is unset beforehand, and restores it in a finally.
Copilot AI review requested due to automatic review settings July 9, 2026 19:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment thread src/Compilers/Core/MSBuildTaskTests/MSBuildManagedToolTests.cs
Comment thread src/Compilers/Core/MSBuildTask/Csc.cs Outdated
Comment thread src/Compilers/Core/MSBuildTask/ManagedToolTask.cs Outdated
Comment thread src/Compilers/Core/MSBuildTask/Vbc.cs Outdated
Use Debug.Fail for the bridge-only branches in Csc and Vbc. Remove the hand-maintained ManagedToolTask hierarchy diagram and document ToolNameWithoutExtension at its declaration instead.
Copilot AI review requested due to automatic review settings July 10, 2026 00:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Comment thread src/Dependencies/Contracts/ErrorReporting/FatalError.cs Outdated
Comment thread src/Compilers/Core/MSBuildTask/ManagedToolTask.cs
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 10, 2026 00:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment thread src/Compilers/Core/MSBuildTaskTests/MSBuildManagedToolTests.cs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Compilers Community The pull request was submitted by a contributor who is not a Microsoft employee.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants