Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Enable AOT compatibility analyzers and fix issues - #52865

#52865
Merged
JeremyKuhne merged 5 commits into
dotnet:maindotnet/sdk:mainfrom
JeremyKuhne:aotcliJeremyKuhne/sdk:aotcliCopy head branch name to clipboard
Feb 10, 2026
Merged

Enable AOT compatibility analyzers and fix issues#52865
JeremyKuhne merged 5 commits into
dotnet:maindotnet/sdk:mainfrom
JeremyKuhne:aotcliJeremyKuhne/sdk:aotcliCopy head branch name to clipboard

Conversation

@JeremyKuhne

Copy link
Copy Markdown
Member

Replace reflection-based patterns with AOT-compatible alternatives across the CLI codebase:

  • Source-generated JSON serialization: Replace JsonSerializer.Serialize<T>/Deserialize<T> calls with source-generated JsonSerializerContext types throughout workload, tool list, SDK check, template, and manifest commands. This eliminates reliance on reflection-based DefaultJsonTypeInfoResolver.

  • Replace Assembly.GetExecutingAssembly().Location with AppContext.BaseDirectory or Environment.ProcessPath in VBCSCompilerServer, InstallerBase, InstallClientElevationContext, SignCheck, and ToolPackageDownloaderBase, since Assembly.Location returns empty in single-file/AOT deployments.

  • Replace XmlSerializer with manual XML parsing: Use XDocument/XmlReader in ToolConfigurationDeserializer and WorkloadUnixFilePermissionsFileList to avoid runtime code generation.

  • AOT-compatible logging registration: Change CliTemplateEngineHost to use Services.TryAddEnumerable instead of the generic AddConsoleFormatter<T> overload that relies on MakeGenericType.

  • Enable AOT compatibility analyzers: Add <IsAotCompatible>true</IsAotCompatible> to dotnet.csproj, Microsoft.DotNet.Configurer, Microsoft.DotNet.InternalAbstractions, Microsoft.TemplateEngine.Cli, Microsoft.DotNet.ProjectTools, Microsoft.DotNet.TemplateLocator, Microsoft.Win32.Msi, and Microsoft.DotNet.SdkResolver project files.

  • Suppress IL3000 warnings with #pragma in locations where Assembly.Location is unavoidable (MSBuildForwardingApp, BuiltInTemplatePackageProvider, OptionalWorkloadProvider).

@JeremyKuhne

Copy link
Copy Markdown
Member Author

Still in draft; checking test results and working through a few issues.

@NikolaMilosavljevic

Copy link
Copy Markdown
Contributor

/azp run sdk-unified-build

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@JeremyKuhne
JeremyKuhne marked this pull request as ready for review February 9, 2026 17:58
@JeremyKuhne
JeremyKuhne requested review from a team as code owners February 9, 2026 17:58
Copilot AI review requested due to automatic review settings February 9, 2026 17:58

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 aims to make the CLI codebase more Native AOT-friendly by enabling AOT compatibility analyzers across multiple projects and replacing reflection- or runtime-codegen-based patterns (JSON/XML serialization, assembly path discovery, logging registration) with AOT-compatible alternatives.

Changes:

  • Switch various JSON serialization/deserialization call sites to source-generated JsonSerializerContext type metadata.
  • Replace Assembly.Location usage with AppContext.BaseDirectory / Environment.ProcessPath in multiple components to support single-file/AOT scenarios.
  • Enable AOT compatibility analyzers via <IsAotCompatible>true</IsAotCompatible> in several project files and add targeted suppressions where needed.

Reviewed changes

Copilot reviewed 52 out of 52 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test/dotnet.Tests/CommandTests/Workload/Repair/GivenDotnetWorkloadRepair.cs Updates test JSON serialization of PackInfo to use source-generated type info.
test/dotnet.Tests/CommandTests/Workload/Install/WorkloadGarbageCollectionTests.cs Updates test JSON serialization to use source-generated type info; minor whitespace cleanup.
test/dotnet.Tests/CommandTests/Workload/Install/GivenFileBasedWorkloadInstall.cs Updates test JSON serialization to use source-generated type info.
test/dotnet.Tests/CommandTests/Workload/Clean/GivenDotnetWorkloadClean.cs Updates test JSON serialization to use source-generated type info.
start-code.cmd Adds a helper script to launch VS Code with repo-local dotnet environment variables.
src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSetJsonSerializerContext.cs Adds source-generated JSON context for WorkloadSet dictionary serialization.
src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSet.cs Switches WorkloadSet JSON (de)serialization to the generated context.
src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs Adjusts PackInfo JSON converter usage (removes attribute on Id).
src/Resolvers/Microsoft.DotNet.SdkResolver/Microsoft.DotNet.SdkResolver.csproj Enables AOT compatibility analyzers (conditional for non-net472).
src/Microsoft.Win32.Msi/Microsoft.Win32.Msi.csproj Enables AOT compatibility analyzers (conditional for non-NETFX TFM).
src/Microsoft.DotNet.TemplateLocator/Microsoft.DotNet.TemplateLocator.csproj Enables AOT compatibility analyzers (conditional for non-NETFX TFM).
src/Microsoft.DotNet.ProjectTools/Microsoft.DotNet.ProjectTools.csproj Enables AOT compatibility analyzers.
src/Microsoft.DotNet.ProjectTools/LaunchSettings/ProjectLaunchProfileParser.cs Switches JSON deserialization to a generated context.
src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfileJsonSerializerContext.cs Adds generated JSON context for launch profile types.
src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfile.cs Makes EnvironmentVariables init resilient to null values during deserialization.
src/Microsoft.DotNet.ProjectTools/LaunchSettings/ExecutableLaunchProfileParser.cs Switches JSON deserialization to a generated context.
src/Common/WorkloadFileBasedInstall.cs Switches JSON deserialization to a generated context for workload history.
src/Cli/dotnet/dotnet.csproj Enables AOT compatibility analyzers (conditional for non-NETFX TFM).
src/Cli/dotnet/ToolPackage/ToolPackageDownloaderBase.cs Replaces Assembly.Location-based path resolution with AppContext.BaseDirectory.
src/Cli/dotnet/ToolPackage/ToolConfigurationDeserializer.cs Replaces XmlSerializer with LINQ-to-XML parsing for tool config.
src/Cli/dotnet/ToolPackage/LocalToolsResolverCache.cs Switches cache JSON (de)serialization to a source-generated context.
src/Cli/dotnet/NugetSearch/NugetSearchApiResultDeserializer.cs Switches NuGet search JSON deserialization to a source-generated context.
src/Cli/dotnet/NugetPackageDownloader/WorkloadUnixFilePermissionsFileList.cs Replaces XmlSerializer with streaming XmlReader parsing for file permissions list.
src/Cli/dotnet/Installer/Windows/InstallerBase.cs Replaces SDK directory detection logic to use AppContext.BaseDirectory.
src/Cli/dotnet/Installer/Windows/InstallClientElevationContext.cs Replaces elevated process invocation arguments to avoid Assembly.Location.
src/Cli/dotnet/Commands/Workload/WorkloadJsonSerializerContext.cs Adds generated JSON contexts and a local WorkloadPackId converter for source-gen.
src/Cli/dotnet/Commands/Workload/Update/WorkloadUpdateCommand.cs Switches JSON output to a generated context.
src/Cli/dotnet/Commands/Workload/SignCheck_Windows.cs Replaces Assembly.Location with Environment.ProcessPath for signature checks.
src/Cli/dotnet/Commands/Workload/Search/WorkloadSearchVersionsCommand.cs Switches JSON outputs to a generated context and adds a local context type.
src/Cli/dotnet/Commands/Workload/List/WorkloadListCommand.cs Switches JSON output to a generated context and adds a local context type.
src/Cli/dotnet/Commands/Workload/InstallStateContents.cs Switches install-state JSON (de)serialization to a generated context.
src/Cli/dotnet/Commands/Workload/Install/WorkloadManifestUpdater.cs Switches JSON (de)serialization of advertised workloads to a generated context.
src/Cli/dotnet/Commands/Workload/Install/WorkloadInstallCommand.cs Switches JSON output to a generated context and adds a local context type.
src/Cli/dotnet/Commands/Workload/Install/NetSdkMsiInstallerClient.PackGroup.cs Switches pack group JSON deserialization to a generated context; null-safe collection setter.
src/Cli/dotnet/Commands/Workload/Install/MsiInstallerBase.cs Switches workload history JSON serialization to a generated context.
src/Cli/dotnet/Commands/Workload/Install/FileBasedInstaller.cs Switches PackInfo (de)serialization and history JSON serialization to generated contexts.
src/Cli/dotnet/Commands/Workload/GlobalJsonWorkloadSetFile.cs Switches global-json workload set JSON (de)serialization to a generated context.
src/Cli/dotnet/Commands/Tool/List/ToolListLocalCommand.cs Switches tool list JSON output to source-generated type info.
src/Cli/dotnet/Commands/Tool/List/ToolListJsonHelper.cs Introduces a JsonSerializerContext (with unsafe encoder) for tool list contracts.
src/Cli/dotnet/Commands/Tool/List/ToolListGlobalOrToolPathCommand.cs Switches tool list JSON output to source-generated type info.
src/Cli/dotnet/Commands/Test/TestCommandDefinition.cs Switches global.json parsing to a generated context.
src/Cli/dotnet/Commands/Sdk/Check/SdkCheckCommand.cs Switches SDK-check config JSON parsing to a generated context.
src/Cli/dotnet/Commands/Run/CSharpCompilerCommand.cs Uses source-generated JSON metadata for string serialization within generated JSON output; preserves editorconfig trailing spaces.
src/Cli/dotnet/Commands/New/OptionalWorkloadProvider.cs Adds IL3000 suppression around unavoidable Assembly.Location usage.
src/Cli/dotnet/Commands/New/BuiltInTemplatePackageProvider.cs Adds IL3000 suppression around unavoidable Assembly.Location usage.
src/Cli/dotnet/Commands/MSBuild/MSBuildForwardingApp.cs Adds IL3000 suppression around unavoidable Assembly.Location usage.
src/Cli/dotnet/CliSchema.cs Switches CLI schema serialization and schema generation to use a source-generated context/options.
src/Cli/dotnet/BuildServer/VBCSCompilerServer.cs Replaces Assembly.Location-based path resolution with AppContext.BaseDirectory.
src/Cli/Microsoft.TemplateEngine.Cli/Microsoft.TemplateEngine.Cli.csproj Enables AOT compatibility analyzers.
src/Cli/Microsoft.TemplateEngine.Cli/CliTemplateEngineHost.cs Adjusts console formatter registration to avoid reflection-heavy generic registration.
src/Cli/Microsoft.DotNet.InternalAbstractions/Microsoft.DotNet.InternalAbstractions.csproj Enables AOT compatibility analyzers (conditional for non-net472).
src/Cli/Microsoft.DotNet.Configurer/Microsoft.DotNet.Configurer.csproj Enables AOT compatibility analyzers and normalizes PublicSign condition formatting.

Comment thread src/Cli/dotnet/Installer/Windows/InstallerBase.cs Outdated
Comment thread src/Cli/dotnet/Installer/Windows/InstallClientElevationContext.cs Outdated
Comment thread src/Cli/dotnet/Commands/Workload/SignCheck_Windows.cs Outdated
…ross the CLI codebase:

- **Source-generated JSON serialization**: Replace `JsonSerializer.Serialize<T>`/`Deserialize<T>` calls with source-generated `JsonSerializerContext` types throughout workload, tool list, SDK check, template, and manifest commands. This eliminates reliance on reflection-based `DefaultJsonTypeInfoResolver`.

- **Replace `Assembly.GetExecutingAssembly().Location`** with `AppContext.BaseDirectory` or `Environment.ProcessPath` in `VBCSCompilerServer`, `InstallerBase`, `InstallClientElevationContext`, `SignCheck`, and `ToolPackageDownloaderBase`, since `Assembly.Location` returns empty in single-file/AOT deployments.

- **Replace `XmlSerializer` with manual XML parsing**: Use `XDocument`/`XmlReader` in `ToolConfigurationDeserializer` and `WorkloadUnixFilePermissionsFileList` to avoid runtime code generation.

- **AOT-compatible logging registration**: Change `CliTemplateEngineHost` to use `Services.TryAddEnumerable` instead of the generic `AddConsoleFormatter<T>` overload that relies on `MakeGenericType`.

- **Enable AOT compatibility analyzers**: Add `<IsAotCompatible>true</IsAotCompatible>` to `dotnet.csproj`, `Microsoft.DotNet.Configurer`, `Microsoft.DotNet.InternalAbstractions`, `Microsoft.TemplateEngine.Cli`, `Microsoft.DotNet.ProjectTools`, `Microsoft.DotNet.TemplateLocator`, `Microsoft.Win32.Msi`, and `Microsoft.DotNet.SdkResolver` project files.

- **Suppress IL3000 warnings** with `#pragma` in locations where `Assembly.Location` is unavoidable (`MSBuildForwardingApp`, `BuiltInTemplatePackageProvider`, `OptionalWorkloadProvider`).
…nd make converter public

The PR removed [JsonConverter(typeof(PackIdJsonConverter))] from the
PackInfo.Id property in WorkloadResolver.cs to enable source-generated
JSON serialization. However, WorkloadPackId is a struct with only a
private field (_id), so default System.Text.Json serialization emits {}
instead of the string value. This breaks JSON round-tripping for any
consumer of the public PackInfo type that doesn't use the CLI's
source-generated context.

Fix by placing [JsonConverter] on the WorkloadPackId struct itself. This
is the lowest-precedence converter location in STJ's resolution order,
so explicit converters specified in source-gen context options (e.g.
WorkloadPackIdJsonConverter in PackInfoJsonSerializerContext.Converters)
still take priority. But for default/reflection-based serialization, the
type-level attribute ensures correct string round-tripping without
requiring any per-property annotation.

PackIdJsonConverter is also changed from internal to public. Previously,
the internal visibility was fine because [JsonConverter] attributes on
properties are resolved at runtime via reflection, which bypasses access
modifiers. With source generation, the compile-time generator validates
the converter type referenced in the attribute is accessible, and an
internal type in another assembly causes SYSLIB1220. Making it public is
consistent with WorkloadPackId itself already being public.
Comment thread src/Cli/dotnet/Commands/Workload/Install/WorkloadManifestUpdater.cs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.