Skip to content

Add NativeAOT entry point for the dotnet CLI - #54002

Merged
JeremyKuhne merged 5 commits into
dotnet:mainfrom
JeremyKuhne:aotme
Apr 22, 2026
Merged

Add NativeAOT entry point for the dotnet CLI#54002
JeremyKuhne merged 5 commits into
dotnet:mainfrom
JeremyKuhne:aotme

Conversation

@JeremyKuhne

Copy link
Copy Markdown
Member

Introduce a three-layer AOT architecture to enable near-instant startup for common CLI commands while preserving full managed CLI functionality:

  • dn.exe (src/Cli/dn): NativeAOT host that resolves DOTNET_ROOT and hostfxr, marshals args, and calls into dotnet-aot via P/Invoke. Includes dn-native-debug.vcxproj for native debugging in VS.

  • dotnet-aot.dll (src/Cli/dotnet-aot): NativeAOT shared library that tries an AOT-compiled parser for simple commands (--version, --info), then falls back to hosting the full managed CLI via hostfxr.

  • dotnet.dll (src/Cli/dotnet): Existing managed CLI, wrapped with #if CLI_AOT conditional compilation to share source files with the AOT build while keeping full functionality in the managed path.

Supporting changes:

  • Add hostfxr interop APIs to Microsoft.DotNet.NativeWrapper (init, run_app, close, get_runtime_delegate, set_runtime_property_value)
  • Fix hostfxr_get_dotnet_environment_info return type to StatusCode
  • Add VS Code tasks and launch config for building/debugging AOT
  • Add DESIGN.md documenting architecture, build, and debugging workflow

Introduce a three-layer AOT architecture to enable near-instant startup
for common CLI commands while preserving full managed CLI functionality:

- dn.exe (src/Cli/dn): NativeAOT host that resolves DOTNET_ROOT and
  hostfxr, marshals args, and calls into dotnet-aot via P/Invoke.
  Includes dn-native-debug.vcxproj for native debugging in VS.

- dotnet-aot.dll (src/Cli/dotnet-aot): NativeAOT shared library that
  tries an AOT-compiled parser for simple commands (--version, --info),
  then falls back to hosting the full managed CLI via hostfxr.

- dotnet.dll (src/Cli/dotnet): Existing managed CLI, wrapped with
  #if CLI_AOT conditional compilation to share source files with the
  AOT build while keeping full functionality in the managed path.

Supporting changes:
- Add hostfxr interop APIs to Microsoft.DotNet.NativeWrapper (init,
  run_app, close, get_runtime_delegate, set_runtime_property_value)
- Fix hostfxr_get_dotnet_environment_info return type to StatusCode
- Add VS Code tasks and launch config for building/debugging AOT
- Add DESIGN.md documenting architecture, build, and debugging workflow

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 introduces an experimental NativeAOT-based entry point for the SDK CLI (dn) that can handle a small set of fast-path commands in AOT, and otherwise hosts/runs the existing managed CLI as a fallback.

Changes:

  • Add new NativeAOT projects for dn (exe) and dotnet-aot (NativeAOT shared library) plus design/debugging documentation.
  • Extend Microsoft.DotNet.NativeWrapper hostfxr interop surface (and fix hostfxr_get_dotnet_environment_info return type).
  • Add VS/VS Code workspace, tasks, and solution wiring for building/debugging the new AOT layers.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
tasks.code-workspace Adds VS Code tasks + a native debug launch profile for dn AOT.
start-code.cmd Allows launching a specific .code-workspace, defaults to tasks.code-workspace.
src/Resolvers/Microsoft.DotNet.NativeWrapper/NETBundlesNativeWrapper.cs Updates environment-info interop call to use StatusCode.
src/Resolvers/Microsoft.DotNet.NativeWrapper/Microsoft.DotNet.NativeWrapper.csproj Adds InternalsVisibleTo for dotnet-aot.
src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs Adds hostfxr hosting APIs and adjusts environment-info return type.
src/Cli/dotnet/Program.cs Adds CLI_AOT conditional entry point for shared-source AOT build.
src/Cli/dotnet/Parser.cs Adds minimal AOT parser under CLI_AOT plus conditional compilation split.
src/Cli/dotnet/CommandLineInfo.cs Adjusts output/logic to support AOT compilation path.
src/Cli/dotnet-aot/dotnet-aot.csproj New NativeAOT shared-library project linking shared CLI sources.
src/Cli/dotnet-aot/NativeEntryPoint.cs New unmanaged export entry point implementing fast-path vs fallback dispatch.
src/Cli/dotnet-aot/ManagedHost.cs New hostfxr-based managed-host fallback implementation.
src/Cli/dotnet-aot/DESIGN.md Architecture/design/build/debug documentation for the three-layer approach.
src/Cli/dn/dn.csproj New NativeAOT dn host project + VS debugging helper generation.
src/Cli/dn/dn-native-debug.vcxproj New VS-native-debug “stub” project for reliable AOT breakpoint binding.
src/Cli/dn/Program.cs New dn host that resolves DOTNET_ROOT/hostfxr and calls into dotnet-aot.
src/Cli/dn/.gitignore Ignores machine-specific generated debug artifacts.
sdk.slnx Adds the new CLI projects to the main solution.
cli.slnf Adds the new CLI projects to the CLI solution filter.

Comment thread src/Cli/dotnet/Parser.cs Outdated
Comment thread tasks.code-workspace
Comment thread src/Cli/dotnet-aot/NativeEntryPoint.cs
Comment thread src/Cli/dn/Program.cs Outdated
Comment thread src/Cli/dn/dn-native-debug.vcxproj
Comment thread src/Cli/dn/Program.cs Outdated
Comment thread src/Cli/dotnet-aot/NativeEntryPoint.cs Outdated
Comment thread src/Cli/dotnet-aot/ManagedHost.cs
Comment thread src/Cli/dotnet/Program.cs Outdated
Comment thread src/Cli/dn/Program.cs
Comment thread src/Cli/dotnet/Parser.cs
Comment thread src/Cli/dotnet-aot/NativeEntryPoint.cs Outdated
Comment thread src/Cli/dotnet-aot/NativeEntryPoint.cs Outdated
Comment thread src/Cli/dotnet/CommandLineInfo.cs
Comment thread src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs
Comment thread src/Cli/dotnet-aot/ManagedHost.cs
Comment thread src/Cli/dotnet/Parser.cs
Comment thread src/Cli/dotnet/Program.cs
@baronfel

Copy link
Copy Markdown
Member

/ba-g known issue around macos communication to redhat/quay servers

@JeremyKuhne
JeremyKuhne merged commit 8a2fa1c into dotnet:main Apr 22, 2026
21 of 24 checks passed
@JeremyKuhne
JeremyKuhne deleted the aotme branch April 22, 2026 17:36
@NikolaMilosavljevic

Copy link
Copy Markdown
Contributor

SDK directory resolution gap in managed fallback path

In src/Cli/dn/Program.cs (line 24), sdkDir is set to AppContext.BaseDirectory — the directory where dn.exe lives (e.g., .dotnet/). This value is passed to NativeEntryPoint.ExecuteCore, which constructs the managed fallback path as:

\\csharp
string dotnetDll = Path.Join(sdkDir, "dotnet.dll"); // NativeEntryPoint.cs:58
\\

However, dotnet.dll doesn't live next to dn.exe — it lives in a version-specific SDK subdirectory (e.g., .dotnet/sdk/11.0.100-preview.3.26170.106/dotnet.dll). The native dotnet muxer resolves this via hostfxr_resolve_sdk2, but dn currently skips that step.

As a result, the managed fallback path (when DOTNET_CLI_ENABLEAOT is unset or false) always fails with:
\
The managed fallback could not be located. Expected '/dotnet.dll'...
\\

This doesn't affect the AOT fast path (--version, --info), but it means any command that needs the managed CLI (e.g., build, test, run) will fail even when a full SDK is installed.

Suggested fix: Use hostfxr_resolve_sdk2 (or equivalent logic) to resolve the actual SDK version directory before passing sdkDir to dotnet_execute.

@JeremyKuhne

NikolaMilosavljevic added a commit to NikolaMilosavljevic/sdk that referenced this pull request May 13, 2026
Add test project dotnet-aot.Tests with 44 unit and integration tests
covering the NativeAOT CLI entry point added in PR dotnet#54002.

Refactoring for testability:
- Extract DotnetRootResolver from dn/Program.cs with injectable deps
- Extract NativeEntryPoint.ExecuteCore from [UnmanagedCallersOnly] Execute
- Create AotSourceFiles.props shared source file list

Test categories (44 tests):
- AOT Parser (10): Parse/invoke --version, --info, default, errors
- Path Resolution (13): DOTNET_ROOT env vars, arch-specific, walk-up,
  hostfxr discovery, version selection, cross-platform
- Decision Logic (11): DOTNET_CLI_ENABLEAOT gating, fallback behavior,
  env var format variants, AppContext/hostfxr setup
- Integration/E2E (6): Run actual dn binary (Assert.Skip if not built)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NikolaMilosavljevic added a commit to NikolaMilosavljevic/sdk that referenced this pull request May 13, 2026
Add test project dotnet-aot.Tests with 44 unit and integration tests
covering the NativeAOT CLI entry point added in PR dotnet#54002.

Refactoring for testability:
- Extract DotnetRootResolver from dn/Program.cs with injectable deps
- Extract NativeEntryPoint.ExecuteCore from [UnmanagedCallersOnly] Execute
- Create AotSourceFiles.props shared source file list

Test categories (44 tests):
- AOT Parser (10): Parse/invoke --version, --info, default, errors
- Path Resolution (13): DOTNET_ROOT env vars, arch-specific, walk-up,
  hostfxr discovery, version selection, cross-platform
- Decision Logic (11): DOTNET_CLI_ENABLEAOT gating, fallback behavior,
  env var format variants, AppContext/hostfxr setup
- Integration/E2E (6): Run actual dn binary (Assert.Skip if not built)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants