[WIP][TrimmableTypeMap] Decompose _GenerateJavaStubs: shared tasks for trimmable path#10810
Draft
simonrozsival wants to merge 12 commits intodev/simonrozsival/trimmable-typemap-03-generatorsfrom
Conversation
83a50be to
4e7d06c
Compare
Extract all typemap-related MSBuild targets from Xamarin.Android.Common.targets and Microsoft.Android.Sdk.ILLink.targets into a dedicated Xamarin.Android.TypeMap.Legacy.targets file, imported conditionally based on _AndroidTypeMapImplementation. Create empty stub files for the trimmable typemap implementation (Trimmable.targets, Trimmable.CoreCLR.targets, Trimmable.NativeAOT.targets). This is a pure refactoring — no new tasks, no new C# code, no behavioral changes. When _AndroidTypeMapImplementation != 'trimmable' (the default), the legacy targets are imported and the build pipeline is identical to before. Changes: - New: Xamarin.Android.TypeMap.Legacy.targets — all legacy typemap targets - _GenerateLegacyJavaCallableWrappers (JCW gen, ACW map, stubs, marshal methods) - _GenerateLegacyAndroidManifest (manifest + additional providers) - _GenerateLegacyTypeMappings (LLVM IR typemaps) - _SetLegacyTypemapProperties (_TypeMapKind) - _GetMonoPlatformJarPath (overrides empty stub) - _PrepareNativeAssemblySources (overrides empty stub) - _AddLegacyTypeManagerResources (TypeManager.java + mono.android.jar) - _RemoveRegisterAttribute (full version with RemoveRegisterAttribute task) - _CollectLegacyTypeMapFiles (FastDev archive) - New: Xamarin.Android.TypeMap.Trimmable.targets — dispatcher + validation stub - New: Xamarin.Android.TypeMap.Trimmable.CoreCLR.targets — empty stub - New: Xamarin.Android.TypeMap.Trimmable.NativeAOT.targets — empty stub - Modified: Common.targets — stripped of all legacy typemap task invocations, added empty stubs + conditional imports - Modified: ILLink.targets — added conditions to skip legacy ILLink steps when _AndroidTypeMapImplementation == 'trimmable' Fixes: #10779
…erateLegacyAndroidManifest GenerateMainAndroidManifest unregisters NativeCodeGenState from the build engine, so GenerateTypeMappings must retrieve it first. Add DependsOnTargets to ensure correct ordering between the two AfterTargets targets.
Move _PrepareLinking, _FixRootAssembly, and _TouchAndroidLinkFlag from Microsoft.Android.Sdk.ILLink.targets into Xamarin.Android.TypeMap.Legacy.targets. This eliminates scattered _AndroidTypeMapImplementation != 'trimmable' conditions in ILLink.targets — the conditions are now implicit since Legacy.targets is only imported when _AndroidTypeMapImplementation is not 'trimmable'.
Address PR feedback: - Rename Xamarin.Android.TypeMap.*.targets -> Microsoft.Android.Sdk.TypeMap.*.targets - Move files to Microsoft.Android.Sdk/targets/ (new file convention) - Remove @(None) entries (handled by _CopyNetSdkTargets wildcard) - Delete Microsoft.Android.Sdk.ILLink.targets (moved _LinkAssemblies to Common.targets) - Add _ValidateAndroidTypeMapImplementation target - Add _GenerateJavaStubs stub in Trimmable.targets - Fix UsingTask references to use $(_XamarinAndroidBuildTasksAssembly) - Fix ILLink DLL paths for targets/ directory context
…e stub - Restore missing TypeMappingStep ILLink custom step for managed typemap implementation (used by NativeAOT) - Add proper DependsOnTargets, Inputs/Outputs, and stamp file to the trimmable _GenerateJavaStubs stub for incremental build support - Add TODO comment about manifest extraction (#10807): both GenerateMainAndroidManifest and GenerateAdditionalProviderSources depend on NativeCodeGenState and need to be decoupled before they can be shared across typemap paths
Introduce Microsoft.Android.Build.TypeMap assembly with a two-phase scanner that extracts Java peer type information from .NET assemblies using SRM (no Mono.Cecil dependency). Key components: - JavaPeerScanner: scans assemblies for [Register], [Export], and component attributes to build JavaPeerInfo entries - AssemblyIndex: per-assembly O(1) lookup index built in phase 1 - JavaPeerInfo/MarshalMethodInfo: rich data model for downstream generators (PR2/PR3) - CRC64 package name computation via System.IO.Hashing Tests: - 62 xUnit tests covering all scanner code paths - 3 integration tests comparing side-by-side with legacy Cecil-based scanner on Mono.Android.dll (all pass)
- Rename project from Microsoft.Android.Build.TypeMap to Microsoft.Android.Sdk.TrimmableTypeMap to match naming of Microsoft.Android.Sdk.ILLink and Microsoft.Android.Sdk.Analysis - Fix ParseJniType crash on malformed JNI signatures - Add cycle detection to ExtendsJavaPeer - Fix SignatureTypeProvider nested type resolution - Implement GetUnderlyingEnumType via value__ field inspection - Implement TryGetTypeProperty for BackupAgent and ManageSpaceActivity - Fix InternalsVisibleTo: remove AssemblyName hack, add proper entries - Add 7 ParseJniSignature unit tests
…rom [Application] Types referenced by [Application(BackupAgent = typeof(X))] or [Application(ManageSpaceActivity = typeof(X))] are now forced unconditional in Phase 3 of the scan, since the manifest will reference them regardless of whether anything else in managed code does. Added 3 unit tests, removed the skipped test placeholder.
…overage Review-driven fixes: Bug fixes: - Fix critical bug: constructor JNI signatures were hardcoded to "()V" in BuildNativeRegistrations. Now propagated from JavaConstructorInfo through UcoConstructorData.JniSignature to NativeRegistrationData. - Fix non-deterministic alias ordering: replaced Dictionary with SortedDictionary, sort alias peers by ManagedTypeName. - Fix Export attribute ThrownNames parsing: string[] was not being decoded from ImmutableArray<CustomAttributeTypedArgument<string>>. Test improvements: - Cache scanner results with static Lazy<> in all test classes - Add parameterized constructor JNI signature test - Add fixture-based CustomView constructor signature assertions - Add PE blob validation tests (2-arg vs 3-arg TypeMap attributes) - Add determinism test (same input → same output) - Add Export with throws clause test fixture + JCW test - Fix Build_CreatesOneEntryPerPeer for alphabetical ordering Code quality: - Add ECMA-335 comment explaining Type args as serialized strings - Add comment explaining UCO constructor 2-param signature - Fix doc comment: remove 'Intermediate representation' wording 215 tests pass, 1 skipped.
…support - Invoker types no longer get their own proxy types or TypeMap entries. They are only referenced as a TypeRef in the interface proxy's get_InvokerType property and CreateInstance method. - Invoker detection now uses explicit relationship from [Register] third argument (InvokerTypeName) instead of name-based heuristic. - Interface proxy CreateInstance creates the invoker type, not the interface itself. - Added dotnetVersion parameter to TypeMapAssemblyEmitter, TypeMapAssemblyGenerator, and RootTypeMapAssemblyGenerator constructors (will be passed from $(DotNetTargetVersion) MSBuild property later). - JCW generator now uses SuperArgumentsString for [Export] constructor super() calls instead of always forwarding all parameters. - Documented PE-reading test helpers with clear comments explaining the approach and its limitations.
Implement core building blocks for issue #10807: Phase 1: ACW map generation - AcwMapWriter: generates acw-map.txt from scanner results with XA4214/XA4215 conflict detection - TrimmableTypeMapGenerator: per-assembly pipeline orchestrator (scan → TypeMap → JCW → ACW map → component data) Phase 2: IManifestTypeInfo abstraction - IManifestTypeInfo interface: decouples manifest generation from Cecil - ManifestTypeInfo: default mutable implementation - ManifestComponentKind enum: Activity, Service, BroadcastReceiver, ContentProvider, Application, Instrumentation - ComponentAttributeInfo: raw property dictionaries for attributes Phase 3: Component attribute extraction - ComponentAttributeExtractor: SRM-based extraction of component attributes ([Activity], [Service], etc.) and sub-attributes ([IntentFilter], [MetaData], [Layout], [Property], [GrantUriPermission]) - Integrated into JavaPeerScanner (ComponentData on JavaPeerInfo) - ScannerManifestTypeInfoAdapter: converts scanner output to IManifestTypeInfo objects - ComponentDataSerializer: text-based serialization for inter-target communication of component data Tests: 346 tests (28 new) covering all new code: - AcwMapWriterTests (14 tests) - ManifestTypeInfoTests (12 tests) - ComponentAttributeExtractorTests (19 tests) - ScannerManifestTypeInfoAdapterTests (16 tests) - EndToEndTests (10 tests) - ComponentDataSerializerTests (19 tests) - TrimmableTypeMapGeneratorTests (9 tests)
…apGenerator Remove 1,280 lines of unnecessary code: - ComponentDataSerializer (349 lines) + tests (512 lines): custom text serializer with no consumer — ScannerManifestTypeInfoAdapter already converts JavaPeerInfo → IManifestTypeInfo directly - TrimmableTypeMapGenerator (118 lines) + tests (212 lines): pipeline orchestrator with no caller — individual pieces are independently tested Also trim verbose doc comments and simplify null-coalescing in ScannerManifestTypeInfoAdapter. All 318 tests pass.
1459e93 to
01136d4
Compare
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.
Part of #10807
Stacked on #10808
Summary
Decomposes the monolithic
_GenerateJavaStubsmega-target to extract shared tasks (ACW map generation, manifest generation, provider sources) that both the legacy LLVM IR path and the new trimmable typemap path need.What's included
IManifestTypeInfoabstraction (~40 lines)Interface decoupling manifest generation from Cecil. Implemented by both
CecilManifestTypeInfoAdapter(legacy) andScannerManifestTypeInfoAdapter(trimmable). Compiled into both projects via<Compile Include>.ManifestXmlGenerator(~264 lines)Generates AndroidManifest.xml XElements from
ComponentAttributeInfodata without Cecil. Maps ~90 C# attribute properties toandroid:xxxXML attributes. Handles IntentFilter constructor args, data elements, layout, meta-data, property, and grant-uri-permission sub-elements.ManifestDocument.Merge()dual-pathModified to accept
IReadOnlyList<IManifestTypeInfo>instead ofList<TypeDefinition>. Cecil path casts toCecilManifestTypeInfoAdapterfor the existing pipeline. Non-Cecil path usesManifestXmlGenerator.GenerateTrimmableJavaStubsMSBuild task (~141 lines)Replaces
GenerateJavaStubs + GenerateMainAndroidManifestfor the trimmable path. UsesJavaPeerScannerfor scanning,AcwMapWriterfor ACW map,ScannerManifestTypeInfoAdapterfor conversion.Trimmable.targetswiringFully wired with
GenerateTrimmableJavaStubs+GenerateAdditionalProviderSources. Stamp-based incrementality,_ManifestOutput,_MergedManifestDocuments,FileWrites.Supporting types
AcwMapWriter— generatesacw-map.txtfrom scanner resultsUnconditionalMarker— marks types from customview-map and manifest as unconditionalManifestTypeReader— readsandroid:namefrom merged manifestCecilManifestTypeInfoAdapter— wraps CecilTypeDefinition→IManifestTypeInfoTests (349 total, ~1k lines new)
Diff vs base branch
~1,059 lines added (production + tests for this issue only)