Skip to content
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

[Xamarin.Android.Build.Tasks] Feature for excluding Kotlin-related files from apps #7356

Merged
merged 11 commits into from
Sep 13, 2022
20 changes: 20 additions & 0 deletions Documentation/guides/building-apps/build-items.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,26 @@ used to specify the ABI that the library targets. Thus, if you add
</ItemGroup>
```

## AndroidPackagingOptionsExclude

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

```
<ItemGroup>
<AndroidPackagingOptionsExclude Include="DebugProbesKt.bin" />
<AndroidPackagingOptionsExclude Include="$([MSBuild]::Escape('*.kotlin_*')" />
</ItemGroup>
```
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: `*`, `?` and `.` will be replaced in the `BuildApk` task with the
appropriate RegEx expressions.

Added in Xamarin.Android 13.0.
dellis1972 marked this conversation as resolved.
Show resolved Hide resolved

## AndroidResource

All files with an *AndroidResource* build action are compiled into
Expand Down
32 changes: 32 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down Expand Up @@ -122,6 +124,8 @@ protected virtual void FixupArchive (ZipArchiveEx zip) { }

List<string> existingEntries = new List<string> ();

List<Regex> excludePatterns = new List<Regex> ();

void ExecuteWithAbi (string [] supportedAbis, string apkInputPath, string apkOutputPath, bool debug, bool compress, IDictionary<string, CompressedAssemblyInfo> compressedAssembliesInfo, string assemblyStoreApkName)
{
ArchiveFileList files = new ArchiveFileList ();
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -293,6 +304,10 @@ public override bool RunTask ()

existingEntries.Clear ();

foreach (var pattern in ExcludeFiles ?? Array.Empty<string> ()) {
excludePatterns.Add (FileGlobToRegEx (pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled));
}

bool debug = _Debug;
bool compress = !debug && EnableCompression;
IDictionary<string, CompressedAssemblyInfo> compressedAssembliesInfo = null;
Expand Down Expand Up @@ -326,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<string, CompressedAssemblyInfo> compressedAssembliesInfo, string assemblyStoreApkName)
{
string sourcePath;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 ()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
12 changes: 12 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>

<ItemGroup>
<AndroidPackagingOptionsExclude Include="DebugProbesKt.bin" />
<AndroidPackagingOptionsExclude Include="$([MSBuild]::Escape('*.kotlin_*'))" />
</ItemGroup>

<!--
*******************************************
Imports
Expand Down Expand Up @@ -2033,6 +2038,11 @@ because xbuild doesn't support framework reference assemblies.
Outputs="$(_BuildApkEmbedOutputs)"
Condition="'$(EmbedAssembliesIntoApk)' == 'True'">
<!-- Put the assemblies and native libraries in the apk -->
<!--
NOTE: Adding Arguments to BuildApk or BuildBaseAppBundle
also need to have the args added to Xamarin.Android.Common.Debugging.targets
in monodroid.
-->
<BuildApk
Condition=" '$(AndroidPackageFormat)' != 'aab' "
AndroidNdkDirectory="$(_AndroidNdkDirectory)"
Expand Down Expand Up @@ -2063,6 +2073,7 @@ because xbuild doesn't support framework reference assemblies.
IncludeWrapSh="$(AndroidIncludeWrapSh)"
CheckedBuild="$(_AndroidCheckedBuild)"
RuntimeConfigBinFilePath="$(_BinaryRuntimeConfigPath)"
ExcludeFiles="@(AndroidPackagingOptionsExclude)"
UseAssemblyStore="$(AndroidUseAssemblyStore)">
<Output TaskParameter="OutputFiles" ItemName="ApkFiles" />
</BuildApk>
Expand Down Expand Up @@ -2096,6 +2107,7 @@ because xbuild doesn't support framework reference assemblies.
IncludeWrapSh="$(AndroidIncludeWrapSh)"
CheckedBuild="$(_AndroidCheckedBuild)"
RuntimeConfigBinFilePath="$(_BinaryRuntimeConfigPath)"
ExcludeFiles="@(AndroidPackagingOptionsExclude)"
UseAssemblyStore="$(AndroidUseAssemblyStore)">
<Output TaskParameter="OutputFiles" ItemName="BaseZipFile" />
</BuildBaseAppBundle>
Expand Down