A MSBuild SDK package for building Native AOT applications and libraries with C#.
- .NET 8.0 or later
Use NativeSdk as your project SDK:
<Project Sdk="NativeSdk/0.5.2">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>This SDK automatically inherits from Microsoft.NET.Sdk, so you don't need to specify it separately.
This SDK automatically configures your project with:
| Setting | Default Value | Description |
|---|---|---|
OutputType |
Exe |
Builds as executable by default |
PublishAot |
true |
Enables Native AOT compilation |
IsAotCompatible |
true |
Marks the project as AOT compatible |
AllowUnsafeBlocks |
true |
Enables unsafe code |
TrimMode |
full |
Full trimming for size optimization |
InvariantGlobalization |
true |
Invariant globalization mode |
EnableTrimAnalyzer |
true |
Enables trim compatibility analyzer |
EnableAotAnalyzer |
true |
Enables AOT compatibility analyzer |
TreatWarningsAsErrors |
true |
Treats warnings as errors |
The following namespaces are automatically included for Interop scenarios:
| Namespace | Description |
|---|---|
System.Runtime.InteropServices |
Core interop types ([DllImport], [UnmanagedCallersOnly], Marshal) |
System.Runtime.InteropServices.Marshalling |
Source-generated marshalling ([LibraryImport]) |
System.Runtime.CompilerServices |
Compiler services ([SkipLocalsInit], Unsafe) |
System.Buffers |
Buffer operations (Span<T>, Memory<T>) |
When OutputType is set to Library, the following additional settings are applied:
| Setting | Default Value | Description |
|---|---|---|
NativeLib |
Shared |
Builds as a shared/dynamic library (can be overridden to Static) |
DnneGenerateExports |
true |
DNNE export generation enabled |
DnneBuildExports |
false |
DNNE build exports disabled |
- Stack trace support enabled
- Metadata preserved for debugging
- Stack trace support disabled
- Metadata trimmed for smaller binaries
<Project Sdk="NativeSdk/0.5.2">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project><Project Sdk="NativeSdk/0.5.2">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Library</OutputType>
</PropertyGroup>
</Project><Project Sdk="NativeSdk/0.5.2">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Library</OutputType>
<NativeLib>Static</NativeLib>
</PropertyGroup>
</Project>This example demonstrates using unsafe pointers with stackalloc for high-performance sorting:
unsafe
{
const int ArraySize = 10;
// Allocate memory on the stack using stackalloc
int* arr = stackalloc int[ArraySize];
// Initialize array with random values
Random rand = new(42);
Console.WriteLine("Before sorting:");
for (int i = 0; i < ArraySize; i++)
{
arr[i] = rand.Next(1, 100);
Console.Write($"{arr[i]} ");
}
Console.WriteLine();
// Execute QuickSort
QuickSort(arr, 0, ArraySize - 1);
// Print sorted result
Console.WriteLine("\nAfter sorting:");
for (int i = 0; i < ArraySize; i++)
{
Console.Write($"{arr[i]} ");
}
Console.WriteLine();
static void QuickSort(int* arr, int left, int right)
{
if (left >= right) return;
int pivotIndex = Partition(arr, left, right);
QuickSort(arr, left, pivotIndex - 1);
QuickSort(arr, pivotIndex + 1, right);
}
static int Partition(int* arr, int left, int right)
{
int pivot = arr[right];
int i = left - 1;
for (int j = left; j < right; j++)
{
if (arr[j] <= pivot)
{
i++;
(arr[i], arr[j]) = (arr[j], arr[i]); // Tuple swap
}
}
(arr[i + 1], arr[right]) = (arr[right], arr[i + 1]);
return i + 1;
}
}This SDK includes DNNE for generating native exports when building as a library. Use the [UnmanagedCallersOnly] attribute to export functions:
public static class NativeExports
{
[UnmanagedCallersOnly(EntryPoint = "add")]
public static int Add(int a, int b) => a + b;
}Note: DNNE is only included when
OutputTypeis set toLibrary. TheSystem.Runtime.InteropServicesnamespace is already included by default.
All settings can be overridden in your project file:
<PropertyGroup>
<!-- Build as library instead of executable -->
<OutputType>Library</OutputType>
<!-- Change to static library -->
<NativeLib>Static</NativeLib>
<!-- Optimize for size instead of speed -->
<IlcOptimizationPreference>Size</IlcOptimizationPreference>
<!-- Disable unsafe code -->
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>dotnet publish -c Release -r win-x64
dotnet publish -c Release -r linux-x64
dotnet publish -c Release -r osx-arm64MIT