Skip to content

Commit a648981

Browse files
authored
[build] Use API-21 for all native builds (#4584)
Previously, we built the 64-bit targets (`x86-64` and `arm64-v8a`) against NDK API-21 and the32-bit targets (`x86` and `armeabi-v7a`) against NDK API-16. Update so that all targets build against API-21. This gives us the ability to speed up on-device app startup of Debug- configuration builds on 32-bit platforms by using POSIX APIs for directory traversal that are available starting from API-21 onwards ([**openat**(2)][0] and [**fstatat**(2)][1]). The switch to API-21 was initially planned for .NET5 but there's no significant harm in making the change now. In addition, this commit updates versions of several components: * Bump emulator version to 30.0.5 * Bump NDK version to 21b (21.1.6352462) * Bump x86 system image revision to 7 Also, `XABuildConfig.NDKMinimumApiAvailable` is now set to the minimum supported NDK API level instead of the minimum API level *installed* by the NDK. TODO: This commit knowingly breaks some unit tests, e.g. `Xamarin.Android.Build.Tests.BuildTest.BuildMultiDexApplication()`. These will be fixed in a later commit. [0]: https://linux.die.net/man/2/openat [1]: https://linux.die.net/man/2/fstatat
1 parent 5c9447d commit a648981

File tree

11 files changed

+66
-30
lines changed

11 files changed

+66
-30
lines changed

Configuration.props

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
<TargetFrameworkVersion Condition=" '$(TargetFrameworkVersion)' == '' And '$(UsingMicrosoftNETSdk)' != 'true' ">v4.7.1</TargetFrameworkVersion>
2020
<!-- Used by the `build-tools/create-vsix` build so that `Mono.Android.Export.dll`/etc. are only included *once* -->
2121
<!-- Should correspond to the first value from `$(API_LEVELS)` in `build-tools/api-xml-adjuster/Makefile` -->
22-
<AndroidFirstFrameworkVersion Condition="'$(AndroidFirstFrameworkVersion)' == ''">v4.4</AndroidFirstFrameworkVersion>
23-
<AndroidFirstApiLevel Condition="'$(AndroidFirstApiLevel)' == ''">19</AndroidFirstApiLevel>
22+
<AndroidFirstFrameworkVersion Condition="'$(AndroidFirstFrameworkVersion)' == ''">v5.0</AndroidFirstFrameworkVersion>
23+
<AndroidFirstApiLevel Condition="'$(AndroidFirstApiLevel)' == ''">21</AndroidFirstApiLevel>
2424
<AndroidFirstPlatformId Condition="'$(AndroidFirstPlatformId)' == ''">$(AndroidFirstApiLevel)</AndroidFirstPlatformId>
2525
<_IsRunningNuGetRestore Condition="$(RestoreTaskAssemblyFile.EndsWith('NuGet.exe', StringComparison.InvariantCultureIgnoreCase))">True</_IsRunningNuGetRestore>
2626
<!-- *Latest* *stable* API level binding that we support; used when building src/Xamarin.Android.Build.Tasks -->
@@ -136,8 +136,8 @@
136136
<AndroidToolPath Condition=" '$(AndroidToolPath)' == '' ">$(AndroidSdkFullPath)\tools</AndroidToolPath>
137137
<AndroidToolsBinPath Condition=" '$(AndroidToolsBinPath)' == '' ">$(AndroidToolPath)\bin</AndroidToolsBinPath>
138138
<AndroidToolExe Condition=" '$(AndroidToolExe)' == '' ">android</AndroidToolExe>
139-
<EmulatorVersion Condition=" '$(EmulatorVersion)' == '' ">5598178</EmulatorVersion>
140-
<EmulatorPkgRevision Condition=" '$(EmulatorPkgRevision)' == '' ">29.0.11</EmulatorPkgRevision>
139+
<EmulatorVersion Condition=" '$(EmulatorVersion)' == '' ">6306047</EmulatorVersion>
140+
<EmulatorPkgRevision Condition=" '$(EmulatorPkgRevision)' == '' ">30.0.5</EmulatorPkgRevision>
141141
<EmulatorToolPath Condition=" '$(EmulatorToolPath)' == '' ">$(AndroidSdkFullPath)\emulator</EmulatorToolPath>
142142
<EmulatorToolExe Condition=" '$(EmulatorToolExe)' == '' ">emulator</EmulatorToolExe>
143143
<NdkBuildPath Condition=" '$(NdkBuildPath)' == '' And '$(HostOS)' != 'Windows' ">$(AndroidNdkDirectory)\ndk-build</NdkBuildPath>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
### Minimum compatible Android version now Android 5.0 Lollipop (API level 21)
2+
3+
The minimum compatible Android version for Xamarin.Android apps is now Android
4+
5.0 Lollipop (API level 21). Warning XA4216 has been updated to help highlight
5+
this change for any projects that might still have an older version set for the
6+
`minSdkVersion` in the `AndroidManifest.xml` file:
7+
8+
```
9+
warning XA4216: AndroidManifest.xml //uses-sdk/@android:minSdkVersion '20' is less than API-21, this configuration is not supported.
10+
```
11+
12+
#### Background information
13+
14+
The unmanaged native libraries that are part of Xamarin.Android are now built to
15+
target Android 5.0 Lollipop (API level 21), so apps built using this release can
16+
abort due to incompatible APIs if run on earlier Android versions.

build-tools/api-merge/merge-configuration.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
<File Path="api-R.xml.in" Level="R" />
2222
</Inputs>
2323
<Outputs>
24-
<File Path="android-19\mcw\api.xml" LastLevel="19" />
25-
<File Path="android-20\mcw\api.xml" LastLevel="20" />
2624
<File Path="android-21\mcw\api.xml" LastLevel="21" />
2725
<File Path="android-22\mcw\api.xml" LastLevel="22" />
2826
<File Path="android-23\mcw\api.xml" LastLevel="23" />

build-tools/api-xml-adjuster/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ API_XML_TOOL = $(BUILDBIN)/api-xml-adjuster.exe
1717
RUNTIME = mono --debug
1818
RUN_CLASS_PARSE = $(RUNTIME) $(CLASS_PARSE)
1919
RUN_API_XML_TOOL = $(RUNTIME) $(API_XML_TOOL)
20-
API_LEVELS = 10 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 R
20+
API_LEVELS = 21 22 23 24 25 26 27 28 29 R
2121

2222
XML_OUTPUT_DIR = .
2323

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ namespace Xamarin.Android.Prepare
55
{
66
class BuildAndroidPlatforms
77
{
8-
public const string AndroidNdkVersion = "21";
9-
public const string AndroidNdkPkgRevision = "21.0.6113669";
8+
public const string AndroidNdkVersion = "21b";
9+
public const string AndroidNdkPkgRevision = "21.1.6352462";
1010

1111
public static readonly List<AndroidPlatform> AllPlatforms = new List<AndroidPlatform> {
1212
new AndroidPlatform (apiName: "", apiLevel: 1, platformID: "1"),
@@ -27,8 +27,8 @@ class BuildAndroidPlatforms
2727
new AndroidPlatform (apiName: "Jelly Bean", apiLevel: 16, platformID: "16", include: "v4.1"),
2828
new AndroidPlatform (apiName: "Jelly Bean", apiLevel: 17, platformID: "17", include: "v4.2"),
2929
new AndroidPlatform (apiName: "Jelly Bean", apiLevel: 18, platformID: "18", include: "v4.3"),
30-
new AndroidPlatform (apiName: "Kit Kat", apiLevel: 19, platformID: "19", include: "v4.4", framework: "v4.4"),
31-
new AndroidPlatform (apiName: "Kit Kat + Wear support", apiLevel: 20, platformID: "20", include: "v4.4.87", framework: "v4.4.87"),
30+
new AndroidPlatform (apiName: "Kit Kat", apiLevel: 19, platformID: "19", include: "v4.4"),
31+
new AndroidPlatform (apiName: "Kit Kat + Wear support", apiLevel: 20, platformID: "20", include: "v4.4.87"),
3232
new AndroidPlatform (apiName: "Lollipop", apiLevel: 21, platformID: "21", include: "v5.0", framework: "v5.0"),
3333
new AndroidPlatform (apiName: "Lollipop", apiLevel: 22, platformID: "22", include: "v5.1", framework: "v5.1"),
3434
new AndroidPlatform (apiName: "Marshmallow", apiLevel: 23, platformID: "23", include: "v6.0", framework: "v6.0"),
@@ -42,9 +42,9 @@ class BuildAndroidPlatforms
4242
};
4343

4444
public static readonly Dictionary<string, uint> NdkMinimumAPI = new Dictionary<string, uint> {
45-
{ AbiNames.TargetJit.AndroidArmV7a, 16 },
45+
{ AbiNames.TargetJit.AndroidArmV7a, 21 },
4646
{ AbiNames.TargetJit.AndroidArmV8a, 21 },
47-
{ AbiNames.TargetJit.AndroidX86, 16 },
47+
{ AbiNames.TargetJit.AndroidX86, 21 },
4848
{ AbiNames.TargetJit.AndroidX86_64, 21 },
4949
};
5050
}

build-tools/xaprepare/xaprepare/ConfigAndData/Dependencies/AndroidToolchain.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,11 @@ public AndroidToolchain ()
4444

4545
new AndroidToolchainComponent ("docs-24_r01", destDir: "docs", pkgRevision: "1"),
4646
new AndroidToolchainComponent ("android_m2repository_r47", destDir: Path.Combine ("extras", "android", "m2repository"), pkgRevision: "47.0.0"),
47-
new AndroidToolchainComponent ("x86-29_r06", destDir: Path.Combine ("system-images", "android-29", "default", "x86"), relativeUrl: new Uri ("sys-img/android/", UriKind.Relative), pkgRevision: "6"),
47+
48+
// NOTE: for some reason x86-29_r07 and x86_64-29_r07 zips are tagged with the OS name, JUST these system images - when
49+
// updating to a latter version check if that's changed or not.
4850
new AndroidToolchainComponent ($"x86_64-29_r07-{osTag}", destDir: Path.Combine ("system-images", "android-29", "default", "x86_64"), relativeUrl: new Uri ("sys-img/android/", UriKind.Relative), pkgRevision: "7"),
51+
new AndroidToolchainComponent ($"x86-29_r07-{osTag}", destDir: Path.Combine ("system-images", "android-29", "default", "x86"), relativeUrl: new Uri ("sys-img/android/", UriKind.Relative), pkgRevision: "7"),
4952
new AndroidToolchainComponent ($"android-ndk-r{AndroidNdkVersion}-{osTag}-x86_64", destDir: AndroidNdkDirectory, pkgRevision: AndroidPkgRevision),
5053
new AndroidToolchainComponent ($"build-tools_r{XABuildToolsVersion}-{altOsTag}", destDir: Path.Combine ("build-tools", XABuildToolsFolder), isMultiVersion: true),
5154
new AndroidToolchainComponent ($"platform-tools_r{XAPlatformToolsVersion}-{osTag}", destDir: "platform-tools", pkgRevision: XAPlatformToolsVersion),

build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,17 @@ GeneratedFile Get_XABuildConfig_cs (Context context)
114114
{
115115
const string OutputFileName = "XABuildConfig.cs";
116116

117+
uint minimumApiAvailable = UInt32.MaxValue;
118+
foreach (uint api in BuildAndroidPlatforms.NdkMinimumAPI.Values) {
119+
if (api > minimumApiAvailable)
120+
continue;
121+
minimumApiAvailable = api;
122+
}
123+
117124
var replacements = new Dictionary<string, string> (StringComparer.Ordinal) {
118125
{ "@NDK_REVISION@", context.BuildInfo.NDKRevision },
119126
{ "@NDK_RELEASE@", BuildAndroidPlatforms.AndroidNdkVersion },
120-
{ "@NDK_MINIMUM_API_AVAILABLE@", context.BuildInfo.NDKMinimumApiAvailable },
127+
{ "@NDK_MINIMUM_API_AVAILABLE@", minimumApiAvailable.ToString () },
121128
{ "@NDK_VERSION_MAJOR@", context.BuildInfo.NDKVersionMajor },
122129
{ "@NDK_VERSION_MINOR@", context.BuildInfo.NDKVersionMinor },
123130
{ "@NDK_VERSION_MICRO@", context.BuildInfo.NDKVersionMicro },

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ public void BuildAotApplicationAndÜmläüts (string supportedAbis, bool enableL
10071007
// LLVM passes a direct path to libc.so, and we need to use the libc.so
10081008
// which corresponds to the *minimum* SDK version specified in AndroidManifest.xml
10091009
// Since we overrode minSdkVersion=16, that means we should use libc.so from android-16.
1010-
StringAssertEx.ContainsRegex (@"\s*\[aot-compiler stdout].*android-16.arch-.*.usr.lib.libc\.so", b.LastBuildOutput, "AOT+LLVM should use libc.so from minSdkVersion!");
1010+
StringAssertEx.ContainsRegex (@"\s*\[aot-compiler stdout].*android-21.arch-.*.usr.lib.libc\.so", b.LastBuildOutput, "AOT+LLVM should use libc.so from minSdkVersion!");
10111011
}
10121012
foreach (var abi in supportedAbis.Split (new char [] { ';' })) {
10131013
var libapp = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath,
@@ -1137,25 +1137,32 @@ public void BuildProguardEnabledProject ([Values (true, false)] bool isRelease,
11371137

11381138
XamarinAndroidApplicationProject CreateMultiDexRequiredApplication (string debugConfigurationName = "Debug", string releaseConfigurationName = "Release")
11391139
{
1140+
const int NumberOfMethods = (32 * 1024) - 1;
11401141
var proj = new XamarinAndroidApplicationProject (debugConfigurationName, releaseConfigurationName);
11411142
proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods.java") {
11421143
TextContent = () => "public class ManyMethods { \n"
1143-
+ string.Join (Environment.NewLine, Enumerable.Range (0, 32768).Select (i => "public void method" + i + "() {}"))
1144+
+ string.Join (Environment.NewLine, Enumerable.Range (0, NumberOfMethods).Select (i => "public void method" + i + "() {}"))
11441145
+ "}",
11451146
Encoding = Encoding.ASCII
11461147
});
11471148
proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods2.java") {
11481149
TextContent = () => "public class ManyMethods2 { \n"
1149-
+ string.Join (Environment.NewLine, Enumerable.Range (0, 32768).Select (i => "public void method" + i + "() {}"))
1150+
+ string.Join (Environment.NewLine, Enumerable.Range (0, NumberOfMethods).Select (i => "public void method" + i + "() {}"))
11501151
+ "}",
11511152
Encoding = Encoding.ASCII
11521153
});
1154+
proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods3.java") {
1155+
TextContent = () => "public class ManyMethods3 { \n"
1156+
+ string.Join (Environment.NewLine, Enumerable.Range (0, NumberOfMethods).Select (i => "public void method" + i + "() {}"))
1157+
+ "}",
1158+
Encoding = Encoding.ASCII
1159+
});
11531160
return proj;
11541161
}
11551162

11561163
[Test]
11571164
[Category ("Minor")]
1158-
public void BuildApplicationOver65536Methods ([Values ("dx", "d8")] string dexTool)
1165+
public void BuildApplicationRequiresMultiDex ([Values ("dx", "d8")] string dexTool)
11591166
{
11601167
var proj = CreateMultiDexRequiredApplication ();
11611168
proj.DexTool = dexTool;
@@ -1197,9 +1204,13 @@ public void BuildMultiDexApplication (bool useJackAndJill, string fxVersion)
11971204
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
11981205
Assert.IsTrue (File.Exists (Path.Combine (Root, b.ProjectDirectory, intermediateDir, "android/bin/classes.dex")),
11991206
"multidex-ed classes.zip exists");
1200-
var multidexKeepPath = Path.Combine (Root, b.ProjectDirectory, intermediateDir, "multidex.keep");
1201-
Assert.IsTrue (File.Exists (multidexKeepPath), "multidex.keep exists");
1202-
Assert.IsTrue (File.ReadAllLines (multidexKeepPath).Length > 1, "multidex.keep must contain more than one line.");
1207+
1208+
if (proj.DexTool != "d8") {
1209+
var multidexKeepPath = Path.Combine (Root, b.ProjectDirectory, intermediateDir, "multidex.keep");
1210+
Assert.IsTrue (File.Exists (multidexKeepPath), "multidex.keep exists");
1211+
Assert.IsTrue (File.ReadAllLines (multidexKeepPath).Length > 1, "multidex.keep must contain more than one line.");
1212+
}
1213+
12031214
Assert.IsTrue (b.LastBuildOutput.ContainsText (Path.Combine (proj.TargetFrameworkVersion, "mono.android.jar")), proj.TargetFrameworkVersion + "/mono.android.jar should be used.");
12041215
Assert.IsFalse (b.LastBuildOutput.ContainsText ("Duplicate zip entry"), "Should not get warning about [META-INF/MANIFEST.MF]");
12051216
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ public void DirectBootAwareAttribute ()
273273
}
274274
}
275275

276+
// Information about version codes: https://devblogs.microsoft.com/xamarin/advanced-android-versioncode/
276277
static object [] VersionCodeTestSource = new object [] {
277278
new object[] {
278279
/* seperateApk */ false,
@@ -362,7 +363,7 @@ public void DirectBootAwareAttribute ()
362363
/* pattern */ "{abi}{minSDK:00}{versionCode:000}",
363364
/* props */ null,
364365
/* shouldBuild */ true,
365-
/* expected */ "216012;316012",
366+
/* expected */ "221012;321012",
366367
},
367368
new object[] {
368369
/* seperateApk */ true,
@@ -372,7 +373,7 @@ public void DirectBootAwareAttribute ()
372373
/* pattern */ "{abi}{minSDK:00}{screen}{versionCode:000}",
373374
/* props */ "screen=24",
374375
/* shouldBuild */ true,
375-
/* expected */ "21624012;31624012",
376+
/* expected */ "22124012;32124012",
376377
},
377378
new object[] {
378379
/* seperateApk */ true,
@@ -382,7 +383,7 @@ public void DirectBootAwareAttribute ()
382383
/* pattern */ "{abi}{minSDK:00}{screen}{foo:0}{versionCode:000}",
383384
/* props */ "screen=24;foo=$(Foo)",
384385
/* shouldBuild */ true,
385-
/* expected */ "216241012;316241012",
386+
/* expected */ "221241012;321241012",
386387
},
387388
new object[] {
388389
/* seperateApk */ true,
@@ -392,7 +393,7 @@ public void DirectBootAwareAttribute ()
392393
/* pattern */ "{abi}{minSDK:00}{screen}{foo:00}{versionCode:000}",
393394
/* props */ "screen=24;foo=$(Foo)",
394395
/* shouldBuild */ false,
395-
/* expected */ "2162401012;3162401012",
396+
/* expected */ "2212401012;3212401012",
396397
},
397398
};
398399

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/NdkUtilTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public void TestNdkUtil ()
4141
Assert.IsTrue (NdkUtil.ValidateNdkPlatform (log, ndkDir, arch, enableLLVM: false));
4242
Assert.AreEqual (0, errors.Count, "NdkUtil.ValidateNdkPlatform should not have returned false.");
4343
int level = NdkUtil.GetMinimumApiLevelFor (arch, ndkDir);
44-
int expected = 16;
44+
int expected = 21;
4545
Assert.AreEqual (expected, level, $"Min Api Level for {arch} should be {expected}.");
4646
var compilerNoQuotes = NdkUtil.GetNdkTool (ndkDir, arch, "gcc", level);
4747
Assert.AreEqual (0, errors.Count, "NdkUtil.GetNdkTool should not have errored.");

0 commit comments

Comments
 (0)