Guides you through creating hybrid .NET 10 tool packages that combine Native AOT for maximum performance on select platforms with CoreCLR fallback for universal compatibility.
When I Activate
I automatically load when you mention:
-
"pack .NET tool" or "dotnet pack AOT"
-
"Native AOT tool" or "hybrid .NET tool"
-
"ToolPackageRuntimeIdentifiers"
-
".NET 10 tool packaging"
-
"cross-platform .NET tool with AOT"
What I Do
-
Configure your .csproj with
ToolPackageRuntimeIdentifiersandPublishAot=true -
Generate the pointer package (metapackage)
-
Build Native AOT packages for each target RID
-
Create CoreCLR fallback with
-r any -
Validate package structure
Quick Start
Step 1: Configure .csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<!-- Package as .NET Tool -->
<PackAsTool>true</PackAsTool>
<ToolCommandName>your-tool-name</ToolCommandName>
<!-- RIDs: CoreCLR fallback + Native AOT targets -->
<ToolPackageRuntimeIdentifiers>any;osx-arm64;linux-arm64;linux-x64</ToolPackageRuntimeIdentifiers>
<!-- Enable Native AOT -->
<PublishAot>true</PublishAot>
</PropertyGroup>
<!-- Native AOT optimizations -->
<PropertyGroup Condition="'$(PublishAot)' == 'true'">
<InvariantGlobalization>true</InvariantGlobalization>
<OptimizationPreference>Size</OptimizationPreference>
<StripSymbols>true</StripSymbols>
</PropertyGroup>
</Project>
Step 2: Build Packages
# 1. Create pointer package (no binaries, just metadata)
dotnet pack -o ./packages
# 2. Build Native AOT for each target platform
dotnet pack -r osx-arm64 -o ./packages # On macOS
dotnet pack -r linux-arm64 -o ./packages # On Linux ARM or container
dotnet pack -r linux-x64 -o ./packages # On Linux x64 or container
# 3. Create CoreCLR fallback for all other platforms
dotnet pack -r any -p:PublishAot=false -o ./packages
Step 3: Install & Run
dotnet tool install -g your-tool-name
your-tool-name # Auto-selects best package for platform
Key Concepts
| Pointer Package | Metapackage that references RID-specific packages
| ToolPackageRuntimeIdentifiers | Lists RIDs, creates pointer structure (no auto-build)
| -r any
| CoreCLR fallback for unlisted platforms
| -p:PublishAot=false
| Disables AOT for CoreCLR fallback
Why This Pattern Works
-
PublishAot=truedisables automatic RID package generation (AOT can't cross-compile OSes) -
ToolPackageRuntimeIdentifierscreates the pointer package structure -
Manual
-r <RID>builds produce AOT binaries per platform -
-r any -p:PublishAot=falsecreates portable CoreCLR fallback
Documentation
-
reference.md: Complete build script, container builds, CI/CD patterns
-
examples.md: Real-world examples and troubleshooting
Requirements
-
.NET 10 SDK installed
-
Docker (for cross-platform Linux builds from macOS/Windows)
-
AOT-compatible container:
mcr.microsoft.com/dotnet/sdk:10.0-noble-aot