Summary
I ran an isolated worktree experiment to test whether the current custom NuGet helper libraries (NuGetFetch / SourceLinkFetch) could be replaced by the official NuGet client libraries now that upstream NuGet.Client marks projects as IsAotCompatible=true.
The result is not yet good enough for dotnet-inspect's NativeAOT use case.
The intended bar here is not just "publishes under NativeAOT", but:
- libraries built with
IsAotCompatible
- zero trim/AOT warnings in our scenario
- working real remote operations at runtime under NativeAOT
What I tested
In a worktree on branch experiment/official-nuget-aot, I created two small benchmark harnesses that exercised the same kinds of remote package operations this app depends on:
- search latest package version
- list package versions
- download a
.nupkg
Package used for comparison: Newtonsoft.Json (pinned download version 13.0.3)
Stacks compared:
- Current custom path:
NuGetFetch via DotnetInspector.Packages
- Official path:
NuGet.Protocol 7.3.0
Upstream signal
NuGet.Client does now opt into AOT-compatibility metadata:
<PropertyGroup Condition="'$(IsAotCompatible)' == '' And '$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
Source: NuGet.Client/src/NuGet.Core/Directory.Build.targets
That is encouraging, but it did not translate into a clean warning-free or runtime-successful NativeAOT result in this experiment.
NativeAOT publish outcome
Current custom path (NuGetFetch)
- NativeAOT publish: success
- Remote operations at runtime: success
- Published executable size: 8,799,136 bytes
- Publish directory size: 39,092,224 bytes
Measured NativeAOT timings (5 iterations):
- search latest: 144.33 ms avg
- list versions: 72.90 ms avg
- download nupkg: 340.74 ms avg
Official path (NuGet.Protocol 7.3.0)
- NativeAOT publish: success, but with warnings
- Warnings included:
IL2104: NuGet.Protocol produced trim warnings
IL2104: NuGet.Configuration produced trim warnings
IL2104 / IL3053: Newtonsoft.Json produced trim/AOT analysis warnings
- Remote operations at runtime: failed
- Published executable size: 15,783,896 bytes
- Publish directory size: 77,299,712 bytes
So even before runtime behavior, this failed the stricter goal of "IsAotCompatible with zero warnings."
NativeAOT runtime failures with official libraries
The official stack published, but real network operations failed under NativeAOT:
Search failure
JsonSerializationException: Unable to find a constructor to use for type NuGet.Protocol.PackageSearchMetadata.
A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.
Path 'data[0].@id', line 1, position 149.
This came from NuGet.Protocol.PackageSearchResourceV3 while processing the nuget.org search response.
Version listing / download failure
FatalProtocolException: Unable to get repository signature information for source
https://api.nuget.org/v3-index/repository-signatures/5.0.0/index.json.
Both version listing and package download hit this under NativeAOT.
CoreCLR comparison
For reference, both stacks worked on CoreCLR:
| Stack |
Search avg |
Versions avg |
Download avg |
| NuGetFetch |
461.96 ms |
105.75 ms |
437.14 ms |
| NuGet.Protocol |
687.71 ms |
295.15 ms |
408.33 ms |
CoreCLR published directory sizes were similar (~88.7 MB vs ~90.1 MB), but the NativeAOT size delta was substantial.
Conclusion
The official libraries are closer than they used to be because they now advertise AOT compatibility, but for dotnet-inspect they are not yet a drop-in replacement for the custom libraries.
At least in this experiment, they miss the target in three ways:
- trim/AOT warnings are still present
- real remote operations fail under NativeAOT
- NativeAOT output size is much larger than the current custom path
Suggested next steps
- Keep the current custom NuGet helper path for now
- Revisit after upstream NuGet.Protocol / NuGet.Configuration can pass this scenario with:
- zero AOT warnings
- successful search/version/download operations under NativeAOT
- Optionally distill this into a smaller upstream repro if we want to file against NuGet.Client
Summary
I ran an isolated worktree experiment to test whether the current custom NuGet helper libraries (
NuGetFetch/SourceLinkFetch) could be replaced by the official NuGet client libraries now that upstream NuGet.Client marks projects asIsAotCompatible=true.The result is not yet good enough for dotnet-inspect's NativeAOT use case.
The intended bar here is not just "publishes under NativeAOT", but:
IsAotCompatibleWhat I tested
In a worktree on branch
experiment/official-nuget-aot, I created two small benchmark harnesses that exercised the same kinds of remote package operations this app depends on:.nupkgPackage used for comparison:
Newtonsoft.Json(pinned download version13.0.3)Stacks compared:
NuGetFetchviaDotnetInspector.PackagesNuGet.Protocol7.3.0Upstream signal
NuGet.Client does now opt into AOT-compatibility metadata:
Source:
NuGet.Client/src/NuGet.Core/Directory.Build.targetsThat is encouraging, but it did not translate into a clean warning-free or runtime-successful NativeAOT result in this experiment.
NativeAOT publish outcome
Current custom path (
NuGetFetch)Measured NativeAOT timings (5 iterations):
Official path (
NuGet.Protocol 7.3.0)IL2104:NuGet.Protocolproduced trim warningsIL2104:NuGet.Configurationproduced trim warningsIL2104/IL3053:Newtonsoft.Jsonproduced trim/AOT analysis warningsSo even before runtime behavior, this failed the stricter goal of "IsAotCompatible with zero warnings."
NativeAOT runtime failures with official libraries
The official stack published, but real network operations failed under NativeAOT:
Search failure
This came from
NuGet.Protocol.PackageSearchResourceV3while processing the nuget.org search response.Version listing / download failure
Both version listing and package download hit this under NativeAOT.
CoreCLR comparison
For reference, both stacks worked on CoreCLR:
CoreCLR published directory sizes were similar (~88.7 MB vs ~90.1 MB), but the NativeAOT size delta was substantial.
Conclusion
The official libraries are closer than they used to be because they now advertise AOT compatibility, but for dotnet-inspect they are not yet a drop-in replacement for the custom libraries.
At least in this experiment, they miss the target in three ways:
Suggested next steps