From 2f498242c9f6e59c8de347c143a65c84a89b577f Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Wed, 7 Sep 2022 15:34:50 +0100 Subject: [PATCH 01/11] [Xamarin.Android.Build.Tasks] Feature for excluding Kotlin-related files from apps Fixes #6920 Add a new ItemGroup `AndroidPackagingOptionsExclude` to the common targets. This ItemGroup will contain a set of RegEx compatible patterns which will be used to exlcude certain files from the final apk/aab. The patterns will need to be Url encoded so that MSBuild does not try to interpret them. The main purpose of this is to allow us to exclude certain Kotlin meta-data files from the final package. These files seem to be excluded by gradle so we should do the same. --- .../guides/building-apps/build-items.md | 20 +++++++++++++++++++ .../Tasks/BuildApk.cs | 15 ++++++++++++++ .../PackagingTest.cs | 20 +++++++++++++++++++ .../Android/KnownPackages.cs | 4 ++++ .../Xamarin.Android.Common.targets | 7 +++++++ 5 files changed, 66 insertions(+) diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index 1191532ceb2..4b84d93cce2 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -204,6 +204,26 @@ used to specify the ABI that the library targets. Thus, if you add ``` +## AndroidPackagingOptionsExclude + +A set if RegEx compatible items which will allow for items to be +excluded from the final package. The default values are as follows + +``` + + + + +``` + +NOTE: The Items MUST use URL encoding for characters like `*`. This +is so MSBuild does not try to interpret them as file wildcards. + +NOTE: `*` will be replaced in the `BuildApk` task with the RegEx +`(.)` to match all characters. + +Added in Xamarin.Android XX.X. + ## AndroidResource All files with an *AndroidResource* build action are compiled into diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs b/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs index acb9ab380d8..06b5cad5a83 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs @@ -74,6 +74,8 @@ public class BuildApk : AndroidTask public string[] DoNotPackageJavaLibraries { get; set; } + public string [] ExcludeFiles { get; set; } + public string Debug { get; set; } public string AndroidSequencePointsMode { get; set; } @@ -122,6 +124,8 @@ protected virtual void FixupArchive (ZipArchiveEx zip) { } List existingEntries = new List (); + List excludePatterns = new List (); + void ExecuteWithAbi (string [] supportedAbis, string apkInputPath, string apkOutputPath, bool debug, bool compress, IDictionary compressedAssembliesInfo, string assemblyStoreApkName) { ArchiveFileList files = new ArchiveFileList (); @@ -248,6 +252,13 @@ void ExecuteWithAbi (string [] supportedAbis, string apkInputPath, string apkOut Log.LogDebugMessage ($"Skipping {path} as the archive file is up to date."); continue; } + // check for ignored items + foreach (var pattern in excludePatterns) { + if(pattern.IsMatch (path)) { + Log.LogDebugMessage ($"Ignoring jar entry '{name}' from '{Path.GetFileName (jarFile)}'. Filename matched the exclude pattern '{pattern}'."); + continue; + } + } if (string.Compare (Path.GetFileName (name), "AndroidManifest.xml", StringComparison.OrdinalIgnoreCase) == 0) { Log.LogDebugMessage ("Ignoring jar entry {0} from {1}: the same file already exists in the apk", name, Path.GetFileName (jarFile)); continue; @@ -293,6 +304,10 @@ public override bool RunTask () existingEntries.Clear (); + foreach (var pattern in ExcludeFiles) { + excludePatterns.Add (new Regex (pattern.Replace ("*", "(.)"), RegexOptions.IgnoreCase | RegexOptions.Compiled)); + } + bool debug = _Debug; bool compress = !debug && EnableCompression; IDictionary compressedAssembliesInfo = null; 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 6a4b9917b44..3e480fd8d6c 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 @@ -915,6 +915,26 @@ public class Test } } + [Test] + public void CheckExcludedFilesAreMissing () + { + + var proj = new XamarinAndroidApplicationProject () { + IsRelease = true, + }; + proj.PackageReferences.Add (KnownPackages.Xamarin_Kotlin_StdLib_Common); + using (var b = CreateApkBuilder ()) { + Assert.IsTrue (b.Build (proj), "Build should have succeeded."); + var apk = Path.Combine (Root, b.ProjectDirectory, + proj.OutputPath, $"{proj.PackageName}-Signed.apk"); + string expected = $"Ignoring jar entry 'kotlin/Error.kotlin_metadata'"; + Assert.IsTrue (b.LastBuildOutput.ContainsText (expected), $"Error.kotlin_metadata should have been ignored."); + using (var zip = ZipHelper.OpenZip (apk)) { + Assert.IsFalse (zip.ContainsEntry ("Error.kotlin_metadata"), "Error.kotlin_metadata should have been ignored."); + } + } + } + [Test] public void ExtractNativeLibsTrue () { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs index 3757f53f860..3cac7b400be 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs @@ -499,6 +499,10 @@ public static class KnownPackages Id = "Xamarin.GooglePlayServices.Maps", Version = "117.0.1.2", }; + public static Package Xamarin_Kotlin_StdLib_Common = new Package { + Id = "Xamarin.Kotlin.Stdlib.Common", + Version = "1.6.20.1" + }; public static Package Acr_UserDialogs = new Package { Id = "Acr.UserDialogs", Version = "6.5.1", diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 686fb70c67d..b0e2e33ebad 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -351,6 +351,11 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. + + + + + + Date: Thu, 8 Sep 2022 14:12:55 +0100 Subject: [PATCH 05/11] Add some comments --- src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 0db7a59cbd8..5abab6d0d89 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -2040,7 +2040,8 @@ because xbuild doesn't support framework reference assemblies. Date: Fri, 9 Sep 2022 11:39:12 +0100 Subject: [PATCH 06/11] Fix up file glob stuff and docs --- .../guides/building-apps/build-items.md | 12 ++++++------ .../Tasks/BuildApk.cs | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index 4b84d93cce2..a42463efd63 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -212,15 +212,15 @@ excluded from the final package. The default values are as follows ``` - + ``` +Items can use file blob characters for wildcards such as `*` and `?`. +However these Items MUST use URL encoding or '$([MSBuild]::Escape(''))'. +This is so MSBuild does not try to interpret them as actual file wildcards. -NOTE: The Items MUST use URL encoding for characters like `*`. This -is so MSBuild does not try to interpret them as file wildcards. - -NOTE: `*` will be replaced in the `BuildApk` task with the RegEx -`(.)` to match all characters. +NOTE: `*`, `?` and `.` will be replaced in the `BuildApk` task with the +appropriate RegEx expressions. Added in Xamarin.Android XX.X. diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs b/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs index 9ee44246d2b..8e7100f7ed8 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs @@ -305,7 +305,7 @@ public override bool RunTask () existingEntries.Clear (); foreach (var pattern in ExcludeFiles ?? Array.Empty ()) { - excludePatterns.Add (new Regex (pattern.Replace ("*", "(.)"), RegexOptions.IgnoreCase | RegexOptions.Compiled)); + excludePatterns.Add (FileGlobToRegEx (pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled)); } bool debug = _Debug; @@ -341,6 +341,23 @@ public override bool RunTask () return !Log.HasLoggedErrors; } + static Regex FileGlobToRegEx (string fileGlob, RegexOptions options) { + StringBuilder sb = new StringBuilder (); + foreach (char c in fileGlob) { + switch (c) { + case '*': sb.Append (".*"); + break; + case '?': sb.Append ("."); + break; + case '.': sb.Append (@"\."); + break; + default: sb.Append (c); + break; + } + } + return new Regex (sb.ToString (), options); + } + void AddAssemblies (ZipArchiveEx apk, bool debug, bool compress, IDictionary compressedAssembliesInfo, string assemblyStoreApkName) { string sourcePath; From 8dfa07c9dc1fd280ab3a401908b29514a0961c80 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Fri, 9 Sep 2022 11:47:14 +0100 Subject: [PATCH 07/11] Fix wording --- Documentation/guides/building-apps/build-items.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index a42463efd63..d4b5a8dfe48 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -206,7 +206,7 @@ used to specify the ABI that the library targets. Thus, if you add ## AndroidPackagingOptionsExclude -A set if RegEx compatible items which will allow for items to be +A set of file glob compatible items which will allow for items to be excluded from the final package. The default values are as follows ``` From 0901080725b4a5a52ba966b9b18297f12a0758ab Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Fri, 9 Sep 2022 11:51:55 +0100 Subject: [PATCH 08/11] Fix wording --- Documentation/guides/building-apps/build-items.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index d4b5a8dfe48..17db1fdd9fc 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -212,7 +212,7 @@ excluded from the final package. The default values are as follows ``` - + ``` Items can use file blob characters for wildcards such as `*` and `?`. From 39f634244d1df8db2a41e0f71de89f6b8ab721d5 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Fri, 9 Sep 2022 13:14:20 +0100 Subject: [PATCH 09/11] Updated version --- Documentation/guides/building-apps/build-items.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index 17db1fdd9fc..729c803efe0 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -222,7 +222,7 @@ This is so MSBuild does not try to interpret them as actual file wildcards. NOTE: `*`, `?` and `.` will be replaced in the `BuildApk` task with the appropriate RegEx expressions. -Added in Xamarin.Android XX.X. +Added in Xamarin.Android 13.0. ## AndroidResource From 3ec2e87e1b5248114dadc4e2ef1c7d1c04f58c45 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Sat, 10 Sep 2022 23:19:04 +0100 Subject: [PATCH 10/11] Update Documentation/guides/building-apps/build-items.md Co-authored-by: Jonathan Peppers --- Documentation/guides/building-apps/build-items.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index 729c803efe0..305d34ca957 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -222,7 +222,7 @@ This is so MSBuild does not try to interpret them as actual file wildcards. NOTE: `*`, `?` and `.` will be replaced in the `BuildApk` task with the appropriate RegEx expressions. -Added in Xamarin.Android 13.0. +Added in Xamarin.Android 13.1 and .NET 7. ## AndroidResource From 86d46e09f2539cd82cdc9f26e06fe4e8926e289f Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 13 Sep 2022 13:09:39 -0400 Subject: [PATCH 11/11] Fix indentation --- src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs b/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs index 8e7100f7ed8..28cca622f9b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs @@ -341,7 +341,8 @@ public override bool RunTask () return !Log.HasLoggedErrors; } - static Regex FileGlobToRegEx (string fileGlob, RegexOptions options) { + static Regex FileGlobToRegEx (string fileGlob, RegexOptions options) + { StringBuilder sb = new StringBuilder (); foreach (char c in fileGlob) { switch (c) {