-
Notifications
You must be signed in to change notification settings - Fork 568
[TrimmableTypeMap] Generate NativeAOT ProGuard rules from DGML #11449
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
simonrozsival
wants to merge
13
commits into
main
Choose a base branch
from
dev/simonrozsival/11052-nativeaot-proguard-ilc-metadata
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
b3b929a
[TrimmableTypeMap] Generate NativeAOT ProGuard rules from DGML
simonrozsival 907ce46
[TrimmableTypeMap] Split NativeAOT ProGuard task
simonrozsival 5d4aae8
[TrimmableTypeMap] Move ProGuard wiring to typemap targets
simonrozsival 0debe1e
[TrimmableTypeMap] Address ProGuard review feedback
simonrozsival e3d85aa
[TrimmableTypeMap] Enable R8 by default for NativeAOT
simonrozsival 3d4e1cd
[TrimmableTypeMap] Address ProGuard review comments
simonrozsival a5277f4
Fix NativeAOT typemap entrypoint filtering
Copilot 7b2a141
Fix NativeAOT trimmable typemap DGML inputs
simonrozsival b997979
Address NativeAOT ProGuard review comments
simonrozsival 8021b22
Address NativeAOT ProGuard review feedback
simonrozsival b49b3ad
Address NativeAOT ProGuard review comments
Copilot 0329d06
Update src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/…
simonrozsival 42920c3
Fix NativeAOT trimmable typemap ProGuard generation
simonrozsival File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| --- | ||
| title: .NET for Android error XA4319 | ||
| description: XA4319 error code | ||
| ms.date: 05/27/2026 | ||
| f1_keywords: | ||
| - "XA4319" | ||
| --- | ||
|
|
||
| # .NET for Android error XA4319 | ||
|
|
||
| ## Example messages | ||
|
|
||
| ``` | ||
| error XA4319: No NativeAOT DGML files were provided. | ||
| ``` | ||
|
|
||
| ## Issue | ||
|
|
||
| The .NET for Android build could not find any NativeAOT DGML files to use when | ||
| generating trimmable type map ProGuard configuration. | ||
|
|
||
| ## Solution | ||
|
|
||
| This error is expected only for internal build state inconsistencies. Ensure the | ||
| project is building with the intended Runtime Identifier settings and that the | ||
| NativeAOT compile produced its DGML scan file. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| --- | ||
| title: .NET for Android error XA4320 | ||
| description: XA4320 error code | ||
| ms.date: 05/27/2026 | ||
| f1_keywords: | ||
| - "XA4320" | ||
| --- | ||
|
|
||
| # .NET for Android error XA4320 | ||
|
|
||
| ## Example messages | ||
|
|
||
| ``` | ||
| error XA4320: ACW map file '{file}' was not found. | ||
| ``` | ||
|
|
||
| ## Issue | ||
|
|
||
| The .NET for Android build could not find the Android Callable Wrapper (ACW) map | ||
| file needed to generate trimmable type map ProGuard configuration. | ||
|
|
||
| ## Solution | ||
|
|
||
| This error is expected only for internal build state inconsistencies. Rebuild | ||
| the project from a clean state so the ACW map is regenerated. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| --- | ||
| title: .NET for Android error XA4321 | ||
| description: XA4321 error code | ||
| ms.date: 05/27/2026 | ||
| f1_keywords: | ||
| - "XA4321" | ||
| --- | ||
|
|
||
| # .NET for Android error XA4321 | ||
|
|
||
| ## Example messages | ||
|
|
||
| ``` | ||
| error XA4321: NativeAOT DGML file '{file}' was not found. | ||
| ``` | ||
|
|
||
| ## Issue | ||
|
|
||
| The .NET for Android build could not find a NativeAOT DGML scan file needed to | ||
| generate trimmable type map ProGuard configuration. | ||
|
|
||
| ## Solution | ||
|
|
||
| This error is expected only for internal build state inconsistencies. Rebuild | ||
| the project from a clean state and verify the NativeAOT compile produced the | ||
| DGML scan file for the selected Runtime Identifier. |
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
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
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
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
27 changes: 27 additions & 0 deletions
27
src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
15 changes: 15 additions & 0 deletions
15
src/Xamarin.Android.Build.Tasks/Resources/proguard_trimmable_nativeaot.cfg
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # Xamarin.Android NativeAOT trimmable typemap configuration. | ||
|
|
||
| -dontobfuscate | ||
|
|
||
| -keep class net.dot.jni.** { *; <init>(...); } | ||
| -keep class net.dot.android.crypto.** { *; <init>(...); } | ||
|
|
||
| -keepclassmembers class * extends android.view.View { | ||
| *** set*(...); | ||
| } | ||
|
|
||
| -keepclassmembers class * extends android.view.View { | ||
| <init>(android.content.Context,android.util.AttributeSet); | ||
| <init>(android.content.Context,android.util.AttributeSet,int); | ||
| } |
114 changes: 114 additions & 0 deletions
114
src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeAotProguardConfiguration.cs
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| #nullable enable | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using System.Xml; | ||
| using Microsoft.Build.Framework; | ||
| using Microsoft.Android.Build.Tasks; | ||
|
|
||
| namespace Xamarin.Android.Tasks; | ||
|
|
||
| public class GenerateNativeAotProguardConfiguration : AndroidTask | ||
| { | ||
| const string TypeMetadataPrefix = "Type metadata: ["; | ||
|
|
||
| public override string TaskPrefix => "GNAPC"; | ||
|
|
||
| [Required] | ||
| public ITaskItem [] NativeAotDgmlFiles { get; set; } = []; | ||
|
|
||
| [Required] | ||
| public string AcwMapFile { get; set; } = ""; | ||
|
|
||
| [Required] | ||
| public string OutputFile { get; set; } = ""; | ||
|
|
||
| public override bool RunTask () | ||
| { | ||
| var dir = Path.GetDirectoryName (OutputFile); | ||
| if (!dir.IsNullOrEmpty () && !Directory.Exists (dir)) { | ||
| Directory.CreateDirectory (dir); | ||
| } | ||
|
|
||
| if (NativeAotDgmlFiles.Length == 0) { | ||
| Log.LogCodedError ("XA4319", Properties.Resources.XA4319); | ||
| return !Log.HasLoggedErrors; | ||
| } | ||
| if (!File.Exists (AcwMapFile)) { | ||
| Log.LogCodedError ("XA4320", Properties.Resources.XA4320, AcwMapFile); | ||
| return !Log.HasLoggedErrors; | ||
| } | ||
| foreach (var dgmlFile in NativeAotDgmlFiles) { | ||
| if (!File.Exists (dgmlFile.ItemSpec)) { | ||
| Log.LogCodedError ("XA4321", Properties.Resources.XA4321, dgmlFile.ItemSpec); | ||
| return !Log.HasLoggedErrors; | ||
| } | ||
| } | ||
|
|
||
| var retainedTypeKeys = LoadRetainedTypeKeysFromDgml (); | ||
| var javaTypes = LoadJavaTypesFromAcwMap (retainedTypeKeys); | ||
|
|
||
| using var writer = new StringWriter (); | ||
| writer.WriteLine ("# ACWs retained by NativeAOT ILC"); | ||
| foreach (var javaTypeName in javaTypes) { | ||
| writer.WriteLine ($"-keep class {javaTypeName} {{ *; }}"); | ||
| } | ||
| Files.CopyIfStringChanged (writer.ToString (), OutputFile); | ||
|
|
||
| Log.LogMessage (MessageImportance.Low, "Generated {0} NativeAOT trimmable typemap ProGuard rules from {1} DGML file(s).", javaTypes.Count, NativeAotDgmlFiles.Length); | ||
| return !Log.HasLoggedErrors; | ||
| } | ||
|
|
||
| List<string> LoadJavaTypesFromAcwMap (HashSet<string> retainedTypeKeys) | ||
| { | ||
| var javaTypes = new List<string> (retainedTypeKeys.Count); | ||
| var seenJavaTypes = new HashSet<string> (StringComparer.Ordinal); | ||
| foreach (var line in File.ReadLines (AcwMapFile)) { | ||
| var separator = line.IndexOf (";", StringComparison.Ordinal); | ||
| if (separator <= 0 || separator == line.Length - 1) { | ||
| continue; | ||
| } | ||
| var managedTypeName = line.Substring (0, separator); | ||
| var javaTypeName = line.Substring (separator + 1); | ||
| if (retainedTypeKeys.Contains (managedTypeName) && seenJavaTypes.Add (javaTypeName)) { | ||
| javaTypes.Add (javaTypeName); | ||
| } | ||
| } | ||
| return javaTypes; | ||
| } | ||
|
|
||
| HashSet<string> LoadRetainedTypeKeysFromDgml () | ||
| { | ||
| var typeKeys = new HashSet<string> (StringComparer.Ordinal); | ||
| foreach (var dgmlFile in NativeAotDgmlFiles) { | ||
| using var reader = XmlReader.Create (dgmlFile.ItemSpec, new XmlReaderSettings { | ||
| DtdProcessing = DtdProcessing.Prohibit, | ||
| XmlResolver = null, | ||
| }); | ||
|
|
||
| while (reader.Read ()) { | ||
| if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "Node") { | ||
| continue; | ||
| } | ||
|
|
||
| var label = reader.GetAttribute ("Label"); | ||
| if (label.IsNullOrEmpty () || !label.StartsWith (TypeMetadataPrefix, StringComparison.Ordinal)) { | ||
| continue; | ||
| } | ||
|
|
||
| var assemblyStart = TypeMetadataPrefix.Length; | ||
| var assemblyEnd = label.IndexOf (']', assemblyStart); | ||
| if (assemblyEnd < 0 || assemblyEnd == label.Length - 1) { | ||
| continue; | ||
| } | ||
|
|
||
| var assemblyName = label.Substring (assemblyStart, assemblyEnd - assemblyStart); | ||
| var managedTypeName = label.Substring (assemblyEnd + 1); | ||
| typeKeys.Add ($"{managedTypeName}, {assemblyName}"); | ||
| } | ||
| } | ||
|
|
||
| return typeKeys; | ||
| } | ||
| } |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.