Skip to content

Commit d5ef998

Browse files
authored
[aapt2] Use the aapt2 from build-tools_r$(XABuildToolsVersion)-{os}.zip (#5888)
Context: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1288832 Context: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1287930 Commit c9e2d75 had to revert the version of `aapt2` we were shipping due to issues with older PC's, specifically those with an AMD Phenom II CPU. Commit c9e2d75 simply reverted back to the last known working version. This made us think about if getting `aapt2` from maven was the best idea. We are not 100% sure if the builds on maven even match those being shipped in Google's Android SDK. The idea now is to use the `aapt2` that Google ships with the Android SDK. However, since we will control which version of the Android SDK Build-tools we want to ship, we will *not* be relying on the one from the users Android SDK folder. This will ensure we always ship a known working version of `aapt2` with our product. The Android SDK Build-tools version we use will be the version specified in the `$(XABuildToolsVersion)` MSBuild property within `Configuration.props`, which is currently 30.0.2. If `aapt2` continues to fail on certain customer machines, then we can direct them to download the `aapt2` used in c9e2d75 and override the `$(Aapt2ToolExe)` and `$(Aapt2ToolPath)` MSBuild properties, which is described in `Documentation/release-notes/5888.md`.
1 parent 4201dc1 commit d5ef998

File tree

11 files changed

+172
-27
lines changed

11 files changed

+172
-27
lines changed

Configuration.props

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,11 @@
115115
For some reason, the URL for platform-tools/build-tools 30.0.2 is prefixed with what appears to be a GIT commit hash or some other checksum...
116116
Linux packages don't have any prefix, but this forces us to have *some* mechanism to handle this...
117117
-->
118-
<XABuildToolsPackagePrefix Condition=" '$(HostOS)' == 'Darwin' ">5a6ceea22103d8dec989aefcef309949c0c42f1d.</XABuildToolsPackagePrefix>
119-
<XABuildToolsPackagePrefix Condition=" '$(HostOS)' == 'Windows' ">efbaa277338195608aa4e3dbd43927e97f60218c.</XABuildToolsPackagePrefix>
118+
<XABuildToolsPackagePrefixMacOS>5a6ceea22103d8dec989aefcef309949c0c42f1d.</XABuildToolsPackagePrefixMacOS>
119+
<XABuildToolsPackagePrefixWindows>efbaa277338195608aa4e3dbd43927e97f60218c.</XABuildToolsPackagePrefixWindows>
120+
<XABuildToolsPackagePrefixLinux></XABuildToolsPackagePrefixLinux>
121+
<XABuildToolsPackagePrefix Condition=" '$(HostOS)' == 'Darwin' ">$(XABuildToolsPackagePrefixMacOS)</XABuildToolsPackagePrefix>
122+
<XABuildToolsPackagePrefix Condition=" '$(HostOS)' == 'Windows' ">$(XABuildToolsPackagePrefixWindows)</XABuildToolsPackagePrefix>
120123
<XABuildToolsVersion>30.0.2</XABuildToolsVersion>
121124
<XABuildToolsFolder Condition="'$(XABuildToolsFolder)' == ''">30.0.2</XABuildToolsFolder>
122125
<XAPlatformToolsPackagePrefix Condition=" '$(HostOS)' == 'Darwin' ">b2be9c80582174e645d3736daa0d44d8610b38a8.</XAPlatformToolsPackagePrefix>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#### Application build and deployment
2+
3+
- [GitHub PR #5888](https://github.com/xamarin/xamarin-android/pull/5888):
4+
Use the aapt2 from the Android SDK Build-tools package.
5+
Due to issues with the `aapt2` builds from maven, we are now sourcing
6+
the version of `aapt2` we ship from the SDK build-tools on our build machines.
7+
8+
If you are experiencing endless builds or `aapt2` crashes during a build you
9+
can try using the `aapt2` from maven which was used in previous releases.
10+
11+
1. Download the `aapt2` package:
12+
13+
* Windows users, download: https://dl.google.com/dl/android/maven2/com/android/tools/build/aapt2/4.0.0-6051327/aapt2-4.0.0-6051327-windows.jar
14+
15+
* macOS users, download: https://dl.google.com/dl/android/maven2/com/android/tools/build/aapt2/4.0.0-6051327/aapt2-4.0.0-6051327-osx.jar
16+
17+
2. Extract the `aapt2-*.jar` file into a "well-known" directory; this location will be used in the next step:
18+
19+
* Windows:
20+
21+
cd %USERPROFILE%
22+
mkdir xa-tools
23+
cd xa-tools
24+
jar xf %USERPROFILE%\Downloads\aapt2-4.0.0-6051327-windows.jar
25+
26+
* macOS:
27+
28+
cd
29+
mkdir xa-tools
30+
cd xa-tools
31+
jar xf ~/Downloads/aapt2-4.0.0-6051327-osx.jar
32+
33+
3. In the same directory as your App's `.csproj`, add or update `Directory.Build.props` to contain:
34+
35+
```xml
36+
<Project>
37+
38+
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
39+
<Aapt2ToolPath>$(USERPROFILE)\xa-tools</Aapt2ToolPath>
40+
<Aapt2ToolExe>aapt2.exe</Aapt2ToolExe>
41+
</PropertyGroup>
42+
43+
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT' ">
44+
<Aapt2ToolPath>$(HOME)\xa-tools</Aapt2ToolPath>
45+
<Aapt2ToolExe>aapt2</Aapt2ToolExe>
46+
</PropertyGroup>
47+
48+
</Project>
49+
```

build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/UnzipDirectoryChildren.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Microsoft.Build.Framework;
22
using System.IO;
33
using System.Text;
4+
using System.Collections.Generic;
45
using Xamarin.Tools.Zip;
56
using MTask = Microsoft.Build.Utilities.Task;
67
using TTask = System.Threading.Tasks.Task;
@@ -18,6 +19,8 @@ public class UnzipDirectoryChildren : MTask
1819
[Required]
1920
public ITaskItem DestinationFolder { get; set; }
2021

22+
public ITaskItem[] FilesToExtract { get; set; }
23+
2124
public bool NoSubdirectory { get; set; }
2225

2326
public override bool Execute ()
@@ -42,32 +45,42 @@ public override bool Execute ()
4245
? null
4346
: Encoding.GetEncoding (EntryNameEncoding);
4447

48+
var filesToExtract = new HashSet<string> ();
49+
if (FilesToExtract != null) {
50+
foreach (var file in FilesToExtract) {
51+
filesToExtract.Add (file.ItemSpec);
52+
}
53+
}
54+
4555
var tasks = new TTask [SourceFiles.Length];
4656
for (int i = 0; i < SourceFiles.Length; ++i) {
4757
var sourceFile = SourceFiles [i];
4858
var relativeDestDir = sourceFile.GetMetadata ("DestDir");
4959
var enc = encoding;
5060
var destFolder = DestinationFolder.ItemSpec;
51-
tasks [i] = TTask.Run (() => ExtractFile (sourceFile.ItemSpec, relativeDestDir, destFolder, enc));
61+
tasks [i] = TTask.Run (() => ExtractFile (sourceFile.ItemSpec, relativeDestDir, destFolder, enc, filesToExtract));
5262
}
5363

5464
TTask.WaitAll (tasks);
5565

5666
return !Log.HasLoggedErrors;
5767
}
5868

59-
void ExtractFile (string sourceFile, string relativeDestDir, string destinationFolder, Encoding encoding)
69+
void ExtractFile (string sourceFile, string relativeDestDir, string destinationFolder, Encoding encoding, HashSet<string> filesToExtract)
6070
{
6171
relativeDestDir = relativeDestDir?.Replace ('\\', Path.DirectorySeparatorChar);
6272

6373
using (var zip = ZipArchive.Open (sourceFile, FileMode.Open)) {
6474
foreach (var entry in zip) {
6575
if (!entry.IsDirectory) {
76+
if (filesToExtract.Count > 0 && !filesToExtract.Contains (Path.GetFileName (entry.FullName)))
77+
continue;
6678
var entryPath = entry.NativeFullName;
6779
if (!NoSubdirectory) {
6880
entryPath = entryPath.Substring (entryPath.IndexOf (Path.DirectorySeparatorChar) + 1);
6981
}
7082
var destinationPath = Path.Combine (destinationFolder, relativeDestDir, entryPath);
83+
Log.LogMessage (MessageImportance.Low, $"Extracting {entry.NativeFullName} to {destinationPath}");
7184
entry.Extract (Path.GetDirectoryName (destinationPath), Path.GetFileName (destinationPath));
7285
}
7386
}

build-tools/xaprepare/xaprepare/Application/Context.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,11 @@ public string DebugFileExtension {
344344
/// </summary>
345345
public bool MonoArchiveDownloaded { get; set; }
346346

347+
// <summary>
348+
/// Set by <see cref="Step_Get_Android_BuildTools"/> if the archive has been downloaded and validated.
349+
/// </summary>
350+
public bool BuildToolsArchiveDownloaded { get; set; }
351+
347352
/// <summary>
348353
/// Determines whether or not we are running on a hosted azure pipelines agent.
349354
/// These agents have certain limitations, the most pressing being the amount of available storage.

build-tools/xaprepare/xaprepare/Application/KnownProperties.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ static class KnownProperties
4949
public const string RemapAssemblyRefToolExecutable = "RemapAssemblyRefToolExecutable";
5050
public const string XABuildToolsFolder = "XABuildToolsFolder";
5151
public const string XABuildToolsVersion = "XABuildToolsVersion";
52+
public const string XABuildToolsPackagePrefixMacOS = "XABuildToolsPackagePrefixMacOS";
53+
public const string XABuildToolsPackagePrefixWindows = "XABuildToolsPackagePrefixWindows";
54+
public const string XABuildToolsPackagePrefixLinux = "XABuildToolsPackagePrefixLinux";
5255
public const string XABuildToolsPackagePrefix = "XABuildToolsPackagePrefix";
5356
public const string XABinRelativeInstallPrefix = "XABinRelativeInstallPrefix";
5457
public const string XAInstallPrefix = "XAInstallPrefix";

build-tools/xaprepare/xaprepare/Application/Properties.Defaults.cs.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ namespace Xamarin.Android.Prepare
5353
properties.Add (KnownProperties.RemapAssemblyRefToolExecutable, StripQuotes (@"@RemapAssemblyRefToolExecutable@"));
5454
properties.Add (KnownProperties.XABuildToolsFolder, StripQuotes (@"@XABuildToolsFolder@"));
5555
properties.Add (KnownProperties.XABuildToolsVersion, StripQuotes ("@XABuildToolsVersion@"));
56+
properties.Add (KnownProperties.XABuildToolsPackagePrefixMacOS, StripQuotes ("@XABuildToolsPackagePrefixMacOS@"));
57+
properties.Add (KnownProperties.XABuildToolsPackagePrefixWindows, StripQuotes ("@XABuildToolsPackagePrefixWindows@"));
58+
properties.Add (KnownProperties.XABuildToolsPackagePrefixLinux, StripQuotes ("@XABuildToolsPackagePrefixLinux@"));
5659
properties.Add (KnownProperties.XABuildToolsPackagePrefix, StripQuotes ("@XABuildToolsPackagePrefix@"));
5760
properties.Add (KnownProperties.XABinRelativeInstallPrefix, StripQuotes (@"@XABinRelativeInstallPrefix@"));
5861
properties.Add (KnownProperties.XAInstallPrefix, StripQuotes (@"@XAInstallPrefix@"));

build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ public static partial class Paths
394394
public static string WindowsBinutilsInstallDir => GetCachedPath (ref windowsBinutilsInstallDir, () => Path.Combine (InstallMSBuildDir, "ndk"));
395395
public static string HostBinutilsInstallDir => GetCachedPath (ref hostBinutilsInstallDir, () => Path.Combine (InstallMSBuildDir, ctx.Properties.GetRequiredValue (KnownProperties.HostOS), "ndk"));
396396
public static string BinutilsCacheDir => ctx.Properties.GetRequiredValue (KnownProperties.AndroidToolchainCacheDirectory);
397+
public static string AndroidBuildToolsCacheDir => ctx.Properties.GetRequiredValue (KnownProperties.AndroidToolchainCacheDirectory);
397398

398399
// not really configurables, merely convenience aliases for more frequently used paths that come from properties
399400
public static string XAInstallPrefix => ctx.Properties.GetRequiredValue (KnownProperties.XAInstallPrefix);

build-tools/xaprepare/xaprepare/Scenarios/Scenario_Standard.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ protected override void AddSteps (Context context)
3636
// directory where the NDK binutils are installed
3737
Steps.Add (new Step_InstallGNUBinutils ());
3838
Steps.Add (new Step_GenerateCGManifest ());
39+
Steps.Add (new Step_Get_Android_BuildTools ());
3940

4041
AddRequiredOSSpecificSteps (false);
4142
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Threading.Tasks;
5+
using System.Net;
6+
7+
namespace Xamarin.Android.Prepare
8+
{
9+
partial class Step_Get_Android_BuildTools : StepWithDownloadProgress
10+
{
11+
List<(string package, string prefix)> packages = new List<(string package, string prefix)>();
12+
13+
public Step_Get_Android_BuildTools ()
14+
: base ("Downloading build-tools archive")
15+
{
16+
string XABuildToolsVersion = Context.Instance.Properties [KnownProperties.XABuildToolsVersion];
17+
string XABuildToolsPackagePrefixMacOS = Context.Instance.Properties [KnownProperties.XABuildToolsPackagePrefixMacOS] ?? string.Empty;
18+
string XABuildToolsPackagePrefixWindows = Context.Instance.Properties [KnownProperties.XABuildToolsPackagePrefixWindows] ?? string.Empty;
19+
string XABuildToolsPackagePrefixLinux = Context.Instance.Properties [KnownProperties.XABuildToolsPackagePrefixLinux] ?? string.Empty;
20+
21+
packages.Add ((package: $"build-tools_r{XABuildToolsVersion}-macosx.zip", prefix: XABuildToolsPackagePrefixMacOS));
22+
packages.Add ((package: $"build-tools_r{XABuildToolsVersion}-windows.zip", prefix: XABuildToolsPackagePrefixWindows));
23+
packages.Add ((package: $"build-tools_r{XABuildToolsVersion}-linux.zip", prefix: XABuildToolsPackagePrefixLinux));
24+
}
25+
26+
protected override async Task<bool> Execute (Context context)
27+
{
28+
bool success = true;
29+
foreach (var package in packages) {
30+
success &= await DownloadBuildToolsPackage (context, package.prefix + package.package, package.package);
31+
if (!success) {
32+
Log.InfoLine ($"build-tools package '{package.package}' not present");
33+
return false;
34+
}
35+
}
36+
37+
context.BuildToolsArchiveDownloaded = success;
38+
return true;
39+
}
40+
41+
async Task<bool> DownloadBuildToolsPackage (Context context, string packageName, string localPackageName)
42+
{
43+
string localArchivePath = Path.Combine (Configurables.Paths.AndroidBuildToolsCacheDir, localPackageName);
44+
Uri url = new Uri (AndroidToolchain.AndroidUri, packageName);
45+
46+
if (Utilities.FileExists (localArchivePath)) {
47+
Log.StatusLine ($"build-tools already downloaded ({localArchivePath})");
48+
return true;
49+
}
50+
51+
Log.StatusLine ($"Downloading {packageName} from ", url.ToString (), tailColor: ConsoleColor.White);
52+
(bool success, ulong size, HttpStatusCode status) = await Utilities.GetDownloadSizeWithStatus (url);
53+
if (!success) {
54+
if (status == HttpStatusCode.NotFound)
55+
Log.ErrorLine ("build-tools URL not found");
56+
else
57+
Log.ErrorLine ("Failed to obtain build-tools size. HTTP status code: {status} ({(int)status})");
58+
return false;
59+
}
60+
DownloadStatus downloadStatus = Utilities.SetupDownloadStatus (context, size, context.InteractiveSession);
61+
Log.StatusLine ($" {context.Characters.Link} {url}", ConsoleColor.White);
62+
await Download (context, url, localArchivePath, "build-tools", Path.GetFileName (localArchivePath), downloadStatus);
63+
64+
if (!File.Exists (localArchivePath)) {
65+
Log.ErrorLine ($"Download of build-tools from {url} failed");
66+
return false;
67+
}
68+
69+
return true;
70+
}
71+
}
72+
}

build-tools/xaprepare/xaprepare/xaprepare.targets

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@
8686
<Replacement Include="@RemapAssemblyRefToolExecutable@=$(RemapAssemblyRefToolExecutable)" />
8787
<Replacement Include="@XABuildToolsFolder@=$(XABuildToolsFolder)" />
8888
<Replacement Include="@XABuildToolsVersion@=$(XABuildToolsVersion)" />
89+
<Replacement Include="@XABuildToolsPackagePrefixMacOS@=$(XABuildToolsPackagePrefixMacOS)" />
90+
<Replacement Include="@XABuildToolsPackagePrefixWindows@=$(XABuildToolsPackagePrefixWindows)" />
91+
<Replacement Include="@XABuildToolsPackagePrefixLinux@=$(XABuildToolsPackagePrefixLinux)" />
8992
<Replacement Include="@XABuildToolsPackagePrefix@=$(XABuildToolsPackagePrefix)" />
9093
<Replacement Include="@XAPlatformToolsVersion@=$(XAPlatformToolsVersion)" />
9194
<Replacement Include="@XAInstallPrefix@=$(XAInstallPrefix)" />

0 commit comments

Comments
 (0)