Repository navigation
[Microsoft.Android.Build.Tasks] Read linked typemap keys - #12824
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Unsupported linked-assembly paths must consistently report XA4327 by catching NotSupportedException.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (1)
What changed in this PR
Adds a modern MSBuild task that extracts surviving typemap keys from linked assemblies and emits canonical sorted UTF-8 output.
Changes:
- Implements typemap key extraction, normalization, sorting, and XA4327 diagnostics.
- Adds unit and ILLink integration coverage.
- Links metadata helpers, enables unsafe code, and configures pinned ILLink test dependencies.
Review notes:
- Moderate:
NotSupportedExceptionfromFile.OpenReadis not caught on lines 37 and 56, causing XAETMKA7015 instead of XA4327. - Nit: Use a file-scoped namespace in the new task file.
| File | Description |
|---|---|
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj |
Adds ILLink package and path metadata for integration tests. |
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/ExtractTypeMapKeysFromAssembliesTests.cs |
Tests extraction, normalization, malformed inputs, failures, and linking. |
src/Microsoft.Android.Build.Tasks/Tasks/ExtractTypeMapKeysFromAssemblies.cs |
Implements assembly typemap key extraction and output generation. |
src/Microsoft.Android.Build.Tasks/Microsoft.Android.Build.Tasks.csproj |
Enables unsafe compilation and links metadata helpers. |
| foreach (var assembly in LinkedAssemblies) { | ||
| try { | ||
| ReadKeys (assembly.ItemSpec, keys); | ||
| } catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException || ex is BadImageFormatException || ex is ArgumentException) { |
There was a problem hiding this comment.
maybe this should just catch all Exception types? not a blocker, though.
05926f2 to
79668b8
Compare
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
79668b8 to
4eca7b4
Compare
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
133c588 to
2fd2fe8
Compare
2fd2fe8 to
d8fecf4
Compare
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Extract surviving generic TypeMapAttribute keys from linked managed assemblies, with canonical alias and array normalization and explicit malformed-input failures. Add focused production-task coverage including the pinned real ILLink fixture. Layer 3 of the #12821 split; MSBuild activation remains in a later layer. Co-authored-by: Copilot App <[email protected]>
Provide empty fixtures for optional Windows framework assemblies so the test can keep strict unresolved-reference checking across hosts. Co-authored-by: Copilot App <[email protected]>
d8fecf4 to
7033d4b
Compare
|
/review |
|
❌ Android PR Reviewer failed. Please review the logs for details. Warning Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding. What happenedThe threat detection engine failed to produce results. Review the workflow run logs for details.
|
|
/review |
|
❌ Android PR Reviewer failed. Please review the logs for details. Warning Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding. What happenedThe threat detection engine failed to produce results. Review the workflow run logs for details.
|
## Why Layer 2 of 4 in native stack #12893, depending on #12824. This adds the NativeAOT representation adapter so typemap-based ProGuard rules can consume the keys retained in the final ILC native object rather than infer retention from a dependency graph. ## Extraction contract - `ExtractTypeMapKeysFromNativeAotObject` reads final relocatable ELF objects using LLVM section/symbol metadata and common-fixup relocations to select the Java type-map groups by their EEType identities. It does not scan arbitrary strings or guess group membership from key appearance. - `NativeAotTypeMapReader` enumerates the selected NativeFormat groups, reusing the existing alias/array normalization and class-name validation helpers. Output is a deterministic union of canonical class keys; invalid required inputs fail with XA4327. - Add the frozen parser/adapter coverage, native-object fixture helpers, tool-path test metadata, and test-catalog instructions. All eight changed files match the frozen #12821 snapshot exactly. ## Tools and scope Extraction requires an existing full path to NDK `llvm-readobj` with adjacent `llvm-objdump`; native test fixtures additionally need adjacent `clang`. Supply `-p:_NativeAotLlvmReadObjPath=/path/to/ndk/bin/llvm-readobj` for native-tool test cases. This layer does **not** activate product targets, add assembly-resolution metadata, expand shared target integration tests, change R8 policy, enable NativeAOT trimming, or retire DGML. The existing DGML pipeline remains active; build activation and policy follow in layers 3 and 4. ## Validation Standalone trimmable typemap project built with .NET 11 preview 7 and `-p:_AndroidTreatWarningsAsErrors=true`, passing the existing NDK tool path. Targeted NativeAOT, linked-DLL, LLVM, ProGuard-generator, typemap-generator, and class-name coverage: **694 passed, 0 failed, 0 skipped**. `NativeAotObjectIntegrationTests.cs` contains shared tool/attribute helpers at this layer; real-object MSBuild integration test methods depend on the later shared target-test expansion and are not claimed as executed here.
## Summary Layer 4 of 4 in native stack #12893, depending on #12827 (`simonrozsival-typemap-msbuild-pipeline`). Activate the shared retained-typemap rule pipeline so eligible CoreCLR and explicitly opted-in NativeAOT R8 builds derive Java class roots from retained typemap keys rather than keeping every ACW. This removes the dependency on large NativeAOT DGML graphs while preserving runtime/JNI roots and user-authored Java source retention. - Import the shared MSBuild pipeline, wire R8 flags/resources and incremental inputs, and gate legacy configuration generation. CoreCLR keeps scoped JNI-facing members and optimization while disabling renaming; NativeAOT retains class-wide member preservation and remains opt-in for NDK-backed object inspection. - Remove the old DGML producer, resource, diagnostics implementation, and graph-specific test fixtures; retain the interface-collection runtime test. - Add R8, build, and scoped-member device coverage; restore the three deferred `TypeMapProguardTests` methods and their attributes (17 cases); document retention behavior and retired diagnostics. ## Validation ```sh dotnet test tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests.csproj \ -v minimal \ --filter 'FullyQualifiedName~TypeMapProguardTests|FullyQualifiedName~ExtractTypeMapKeys' \ -p:_AndroidTreatWarningsAsErrors=true \ -p:_NativeAotLlvmReadObjPath="$NDK_LLVM_BIN/llvm-readobj" ``` Passed **294/294**, **0 skipped**: 53 pipeline/generator cases (including all 17 restored cases) and 241 retained-key adapter cases. Used the supplied existing Android NDK `llvm-readobj` and adjacent `llvm-objdump`/`clang` executables read/execute-only. All six changed XML targets/resources parse successfully with `xmllint --nonet --noout`, including XML comments. `git diff --check` passes. **Not run:** `Xamarin.Android.Build.Tests` R8/build cases and `MSBuildDeviceIntegration` device cases. This worktree has neither a local built Android SDK (`bin/Debug/dotnet/dotnet` or Release) nor the corresponding test assemblies. No full SDK bootstrap or new tooling installation was performed for this frozen split. ## Frozen split integrity Exactly 28 paths, +601/-1081, relative to #12827. The final tree is exactly `168821457836836b55368bb7ad53c2bfd9833cb4`: frozen source `87bd3f8a8b512859339e5446c1f86709a6c28c3b` with the base XA1037 documentation/localization/JavaSourceUtils changes preserved. `TypeMapProguardTests.cs` is byte-identical to the frozen source. No non-English localization files changed. Native stack #12893 is registered with #12824, #12825, #12827, and this PR in order. The closed LLVM adapter #12823 is not in this stack.

Why
Layer 1 of 4 in the remaining #12821 stack, based on main. The foundation #12822 has merged; the LLVM adapter #12823 is closed and omitted. Typemap-derived ProGuard rules need the Java class keys that survive ILLink, rather than pre-link registration metadata or stale alias arrays.
Changes
Add
ExtractTypeMapKeysFromAssembliesin the modernMicrosoft.Android.Build.Tasksassembly. It reads surviving assembly-level genericTypeMapAttributeentries, unions and sorts their keys, normalizes alias suffixes and object-array descriptors, and writes canonical UTF-8 output. Empty linked stubs are valid; absent inputs, malformed assemblies/attributes/keys, and output failures report XA4327.Source-link the existing metadata helpers and enable unsafe blocks in the modern task project. Add the pinned ILLink package and its path metadata to the standalone test project, retaining its production-task
ProjectReference.This layer does not activate the task in MSBuild or change R8 policy. Native-object extraction, orchestration, and legacy cleanup remain in later layers. The copied extractor and fixture exactly match frozen source
87bd3f8a8b512859339e5446c1f86709a6c28c3b; the test-project native-object metadata is intentionally deferred to layer 4.Validation
On .NET SDK
11.0.100-preview.7.26381.103, the following focused standalone run passed 89/89, with no skips, using the actual modern production task DLL. This includesRealILLinkRetainsOnlyLiveTypeMapAttributeswith pinnedMicrosoft.NET.ILLink.Tasks11.0.0-rc.2.26461.115.Base:
main. Bottom of native stack #12893.