Skip to content

Commit b8efdae

Browse files
committed
[Xamarin.Android.Tools.AndroidSdk] Preview Build-Tools are Last (#85)
Context: dotnet/android#4735 > https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3771781&view=ms.vss-test-web.build-test-results-tab&runId=13535824&resultId=100072&paneView=attachments Context: dotnet/android#4567 Context: xamarin/androidtools@a3965ba The Windows Smoke Tests are failing on PR #4735, because the wrong Android SDK Build-tools version is being used: Task "ResolveAndroidTooling" (TaskId:9) Task Parameter:AndroidSdkBuildToolsVersion=29.0.2 (TaskId:9) … Trying build-tools path: C:\Users\dlab14\android-toolchain\sdk\build-tools\30.0.0-rc4 (TaskId:9) … ResolveAndroidTooling Outputs: (TaskId:9) AndroidSdkBuildToolsPath: C:\Users\dlab14\android-toolchain\sdk\build-tools\30.0.0-rc4 (TaskId:9) Here, Build-tools 30.0.0-rc4 is used. Why is that a problem? Because JDK 1.8 is still used! C:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.25\bin\java.exe -jar C:\Users\dlab14\android-toolchain\sdk\build-tools\30.0.0-rc4\lib\apksigner.jar sign --ks "C:\Users\dlab14\AppData\Local\Xamarin\Mono for Android\debug.keystore" --ks-pass pass:android --ks-key-alias androiddebugkey --key-pass pass:android --min-sdk-version 21 --max-sdk-version 29 … java.lang.UnsupportedClassVersionError: com/android/apksigner/ApkSignerTool has been compiled by a more recent version of the Java Runtime (class file version 53.0), this version of the Java Runtime only recognizes class file versions up to 52.0 JDK11 is required in order to use Build-tools r30+, but we don't currently support JDK11 use; see PR #4567. What's happening is that *because of* PR #4567, some of the build machines are being provisioned with Build-tools 30.0.0-rc4, i.e. e.g. `$HOME/android-toolchain/sdk/build-tools/30.0.0-rc4` *exists*. *Because* that directory exists -- and *isn't* parse-able by `System.Version.TryParse()` -- it's considered to be a "preview" version, and thus *has priority over non-preview versions*, and thus is returned *first*. *Because* it's returned *first*, `<ResolveAndroidTooling/>` prefers it, causing the `<AndroidApkSigner/>` task to subsequently fail, because it's unusable. The "workaround" is for `$(AndroidSdkBuildToolsVersion)` to be set to the desired version to use. In retrospect, however, this is all *backwards*: `AndroidSdkInfo.GetBuildToolsPaths()` shouldn't prefer preview versions, it should prefer *non-* preview versions. If you *really* want a preview version, *then* you should override `$(AndroidSdkBuildToolsPath)`. Previews should be opt-in, not opt-out. With that in mind, why were preview versions preferred in the first place? That was done in xamarin/androidtools@a3965bae to fix [Bug #30555][0], stating: > handle[] by searching for these "preview" directories first, so that > the latest tooling will be used IF the user decides to install it. > The assumption is that a stable release will NOT inlcude a suffix. While "a preview directory will only exist if someone explicitly installs it, and thus should be preferred" sounds reasonable, in retrospect it's a recipe for pain when using a shared CI environment. Just because it's there does *not* mean it should be used. [0]: https://bugzilla.xamarin.com/show_bug.cgi?id=30555
1 parent 23c4fe0 commit b8efdae

File tree

4 files changed

+49
-7
lines changed

4 files changed

+49
-7
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
CONFIGURATION := Debug
2-
NUNIT_CONSOLE := packages/NUnit.ConsoleRunner.3.9.0/tools/nunit3-console.exe
2+
NUNIT_CONSOLE := packages/nunit.consolerunner/3.9.0/tools/nunit3-console.exe
33
OS := $(shell uname)
44
RUNTIME := mono --debug=casts
55
V ?= 0
@@ -23,7 +23,7 @@ define RUN_NUNIT_TEST
2323
$(RUNTIME) \
2424
$(NUNIT_CONSOLE) $(NUNIT_EXTRA) $(1) \
2525
$(if $(RUN),-run:$(RUN)) \
26-
--result="TestResult-$(basename $(notdir $(1))).xml;format=nunit2" \
26+
--result="TestResult-$(basename $(notdir $(1))).xml" \
2727
-output=bin/Test$(CONFIGURATION)/TestOutput-$(basename $(notdir $(1))).txt \
2828
|| true ; \
2929
if [ -f "bin/Test$(CONFIGURATION)/TestOutput-$(basename $(notdir $(1))).txt" ] ; then \

NuGet.config

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<packageSources>
4+
<clear />
5+
<!-- ensure only the sources defined below are used -->
6+
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" protocolVersion="3" />
7+
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
8+
<add key="dotnet internal feed" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" protocolVersion="3" />
9+
10+
<!-- This is needed (currently) for the Xamarin.Android.Deploy.Installer dependency, getting the installer -->
11+
<!-- Android binary, to support delta APK install -->
12+
<add key="xamarin.android util" value="https://pkgs.dev.azure.com/xamarin/public/_packaging/Xamarin.Android/nuget/v3/index.json" />
13+
</packageSources>
14+
<config>
15+
<add key="globalPackagesFolder" value="packages" />
16+
</config>
17+
</configuration>

src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,17 @@ public IEnumerable<string> GetBuildToolsPaths ()
4545
{
4646
var buildTools = Path.Combine (AndroidSdkPath, "build-tools");
4747
if (Directory.Exists (buildTools)) {
48+
var sorted = SortedSubdirectoriesByVersion (buildTools);
49+
50+
foreach (var d in sorted)
51+
yield return d;
52+
4853
var preview = Directory.EnumerateDirectories (buildTools)
4954
.Where(x => TryParseVersion (Path.GetFileName (x)) == null)
5055
.Select(x => x);
5156

5257
foreach (var d in preview)
5358
yield return d;
54-
55-
var sorted = SortedSubdirectoriesByVersion (buildTools);
56-
57-
foreach (var d in sorted)
58-
yield return d;
5959
}
6060
var ptPath = Path.Combine (AndroidSdkPath, "platform-tools");
6161
if (Directory.Exists (ptPath))

tests/Xamarin.Android.Tools.AndroidSdk-Tests/AndroidSdkInfoTests.cs

+25
Original file line numberDiff line numberDiff line change
@@ -448,5 +448,30 @@ string UnixConfigPath {
448448
return Path.Combine (UnixConfigDirOverridePath, "monodroid-config.xml");
449449
}
450450
}
451+
452+
[Test]
453+
public void GetBuildToolsPaths_StableVersionsFirst ()
454+
{
455+
CreateSdks (out string root, out string jdk, out string ndk, out string sdk);
456+
CreateFauxAndroidSdkDirectory (sdk, "27.0.0-rc4");
457+
458+
var logs = new StringWriter ();
459+
Action<TraceLevel, string> logger = (level, message) => {
460+
logs.WriteLine ($"[{level}] {message}");
461+
};
462+
463+
try {
464+
var info = new AndroidSdkInfo (logger, androidSdkPath: sdk, androidNdkPath: ndk, javaSdkPath: jdk);
465+
466+
var buildToolsPaths = info.GetBuildToolsPaths ().ToList ();
467+
Assert.AreEqual (3, buildToolsPaths.Count);
468+
Assert.AreEqual (Path.Combine (sdk, "build-tools", "26.0.0"), buildToolsPaths [0]);
469+
Assert.AreEqual (Path.Combine (sdk, "build-tools", "27.0.0-rc4"), buildToolsPaths [1]);
470+
Assert.AreEqual (Path.Combine (sdk, "platform-tools"), buildToolsPaths [2]);
471+
}
472+
finally {
473+
Directory.Delete (root, recursive: true);
474+
}
475+
}
451476
}
452477
}

0 commit comments

Comments
 (0)