|
1 | 1 | using System;
|
| 2 | +using System.Collections.Generic; |
2 | 3 | using System.Buffers;
|
3 | 4 | using System.IO;
|
4 | 5 |
|
5 | 6 | using K4os.Compression.LZ4;
|
| 7 | +using Microsoft.Android.Build.Tasks; |
| 8 | +using Microsoft.Build.Framework; |
| 9 | +using Microsoft.Build.Utilities; |
| 10 | +using Xamarin.Android.Tasks; |
| 11 | +using Xamarin.Android.Tools; |
6 | 12 |
|
7 | 13 | namespace Xamarin.Android.Tasks
|
8 | 14 | {
|
@@ -49,7 +55,7 @@ public void SetData (string sourcePath, uint descriptorIndex)
|
49 | 55 |
|
50 | 56 | static readonly ArrayPool<byte> bytePool = ArrayPool<byte>.Shared;
|
51 | 57 |
|
52 |
| - public static CompressionResult Compress (AssemblyData data, string outputDirectory) |
| 58 | + static CompressionResult Compress (AssemblyData data, string outputDirectory) |
53 | 59 | {
|
54 | 60 | if (data == null)
|
55 | 61 | throw new ArgumentNullException (nameof (data));
|
@@ -104,5 +110,57 @@ public static CompressionResult Compress (AssemblyData data, string outputDirect
|
104 | 110 |
|
105 | 111 | return CompressionResult.Success;
|
106 | 112 | }
|
| 113 | + |
| 114 | + public static string Compress ( |
| 115 | + TaskLoggingHelper log, |
| 116 | + ITaskItem assembly, |
| 117 | + IDictionary<AndroidTargetArch, Dictionary<string, CompressedAssemblyInfo>> compressedAssembliesInfo, |
| 118 | + string compressedOutputDir) |
| 119 | + { |
| 120 | + if (bool.TryParse (assembly.GetMetadata ("AndroidSkipCompression"), out bool value) && value) { |
| 121 | + log.LogDebugMessage ($"Skipping compression of {assembly.ItemSpec} due to 'AndroidSkipCompression' == 'true' "); |
| 122 | + return assembly.ItemSpec; |
| 123 | + } |
| 124 | + |
| 125 | + string key = CompressedAssemblyInfo.GetDictionaryKey (assembly); |
| 126 | + AndroidTargetArch arch = MonoAndroidHelper.GetTargetArch (assembly); |
| 127 | + if (!compressedAssembliesInfo.TryGetValue (arch, out Dictionary<string, CompressedAssemblyInfo> assembliesInfo)) { |
| 128 | + throw new InvalidOperationException ($"Internal error: compression assembly info for architecture {arch} not available"); |
| 129 | + } |
| 130 | + |
| 131 | + if (!assembliesInfo.TryGetValue (key, out CompressedAssemblyInfo info) || info == null) { |
| 132 | + log.LogDebugMessage ($"Assembly missing from {nameof (CompressedAssemblyInfo)}: {key}"); |
| 133 | + return assembly.ItemSpec; |
| 134 | + } |
| 135 | + |
| 136 | + AssemblyData compressedAssembly = new AssemblyData (assembly.ItemSpec, info.DescriptorIndex); |
| 137 | + string assemblyOutputDir; |
| 138 | + string subDirectory = assembly.GetMetadata ("DestinationSubDirectory"); |
| 139 | + string abi = MonoAndroidHelper.GetAssemblyAbi (assembly); |
| 140 | + if (!String.IsNullOrEmpty (subDirectory) && !(subDirectory.EndsWith ($"{abi}/", StringComparison.Ordinal) || subDirectory.EndsWith ($"{abi}\\", StringComparison.Ordinal))) { |
| 141 | + assemblyOutputDir = Path.Combine (compressedOutputDir, abi, subDirectory); |
| 142 | + } else { |
| 143 | + assemblyOutputDir = Path.Combine (compressedOutputDir, abi); |
| 144 | + } |
| 145 | + |
| 146 | + CompressionResult result = AssemblyCompression.Compress (compressedAssembly, assemblyOutputDir); |
| 147 | + if (result != CompressionResult.Success) { |
| 148 | + switch (result) { |
| 149 | + case AssemblyCompression.CompressionResult.EncodingFailed: |
| 150 | + log.LogMessage ($"Failed to compress {assembly.ItemSpec}"); |
| 151 | + break; |
| 152 | + |
| 153 | + case AssemblyCompression.CompressionResult.InputTooBig: |
| 154 | + log.LogMessage ($"Input assembly {assembly.ItemSpec} exceeds maximum input size"); |
| 155 | + break; |
| 156 | + |
| 157 | + default: |
| 158 | + log.LogMessage ($"Unknown error compressing {assembly.ItemSpec}"); |
| 159 | + break; |
| 160 | + } |
| 161 | + return assembly.ItemSpec; |
| 162 | + } |
| 163 | + return compressedAssembly.DestinationPath; |
| 164 | + } |
107 | 165 | }
|
108 | 166 | }
|
0 commit comments