Summary
DesignTimeBuildSignAndroidPackage(NativeAOT) fails: the IDE-style flow (run Compile, then separately run SignAndroidPackage, both with BuildingInsideVisualStudio=true) never generates the trimmable typemap, so packaging errors:
Microsoft.Android.Sdk.TypeMap.Trimmable.targets(179,5): error :
Trimmable typemap assembly list 'obj/Release/android-arm64/typemap/typemap-assemblies.txt' was not found.
Diagnosis (reproduced locally)
_GenerateTrimmableTypeMap is gated on '$(_OuterIntermediateOutputPath)' == '' (it is meant to run only in the RID-less outer build, because — per its comment — inner/design-time builds "lack the manifest template and full assembly set needed for correct deferred-registration propagation").
In the IDE flow with a RuntimeIdentifier:
-t:Compile -p:BuildingInsideVisualStudio=true runs in the inner RID build (_OuterIntermediateOutputPath = obj/Release/android-arm64/, DesignTimeBuild = false), so _GenerateTrimmableTypeMap is skipped and produces no typemap-assemblies.txt.
-t:SignAndroidPackage -p:BuildingInsideVisualStudio=true is also an inner RID build → _GenerateTrimmableTypeMap skipped again → _ReadGeneratedTrimmableTypeMapAssemblies finds no list and hard-errors (the empty-list fallback only applies when @(ReferencePath->Count()) == 0).
A normal single-invocation dotnet build works because the RID-less outer pass runs _GenerateTrimmableTypeMap first. The legacy _GenerateJavaStubs has no _OuterIntermediateOutputPath gate, so the legacy/CoreCLR path generates stubs in the inner build and this scenario passes.
Fix direction (needs design)
Make the IDE Compile→SignAndroidPackage flow generate the typemap, without regressing the normal outer/inner RID split or the deferred-registration correctness that motivated the outer-only gate. Options:
- Allow
_GenerateTrimmableTypeMap to run in the inner build when no outer build produced the list (guard on !Exists($(_TypeMapAssembliesListFile))), ensuring it still has the inputs it needs; or
- Ensure the IDE/
BuildingInsideVisualStudio flow performs the RID-less outer typemap generation before SignAndroidPackage; or
- Replace the hard
Error with on-demand generation in this flow.
Acceptance criteria
References
- Repro test:
DesignTimeBuildSignAndroidPackage (src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs).
- Code:
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets (_GenerateTrimmableTypeMap line ~81, _ReadGeneratedTrimmableTypeMapAssemblies line ~169).
Summary
DesignTimeBuildSignAndroidPackage(NativeAOT)fails: the IDE-style flow (runCompile, then separately runSignAndroidPackage, both withBuildingInsideVisualStudio=true) never generates the trimmable typemap, so packaging errors:Diagnosis (reproduced locally)
_GenerateTrimmableTypeMapis gated on'$(_OuterIntermediateOutputPath)' == ''(it is meant to run only in the RID-less outer build, because — per its comment — inner/design-time builds "lack the manifest template and full assembly set needed for correct deferred-registration propagation").In the IDE flow with a RuntimeIdentifier:
-t:Compile -p:BuildingInsideVisualStudio=trueruns in the inner RID build (_OuterIntermediateOutputPath = obj/Release/android-arm64/,DesignTimeBuild = false), so_GenerateTrimmableTypeMapis skipped and produces notypemap-assemblies.txt.-t:SignAndroidPackage -p:BuildingInsideVisualStudio=trueis also an inner RID build →_GenerateTrimmableTypeMapskipped again →_ReadGeneratedTrimmableTypeMapAssembliesfinds no list and hard-errors (the empty-list fallback only applies when@(ReferencePath->Count()) == 0).A normal single-invocation
dotnet buildworks because the RID-less outer pass runs_GenerateTrimmableTypeMapfirst. The legacy_GenerateJavaStubshas no_OuterIntermediateOutputPathgate, so the legacy/CoreCLR path generates stubs in the inner build and this scenario passes.Fix direction (needs design)
Make the IDE
Compile→SignAndroidPackageflow generate the typemap, without regressing the normal outer/inner RID split or the deferred-registration correctness that motivated the outer-only gate. Options:_GenerateTrimmableTypeMapto run in the inner build when no outer build produced the list (guard on!Exists($(_TypeMapAssembliesListFile))), ensuring it still has the inputs it needs; orBuildingInsideVisualStudioflow performs the RID-less outer typemap generation beforeSignAndroidPackage; orErrorwith on-demand generation in this flow.Acceptance criteria
DesignTimeBuildSignAndroidPackage(NativeAOT)passes.dotnet build(single + multi-RID) typemap generation unchanged.References
DesignTimeBuildSignAndroidPackage(src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs).src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets(_GenerateTrimmableTypeMapline ~81,_ReadGeneratedTrimmableTypeMapAssembliesline ~169).