From d91b9d5fea8cdf67987db1233cf2eb3825a02a7e Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 17 Nov 2020 14:06:40 +0000 Subject: [PATCH] [Xamarin.Android.Build.Tasks] Add support for Proguard `mapping.txt` file. Fixes #5186 When uploading a package to the Google Play Store users are seeing the following warning. This App Bundle contains Java/Kotlin code, which might be obfuscated. To fix this users need to provide a `mapping.txt` file which contains the Java class mappings from their plain versions to the ones which are obfuscated. By default we do not obfuscate the java code but the warning still shows. To fix this issue we have a new property `$(AndroidProguardMappingFile)` which defaults to `$(OutputPath)mapping.txt`. This file will be produced as part of the build process. In order for this mapping file to be generated the following lines needed to be added to the `proguard_xamarin.cfg` file. -keepattributes SourceFile -keepattributes LineNumberTable --- .../guides/building-apps/build-properties.md | 11 +++++++++++ Documentation/release-notes/5304.md | 9 +++++++++ .../Resources/proguard_xamarin.cfg | 4 ++++ .../Tasks/Proguard.cs | 18 +++++++++++------- src/Xamarin.Android.Build.Tasks/Tasks/R8.cs | 7 ++++++- .../PackagingTest.cs | 15 +++++++++++++++ .../Xamarin.Android.Common.targets | 1 + .../Xamarin.Android.D8.targets | 2 ++ .../Xamarin.Android.DX.targets | 6 ++++-- 9 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 Documentation/release-notes/5304.md diff --git a/Documentation/guides/building-apps/build-properties.md b/Documentation/guides/building-apps/build-properties.md index 31321ae15c6..031d5002750 100644 --- a/Documentation/guides/building-apps/build-properties.md +++ b/Documentation/guides/building-apps/build-properties.md @@ -806,6 +806,17 @@ with build environments that have FIPS compliance enforced. Added in Xamarin.Android 10.1. +## AndroidProguardMappingFile + +Specifies the `-printmapping` proguard rule for `r8`. This will +mean the `mapping.txt` file will be produced in the `$(OutputPath)` +folder. This file can then be used when uploading packages to the +Google Play Store. + +Default value is `$(OutputPath)mapping.txt` + +Added in Xamarin.Android 11.2 + ## AndroidR8IgnoreWarnings Specifies diff --git a/Documentation/release-notes/5304.md b/Documentation/release-notes/5304.md new file mode 100644 index 00000000000..c646302b1a4 --- /dev/null +++ b/Documentation/release-notes/5304.md @@ -0,0 +1,9 @@ +### Build and deployment performance + + * [GitHub PR 5304](https://github.com/xamarin/xamarin-android/pull/5304): + Add support for producing a proguard `mapping.txt` file to the + build system. This file can be used by users to remove this warning + + "This App Bundle contains Java/Kotlin code, which might be obfuscated." + + when uploading packages to the Google Play Store. \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Resources/proguard_xamarin.cfg b/src/Xamarin.Android.Build.Tasks/Resources/proguard_xamarin.cfg index 914ef686ac2..d74e057069a 100644 --- a/src/Xamarin.Android.Build.Tasks/Resources/proguard_xamarin.cfg +++ b/src/Xamarin.Android.Build.Tasks/Resources/proguard_xamarin.cfg @@ -2,6 +2,10 @@ -dontobfuscate +# required for publishing proguard mapping file +-keepattributes SourceFile +-keepattributes LineNumberTable + -keep class android.support.multidex.MultiDexApplication { (); } -keep class com.xamarin.java_interop.** { *; (); } -keep class mono.MonoRuntimeProvider* { *; (...); } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Proguard.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Proguard.cs index 667bb08dba9..5f1399fd153 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/Proguard.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/Proguard.cs @@ -48,14 +48,15 @@ public class Proguard : AndroidToolTask public string ProguardGeneratedReferenceConfiguration { get; set; } public string ProguardGeneratedApplicationConfiguration { get; set; } public string ProguardCommonXamarinConfiguration { get; set; } + public string ProguardMappingFileOutput { get; set; } [Required] public string [] ProguardConfigurationFiles { get; set; } public ITaskItem[] JavaLibrariesToEmbed { get; set; } - + public ITaskItem[] JavaLibrariesToReference { get; set; } - + public bool UseProguard { get; set; } public string JavaOptions { get; set; } @@ -92,11 +93,11 @@ protected override string GenerateCommandLineCommands () // Add the JavaOptions if they are not null // These could be any of the additional options if (!string.IsNullOrEmpty (JavaOptions)) { - cmd.AppendSwitch (JavaOptions); + cmd.AppendSwitch (JavaOptions); } // Add the specific -XmxN to override the default heap size for the JVM - // N can be in the form of Nm or NGB (e.g 100m or 1GB ) + // N can be in the form of Nm or NGB (e.g 100m or 1GB ) cmd.AppendSwitchIfNotNull ("-Xmx", JavaMaximumHeapSize); cmd.AppendSwitchIfNotNull ("-jar ", Path.Combine (ProguardJarPath)); @@ -118,9 +119,12 @@ protected override string GenerateCommandLineCommands () } if (!string.IsNullOrWhiteSpace (ProguardCommonXamarinConfiguration)) - using (var xamcfg = File.Create (ProguardCommonXamarinConfiguration)) - GetType ().Assembly.GetManifestResourceStream ("proguard_xamarin.cfg").CopyTo (xamcfg); - + using (var xamcfg = File.CreateText (ProguardCommonXamarinConfiguration)) { + GetType ().Assembly.GetManifestResourceStream ("proguard_xamarin.cfg").CopyTo (xamcfg.BaseStream); + if (!string.IsNullOrEmpty (ProguardMappingFileOutput)) + xamcfg.WriteLine ($"-printmapping {Path.GetFullPath (ProguardMappingFileOutput)}"); + } + var enclosingChar = OS.IsWindows ? "\"" : string.Empty; foreach (var file in ProguardConfigurationFiles) { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/R8.cs b/src/Xamarin.Android.Build.Tasks/Tasks/R8.cs index 244eba6fec6..02cee3f22e9 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/R8.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/R8.cs @@ -29,6 +29,7 @@ public class R8 : D8 public string ProguardGeneratedReferenceConfiguration { get; set; } public string ProguardGeneratedApplicationConfiguration { get; set; } public string ProguardCommonXamarinConfiguration { get; set; } + public string ProguardMappingFileOutput { get; set; } public string [] ProguardConfigurationFiles { get; set; } protected override string MainClass => "com.android.tools.r8.R8"; @@ -99,6 +100,8 @@ protected override CommandLineBuilder GetCommandLineBuilder () if (IgnoreWarnings) { xamcfg.WriteLine ("-ignorewarnings"); } + if (!string.IsNullOrEmpty (ProguardMappingFileOutput)) + xamcfg.WriteLine ($"-printmapping {Path.GetFullPath (ProguardMappingFileOutput)}"); } } } else { @@ -115,6 +118,8 @@ protected override CommandLineBuilder GetCommandLineBuilder () if (IgnoreWarnings) { lines.Add ("-ignorewarnings"); } + if (!string.IsNullOrEmpty (ProguardMappingFileOutput)) + lines.Add ($"-printmapping {Path.GetFullPath (ProguardMappingFileOutput)}"); File.WriteAllLines (temp, lines); tempFiles.Add (temp); cmd.AppendSwitchIfNotNull ("--pg-conf ", temp); @@ -131,5 +136,5 @@ protected override CommandLineBuilder GetCommandLineBuilder () return cmd; } } - + } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs index fedebe477d5..5a5486c38cd 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs @@ -48,6 +48,21 @@ public void CheckManagedSymbolsArchive (bool isRelease, bool monoSymbolArchive, } } + [Test] + public void CheckProguardMappingFileExists () + { + var proj = new XamarinAndroidApplicationProject { + IsRelease = true, + }; + proj.SetProperty (proj.ReleaseProperties, KnownProperties.AndroidDexTool, "d8"); + proj.SetProperty (proj.ReleaseProperties, KnownProperties.AndroidLinkTool, "r8"); + using (var b = CreateApkBuilder ()) { + Assert.IsTrue (b.Build (proj), "build should have succeeded."); + string mappingFile = Path.Combine (Root, b.ProjectDirectory, proj.OutputPath, "mapping.txt"); + FileAssert.Exists (mappingFile, $"'{mappingFile}' should have been generated."); + } + } + [Test] public void CheckIncludedAssemblies () { diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index edbdc49bdd0..40a63abdab0 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -275,6 +275,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. proguard r8 True + $(OutputPath)mapping.txt True False True diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.D8.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.D8.targets index bf0d3310dc3..f23db33f84a 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.D8.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.D8.targets @@ -67,6 +67,7 @@ Copyright (C) 2018 Xamarin. All rights reserved. ProguardCommonXamarinConfiguration="$(IntermediateOutputPath)proguard\proguard_xamarin.cfg" ProguardGeneratedReferenceConfiguration="$(_ProguardProjectConfiguration)" ProguardGeneratedApplicationConfiguration="$(IntermediateOutputPath)proguard\proguard_project_primary.cfg" + ProguardMappingFileOutput="$(AndroidProguardMappingFile)" ProguardConfigurationFiles="@(_ProguardConfiguration)" EnableShrinking="$(_R8EnableShrinking)" EnableMultiDex="$(AndroidEnableMultiDex)" @@ -96,6 +97,7 @@ Copyright (C) 2018 Xamarin. All rights reserved. + diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DX.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DX.targets index 71195956a97..0ff87f32115 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DX.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DX.targets @@ -26,7 +26,7 @@ Copyright (C) 2018 Xamarin. All rights reserved. <_JarsToProguard Include="@(_JavaLibrariesToCompile)" /> - + - +