From 94abc6393a141db76a9b00c1da6ced516faae280 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 30 Jan 2024 09:05:07 -0500 Subject: [PATCH] Properly parse acw-map.txt `acw-map.txt` contains mappings from .NET types to Java types, and implicitly vice-versa; see (TODO commit). *Normally* it contains three entries: 1. The fully-qualified .NET type name 2. The .NET type name, no assembly 3. (2) with a lowercased namespace name. For example: Mono.Android_Test.Library.CustomTextView, Mono.Android-Test.Library.NET;crc6456ab8145c81c4100.CustomTextView Mono.Android_Test.Library.CustomTextView;crc6456ab8145c81c4100.CustomTextView mono.android_test.library.CustomTextView;crc6456ab8145c81c4100.CustomTextView However, when XA4214 is emitted, there is a "collision" on the .NET side (but *not* the Java side); (2) and (3) are *ambiguous*, so one .NET type is arbitrarily chosen. The first line is still possible, because of assembly qualification. Enter ``Java.InteropTests.GenericHolder`1``: this type is present in *both* `Java.Interop-Tests.dll` *and* `Mono.Android-Tests.dll`. Before xamarin/java.interop#1181, this was "fine" because the `GenericHolder` within `Java.Interop-Tests.dll` did not participate in typemap generation. Now it does, resulting in the XA4214. XA4214 *also* means that instead of three lines, it's *one* line: Java.InteropTests.GenericHolder`1, Mono.Android.NET-Tests;crc641855b07eca6dcc03.GenericHolder_1 Enter ``, which parses `acw-map.txt` to create a `proguard_project_primary.cfg` file. `` did it's *own* parsing of `acw-map.txt`, parsing only *one of every three lines*, on the assumption that *all* entries took three lines. This breaks in the presence of XA4214, because some entries only take one line, not three lines. Update `` to instead use `MonoAndroidHelper.LoadMapFile()`, which reads all lines within `acw-map.txt`. This should result in a `proguard_project_primary.cfg` file which properly contains a `-keep` entry for `crc641855b07eca6dcc03.GenericHolder_1`. --- src/Xamarin.Android.Build.Tasks/Tasks/R8.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/R8.cs b/src/Xamarin.Android.Build.Tasks/Tasks/R8.cs index 81d65a2c218..d9cafeb4e3d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/R8.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/R8.cs @@ -1,3 +1,4 @@ +using System; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using System.Collections.Generic; @@ -82,16 +83,15 @@ protected override CommandLineBuilder GetCommandLineBuilder () if (EnableShrinking) { if (!string.IsNullOrEmpty (AcwMapFile)) { - var acwLines = File.ReadAllLines (AcwMapFile); + var acwMap = MonoAndroidHelper.LoadMapFile (BuildEngine4, Path.GetFullPath (AcwMapFile), StringComparer.OrdinalIgnoreCase); + var javaTypes = new List (acwMap.Values.Count); + foreach (var v in acwMap.Values) { + javaTypes.Add (v); + } + javaTypes.Sort (StringComparer.Ordinal); using (var appcfg = File.CreateText (ProguardGeneratedApplicationConfiguration)) { - for (int i = 0; i + 2 < acwLines.Length; i += 3) { - try { - var line = acwLines [i + 2]; - var java = line.Substring (line.IndexOf (';') + 1); - appcfg.WriteLine ("-keep class " + java + " { *; }"); - } catch { - // skip invalid lines - } + foreach (var java in javaTypes) { + appcfg.WriteLine ($"-keep class {java} {{ *; }}"); } } }