Description
For example:
TestApp.csproj (normal console app)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\TestLib\TestLib.csproj" />
<TrimmerRootAssembly Include="TestLib" />
</ItemGroup>
</Project>
And then the TestLib
contains
using System.Runtime.Loader;
namespace TestLib;
internal class Derived : AssemblyLoadContext
{
}
Now running (on the TestApp):
dotnet publish --self-contained /p:PublishTrimmed=true
The output will contain AssemblyLoadContext
class in CoreLib, but for example the AssemblyLoadContext.GetAssemblyName
method will be missing from it (since it's not used anywhere).
Now publishing the same app with NativeAOT:
dotnet publish /p:PublishAot=true
Using sizoscope tells us that AssemblyLoadContext.GetAssemblyName
is actually preserved in the app.
In short, the NativeAOT implementation of assembly rooting seems to be rooting too much. For example it seems to fully root all base types of the types from the target assembly, including all members on such base types.
This is not a problem necessarily for cases where TrimmerRootAssembly
is used as a workaround to trim incompatibilities (it's adds more code), but it can matter more when it's used in a test app to validate trim/AOT compatibility of a library.
It would also be nice to make the behavior consistent between illink
and ilc
.