[NativeAOT] Make the trimmable typemap the default#11822
Draft
simonrozsival wants to merge 15 commits into
Draft
[NativeAOT] Make the trimmable typemap the default#11822simonrozsival wants to merge 15 commits into
simonrozsival wants to merge 15 commits into
Conversation
NativeAOT now defaults to and requires _AndroidTypeMapImplementation=trimmable: - Microsoft.Android.Sdk.NativeAOT.targets: default managed -> trimmable; always run _PreTrimmingFixLegacyDesignerUpdateItems before NativeCompile. - Xamarin.Android.Common.targets: error if NativeAOT is used with a non-trimmable typemap; run the post-ILLink AssemblyModifierPipeline for NativeAOT+trimmable (split out _GetAfterILLinkAdditionalStepsInputs); skip the project proguard config for NativeAOT+trimmable. - Microsoft.Android.Sdk.TypeMap.Trimmable.targets: disable ManagedPeerNativeRegistration for trimmable; depend on IlcDynamicBuildPropertyDependencies on NativeAOT. - JNIEnvInit / JreRuntime: NativeAOT now throws if the trimmable type map is not used, and the reflection-backed managers are wrapped in IL2026-suppressed helpers so Mono.Android and the NativeAOT runtime host build clean under trimming. Test infrastructure for follow-up NativeAOT triage: - BaseTest: IgnoreNativeAotLinkedAssemblyChecks / IgnoreOnNativeAot helpers. - Mono.Android-Tests: add a TrimmableTypeMapUnsupported excluded category. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mmable path _PreTrimmingFixLegacyDesignerUpdateItems is only defined in the LlvmIr typemap targets, which are not imported for trimmable builds. Referencing it from _AndroidRunNativeCompileDependsOn unconditionally broke NativeAOT (now trimmable by default) with MSB4057. Restore the per-typemap condition so the trimmable path only depends on NativeCompile. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NativeAOT trims with ILC and does not produce illink's obj/<config>/<rid>/linked/
directory, so tests that inspect linked assemblies (or assert the obsolete
PreserveAttribute IL6001 warning, or use the unsupported 'Lowercase' package naming
policy) cannot run as-is on NativeAOT. Guard them with the BaseTest helpers:
- LinkerTests: AndroidAddKeepAlives, AndroidUseNegotiateAuthentication,
PreserveIX509TrustManagerSubclasses, PreserveServices (linked/ inspection),
WarnWithReferenceToPreserveAttribute (IL6001).
- BuildTest2: NativeAOT (linked/Mono.Android.dll inspection), BuildReleaseArm64.
- IncrementalBuildTest: AppProjectTargetsDoNotBreak, LinkAssembliesNoShrink (linked/),
ChangePackageNamingPolicy ('Lowercase' policy unsupported on trimmable).
Verified locally: PreserveIX509TrustManagerSubclasses(NativeAOT) now reports Skipped
instead of DirectoryNotFoundException, while the CoreCLR case still passes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Making the trimmable type map the default removed the reflection-backed manager IL3050/IL2026 warnings on NativeAOT (the managers are now suppressed/trimmable-only), so the NativeAOT build produces zero warnings. Replace the IL3050 warning-count assertion with AssertHasNoWarnings (). Verified locally: BuildHasNoWarnings (True,*,NativeAOT) apk+aab now pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ault - XASdkTests: NativeAOT is now warning-clean (the reflection-manager IL3050/IL3053 warnings are gone), so assert no warnings instead of one. - ManifestTest.ExportedErrorMessage: the trimmable manifest generator orders merged components differently, so assert the coded AMM0000 error for NativeAOT without the exact manifest line/column (verified: NativeAOT case passes). - BuildWithLibraryTests.ProjectDependencies: the trimmable typemap trims Java Callable Wrappers for library types that are never instantiated, so the unused LibraryB JCWs are absent from classes.dex by design; skip the NativeAOT case (verified locally: the scrc64-named JCW .class files are generated but trimmed out of the dex). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
With the trimmable typemap default, NativeAOT no longer produces the reflection-manager IL3050 warnings, so the 'Mono.Android produced AOT analysis warnings' IL3053 aggregate is gone. Assert the build has no warnings for all runtimes. Verified: XA4310 (apk/aab, NativeAOT) pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NativeAOT release builds emit a proguard mapping.txt in the output directory (confirmed in local NativeAOT build outputs), so add it to the expected file list for the NativeAOT release case of DotNetBuild. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Per review feedback, NativeAOT should keep falling back to ManagedTypeManager (type manager) and JavaMarshalValueManager (value manager) when the trimmable type map is not used, rather than throwing. The MSBuild hard error in Common.targets remains the guard that prevents NativeAOT + non-trimmable builds. The reflection-backed managers are wrapped in IL2026/IL3050-suppressed local helpers so Mono.Android and the NativeAOT runtime host still build clean under trimming; the trimmable-first branch dead-codes the fallback in app builds, so NativeAOT remains warning-free (verified: BuildHasNoWarnings NativeAOT apk+aab pass). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…chable Drop the hard error that required _AndroidTypeMapImplementation=trimmable on NativeAOT. For now this PR only flips the NativeAOT default to trimmable while keeping the existing managed/llvm-ir configurations reachable (the runtime keeps its ManagedTypeManager / JavaMarshalValueManager fallbacks). Removing the non-trimmable NativeAOT paths and re-introducing the error will be done in a separate PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This test inspected illink's linked/Mono.Android.dll and the legacy ManagedTypeMapping class to verify the managed type-map. With the trimmable typemap now the NativeAOT default, ILC produces neither that linked/ output nor the ManagedTypeMapping type, so the test no longer applies. Remove it rather than leaving a permanently-ignored test; a DGML-based type-map check for NativeAOT can be added as a follow-up. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…sival/trimmable-typemap-default-nativeaot
Member
Author
|
/azp run |
|
Azure Pipelines could not run because the pipeline triggers exclude this branch/path. |
The test asserts the build fails with XA8000 for SkiaSharp's unresolved @styleable/SKCanvasView, which relies on FixLegacyResourceDesignerStep. That legacy resource-designer step is intentionally not run on the trimmable typemap path (the NativeAOT default), so the diagnostic isn't emitted and the NativeAOT case no longer applies. Skip it on NativeAOT via the IgnoreOnNativeAot helper. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The merge of dev/simonrozsival/trimmable-managers left two identical CreateAndroidValueManager local functions in JNIEnvInit.CreateValueManager, causing CS0128. Remove the redundant second definition. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
R8 shrinks bound library Java types (JavaSourceJarTest, JavaSourceTestExtension) out of classes.dex on the trimmable typemap path because the proguard keep config is incomplete on NativeAOT, so the class-presence assertions fail. Skip the NativeAOT case via IgnoreOnNativeAot until the underlying proguard-keep bug is fixed. Tracked by #11774. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The trimmable typemap generates additional Java Callable Wrappers that trip XA0102 lint warnings. Ignore on NativeAOT until #11774 is resolved. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Goal
Make the trimmable typemap the default typemap for NativeAOT.
Supersedes #11617. That PR bundled the reflection-free
TrimmableTypeMapType/ValueManagerruntime work and the NativeAOT default flip into one large change. The runtime/manager foundation has since landed in smaller PRs (this PR is based ondev/simonrozsival/trimmable-managers, #11801), so this PR is the focused remainder: flip the NativeAOT default totrimmableand adjust the tests accordingly.Contributes to #10794, #11012, #8724.
Change map
Core enablement
Microsoft.Android.Sdk.NativeAOT.targets— default_AndroidTypeMapImplementationmanaged→trimmable.Xamarin.Android.Common.targets— run the post-ILLinkAssemblyModifierPipelinefor NativeAOT+trimmable (split out_GetAfterILLinkAdditionalStepsInputs); skip the project proguard config for NativeAOT+trimmable. (All gated ontrimmable, somanaged/llvm-irNativeAOT is unchanged.)Microsoft.Android.Sdk.TypeMap.Trimmable.targets— disableManagedPeerNativeRegistrationfor trimmable; depend on ILC'sSetupProperties($(IlcDynamicBuildPropertyDependencies)) on NativeAOT so the runtime-pack framework assemblies are resolved before the typemap is generated.JNIEnvInit/JreRuntime— the reflection-backed managers (ManagedTypeManager,AndroidTypeManager,AndroidValueManager,JavaMarshalValueManager) are wrapped in IL2026/IL3050-suppressed local helpers so Mono.Android and the NativeAOT runtime host build clean under trimming. NativeAOT keeps falling back toManagedTypeManager/JavaMarshalValueManagerwhen the trimmable type map is not used.Tests
BaseTest—IgnoreNativeAotLinkedAssemblyChecks/IgnoreOnNativeAothelpers.obj/<config>/<rid>/linked/output (ILC doesn't produce it):LinkerTests(×5),BuildTest2.BuildReleaseArm64,IncrementalBuildTest(×3).BuildTest2.NativeAOTis deleted (it verified the legacylinked/ManagedTypeMapping, which ILC no longer produces).BuildHasNoWarnings,XASdkTests, andXA4310now assert no warnings.ManifestTest.ExportedErrorMessageasserts the codedAMM0000error without the exact manifest line.BuildWithLibraryTests.ProjectDependenciesis skipped on NativeAOT (the trimmable typemap trims JCWs for library types that are never instantiated).DotNetBuildexpectsmapping.txtfor NativeAOT release.Mono.Android-Testsdefines aTrimmableTypeMapUnsupportedexcluded category for on-device runs.Local validation
make all→ 0 errors / 0 warnings.Build_WithTrimmableTypeMap_Succeeds(NativeAOT) → pass.Microsoft.Android.Sdk.TrimmableTypeMap.Tests→ 597 pass.Still to validate in CI
Mono.Android.NET-Tests(NativeAOT) and any apkdesc/size baseline updates — these need the full CI matrix and are deferred to this PR's CI run.Draft until CI confirms the full matrix (device tests + baselines).
Research note: legacy resource-designer fix is intentionally NOT run on trimmable NativeAOT
The non-trimmable NativeAOT path runs
FixLegacyResourceDesignerStepbefore ILC (the_PreTrimmingFixLegacyDesigner*targets inMicrosoft.Android.Sdk.TypeMap.LlvmIr.targets). Thetrimmable path does not import those targets, so on trimmable NativeAOT this step does not run — and
this PR keeps it that way (
_AndroidRunNativeCompileDependsOnfor trimmable depends only onNativeCompile). That choice was validated with a small experiment (library + app, IL decompiled):AndroidUseDesignerAssembly=true): the step is a no-op.Library code compiles to
call _Microsoft.Android.Resource.Designer.Resource/Layout::get_<id>()(notldsfld), andFixLegacyResourceDesignerSteponly rewritesldsfld. The optimizer then inlines thatgetter to the correct final aapt2 id as a constant (verified: linked values
0x7F040000/0x7F030000matched the merged
R.txt). So for the common case, running or not running the step makes nomeasurable difference.
AndroidUseDesignerAssembly=false, e.g. old SkiaSharp) emitldsfldagainst aretained
Resourceclass whose static fields are populated at runtime byAndroid.Runtime.ResourceIdManager.UpdateIdValues(). Resource ids therefore still resolve correctly atruntime without the rewrite; what the step additionally provides is the XA8000 unresolved-resource
diagnostic and the ability to trim the designer class (a size win).
Decision: for trimmable NativeAOT we accept forgoing the XA8000 diagnostic / size win for legacy
AndroidUseDesignerAssembly=falselibraries, rather than porting the legacy step. Modern libraries — theoverwhelming majority — are unaffected. Porting the step to the trimmable NativeAOT path can be revisited
separately if legacy-AAR support on NativeAOT turns out to need it.