Skip to content

Commit

Permalink
Move compression code from BuildApk to utility class (#9383)
Browse files Browse the repository at this point in the history
Context: #9382

To further simplify `BuildApk`, move assembly compression code
to a separate utility class.  This also lets us compress assemblies
from tasks other than `BuildApk`.
  • Loading branch information
grendello authored Oct 14, 2024
1 parent 7bc14b9 commit 6d524ba
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 44 deletions.
44 changes: 1 addition & 43 deletions src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -515,49 +515,7 @@ string CompressAssembly (ITaskItem assembly)
return assembly.ItemSpec;
}

if (bool.TryParse (assembly.GetMetadata ("AndroidSkipCompression"), out bool value) && value) {
Log.LogDebugMessage ($"Skipping compression of {assembly.ItemSpec} due to 'AndroidSkipCompression' == 'true' ");
return assembly.ItemSpec;
}

string key = CompressedAssemblyInfo.GetDictionaryKey (assembly);
AndroidTargetArch arch = MonoAndroidHelper.GetTargetArch (assembly);
if (!compressedAssembliesInfo.TryGetValue (arch, out Dictionary<string, CompressedAssemblyInfo> assembliesInfo)) {
throw new InvalidOperationException ($"Internal error: compression assembly info for architecture {arch} not available");
}

if (!assembliesInfo.TryGetValue (key, out CompressedAssemblyInfo info) || info == null) {
Log.LogDebugMessage ($"Assembly missing from {nameof (CompressedAssemblyInfo)}: {key}");
return assembly.ItemSpec;
}

EnsureCompressedAssemblyData (assembly.ItemSpec, info.DescriptorIndex);
string assemblyOutputDir;
string subDirectory = assembly.GetMetadata ("DestinationSubDirectory");
string abi = MonoAndroidHelper.GetAssemblyAbi (assembly);
if (!String.IsNullOrEmpty (subDirectory)) {
assemblyOutputDir = Path.Combine (compressedOutputDir, abi, subDirectory);
} else {
assemblyOutputDir = Path.Combine (compressedOutputDir, abi);
}
AssemblyCompression.CompressionResult result = AssemblyCompression.Compress (compressedAssembly, assemblyOutputDir);
if (result != AssemblyCompression.CompressionResult.Success) {
switch (result) {
case AssemblyCompression.CompressionResult.EncodingFailed:
Log.LogMessage ($"Failed to compress {assembly.ItemSpec}");
break;

case AssemblyCompression.CompressionResult.InputTooBig:
Log.LogMessage ($"Input assembly {assembly.ItemSpec} exceeds maximum input size");
break;

default:
Log.LogMessage ($"Unknown error compressing {assembly.ItemSpec}");
break;
}
return assembly.ItemSpec;
}
return compressedAssembly.DestinationPath;
return AssemblyCompression.Compress (Log, assembly, compressedAssembliesInfo, compressedOutputDir);
}
}

Expand Down
60 changes: 59 additions & 1 deletion src/Xamarin.Android.Build.Tasks/Utilities/AssemblyCompression.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
using System;
using System.Collections.Generic;
using System.Buffers;
using System.IO;

using K4os.Compression.LZ4;
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xamarin.Android.Tasks;
using Xamarin.Android.Tools;

namespace Xamarin.Android.Tasks
{
Expand Down Expand Up @@ -49,7 +55,7 @@ public void SetData (string sourcePath, uint descriptorIndex)

static readonly ArrayPool<byte> bytePool = ArrayPool<byte>.Shared;

public static CompressionResult Compress (AssemblyData data, string outputDirectory)
static CompressionResult Compress (AssemblyData data, string outputDirectory)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
Expand Down Expand Up @@ -104,5 +110,57 @@ public static CompressionResult Compress (AssemblyData data, string outputDirect

return CompressionResult.Success;
}

public static string Compress (
TaskLoggingHelper log,
ITaskItem assembly,
IDictionary<AndroidTargetArch, Dictionary<string, CompressedAssemblyInfo>> compressedAssembliesInfo,
string compressedOutputDir)
{
if (bool.TryParse (assembly.GetMetadata ("AndroidSkipCompression"), out bool value) && value) {
log.LogDebugMessage ($"Skipping compression of {assembly.ItemSpec} due to 'AndroidSkipCompression' == 'true' ");
return assembly.ItemSpec;
}

string key = CompressedAssemblyInfo.GetDictionaryKey (assembly);
AndroidTargetArch arch = MonoAndroidHelper.GetTargetArch (assembly);
if (!compressedAssembliesInfo.TryGetValue (arch, out Dictionary<string, CompressedAssemblyInfo> assembliesInfo)) {
throw new InvalidOperationException ($"Internal error: compression assembly info for architecture {arch} not available");
}

if (!assembliesInfo.TryGetValue (key, out CompressedAssemblyInfo info) || info == null) {
log.LogDebugMessage ($"Assembly missing from {nameof (CompressedAssemblyInfo)}: {key}");
return assembly.ItemSpec;
}

AssemblyData compressedAssembly = new AssemblyData (assembly.ItemSpec, info.DescriptorIndex);
string assemblyOutputDir;
string subDirectory = assembly.GetMetadata ("DestinationSubDirectory");
string abi = MonoAndroidHelper.GetAssemblyAbi (assembly);
if (!String.IsNullOrEmpty (subDirectory) && !(subDirectory.EndsWith ($"{abi}/", StringComparison.Ordinal) || subDirectory.EndsWith ($"{abi}\\", StringComparison.Ordinal))) {
assemblyOutputDir = Path.Combine (compressedOutputDir, abi, subDirectory);
} else {
assemblyOutputDir = Path.Combine (compressedOutputDir, abi);
}

CompressionResult result = AssemblyCompression.Compress (compressedAssembly, assemblyOutputDir);
if (result != CompressionResult.Success) {
switch (result) {
case AssemblyCompression.CompressionResult.EncodingFailed:
log.LogMessage ($"Failed to compress {assembly.ItemSpec}");
break;

case AssemblyCompression.CompressionResult.InputTooBig:
log.LogMessage ($"Input assembly {assembly.ItemSpec} exceeds maximum input size");
break;

default:
log.LogMessage ($"Unknown error compressing {assembly.ItemSpec}");
break;
}
return assembly.ItemSpec;
}
return compressedAssembly.DestinationPath;
}
}
}

0 comments on commit 6d524ba

Please sign in to comment.