Skip to content

Commit

Permalink
Add support for NDK r23.
Browse files Browse the repository at this point in the history
NDK r23 removes GNU Binutils and so we need to switch to using our
bundled copy of them.  Additionally, the minimum API level supported by
the NDK is now 19.
  • Loading branch information
grendello committed Jul 15, 2021
1 parent 71ae556 commit 1b577aa
Show file tree
Hide file tree
Showing 13 changed files with 100 additions and 39 deletions.
5 changes: 3 additions & 2 deletions build-tools/xaprepare/xaprepare/Application/BuildInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ partial class BuildInfo : AppObject
public string NDKVersionMajor { get; private set; } = String.Empty;
public string NDKVersionMinor { get; private set; } = String.Empty;
public string NDKVersionMicro { get; private set; } = String.Empty;
public string NDKVersionTag { get; private set; } = String.Empty;
public string NDKMinimumApiAvailable { get; private set; } = String.Empty;

public string VersionHash { get; private set; } = String.Empty;
Expand Down Expand Up @@ -59,15 +60,15 @@ public bool GatherNDKInfo (Context context)
string rev = parts [1].Trim ();
NDKRevision = rev;

Version ver;
if (!Version.TryParse (rev, out ver)) {
if (!Utilities.ParseAndroidPkgRevision (rev, out Version? ver, out string tag)) {
Log.ErrorLine ($"Unable to parse NDK revision '{rev}' as a valid version string");
return false;
}

NDKVersionMajor = ver.Major.ToString ();
NDKVersionMinor = ver.Minor.ToString ();
NDKVersionMicro = ver.Build.ToString ();
NDKVersionTag = tag;
break;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public override void Init (Context context)
OutputMonoBtlsFilename = Configurables.Defaults.MonoRuntimeOutputMonoBtlsFilename;
OutputMonoPosixHelperFilename = Configurables.Defaults.MonoRuntimeOutputMonoPosixHelperFilename;
OutputProfilerFilename = Configurables.Defaults.MonoRuntimeOutputProfilerFilename;
Strip = Path.Combine (Configurables.Paths.AndroidToolchainBinDirectory, $"{Configurables.Defaults.AndroidToolchainPrefixes [Name]}-strip");
Strip = Path.Combine (Configurables.Paths.AndroidToolchainBinDirectory, "llvm-strip");
}
}
}
23 changes: 23 additions & 0 deletions build-tools/xaprepare/xaprepare/Application/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,29 @@ static partial class Utilities

public static readonly Encoding UTF8NoBOM = new UTF8Encoding (false);

public static bool ParseAndroidPkgRevision (string? v, out Version? version, out string? tag)
{
string? ver = v?.Trim ();
version = null;
tag = null;
if (String.IsNullOrEmpty (ver))
return false;

if (ver!.IndexOf ('.') < 0)
ver = $"{ver}.0";

int tagIdx = ver.IndexOf ('-');
if (tagIdx >= 0) {
tag = ver.Substring (tagIdx + 1);
ver = ver.Substring (0, tagIdx - 1);
}

if (Version.TryParse (ver, out version))
return true;

return false;
}

public static bool AbiChoiceChanged (Context context)
{
string cacheFile = Configurables.Paths.MonoRuntimesEnabledAbisCachePath;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ namespace Xamarin.Android.Prepare
{
class BuildAndroidPlatforms
{
public const string AndroidNdkVersion = "22b";
public const string AndroidNdkPkgRevision = "22.1.7171670";
public const string AndroidNdkVersion = "23-beta6";
public const string AndroidNdkPkgRevision = "23.0.7530507-beta6";

public static readonly List<AndroidPlatform> AllPlatforms = new List<AndroidPlatform> {
new AndroidPlatform (apiName: "", apiLevel: 1, platformID: "1"),
Expand Down Expand Up @@ -49,9 +49,9 @@ class BuildAndroidPlatforms
public const string AndroidX86_64_NET6 = AbiNames.TargetJit.AndroidX86_64 + "_NET6";

public static readonly Dictionary<string, uint> NdkMinimumAPI = new Dictionary<string, uint> {
{ AbiNames.TargetJit.AndroidArmV7a, 16 }, { AndroidArmV7a_NET6, 21 },
{ AbiNames.TargetJit.AndroidArmV7a, 19 }, { AndroidArmV7a_NET6, 21 },
{ AbiNames.TargetJit.AndroidArmV8a, 21 }, { AndroidArmV8a_NET6, 21 },
{ AbiNames.TargetJit.AndroidX86, 16 }, { AndroidX86_NET6, 21 },
{ AbiNames.TargetJit.AndroidX86, 19 }, { AndroidX86_NET6, 21 },
{ AbiNames.TargetJit.AndroidX86_64, 21 }, { AndroidX86_64_NET6, 21 },
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public AndroidToolchain ()
new AndroidToolchainComponent ("docs-24_r01", destDir: "docs", pkgRevision: "1", dependencyType: AndroidToolchainComponentType.BuildDependency),
new AndroidToolchainComponent ("android_m2repository_r47", destDir: Path.Combine ("extras", "android", "m2repository"), pkgRevision: "47.0.0", dependencyType: AndroidToolchainComponentType.BuildDependency),
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", dependencyType: AndroidToolchainComponentType.EmulatorDependency),
new AndroidToolchainComponent ($"android-ndk-r{AndroidNdkVersion}-{osTag}-x86_64", destDir: AndroidNdkDirectory, pkgRevision: AndroidPkgRevision),
new AndroidToolchainComponent ($"android-ndk-r{AndroidNdkVersion}-{osTag}", destDir: AndroidNdkDirectory, pkgRevision: AndroidPkgRevision),
new AndroidToolchainComponent ($"{XABuildToolsPackagePrefix}build-tools_r{XABuildToolsVersion}-{altOsTag}", destDir: Path.Combine ("build-tools", XABuildToolsFolder), isMultiVersion: true),
new AndroidToolchainComponent ($"commandlinetools-{cltOsTag}-{CommandLineToolsVersion}",
destDir: Path.Combine ("cmdline-tools", CommandLineToolsFolder), isMultiVersion: true),
Expand Down
24 changes: 4 additions & 20 deletions build-tools/xaprepare/xaprepare/Steps/Step_Android_SDK_NDK.cs
Original file line number Diff line number Diff line change
Expand Up @@ -307,37 +307,21 @@ bool IsInstalled (AndroidToolchainComponent component, string path, out bool mis
return false;
}

if (!ParseVersion (pkgRevision, out Version? pkgVer) || pkgVer == null) {
if (!Utilities.ParseAndroidPkgRevision (pkgRevision, out Version? pkgVer, out string pkgTag) || pkgVer == null) {
Log.DebugLine ($"Failed to parse a valid version from Pkg.Revision ({pkgRevision}) for component '{component.Name}'. Component will be reinstalled.");
return false;
}

if (!ParseVersion (component.PkgRevision, out Version? expectedPkgVer) || expectedPkgVer == null)
if (!Utilities.ParseAndroidPkgRevision (component.PkgRevision, out Version? expectedPkgVer, out string expectedTag) || expectedPkgVer == null)
throw new InvalidOperationException ($"Invalid expected package version for component '{component.Name}': {component.PkgRevision}");

bool equal = pkgVer == expectedPkgVer;
bool equal = (pkgVer == expectedPkgVer) && (pkgTag == expectedTag);
if (!equal)
Log.DebugLine ($"Installed version of '{component.Name}' ({pkgVer}) is different than the required one ({expectedPkgVer})");
Log.DebugLine ($"Installed version of '{component.Name}' ({pkgRevision}) is different than the required one ({component.PkgRevision})");

return equal;
}

bool ParseVersion (string? v, out Version? version)
{
string? ver = v?.Trim ();
version = null;
if (String.IsNullOrEmpty (ver))
return false;

if (ver!.IndexOf ('.') < 0)
ver = $"{ver}.0";

if (Version.TryParse (ver, out version))
return true;

return false;
}

bool IsNdk (AndroidToolchainComponent component)
{
return component.Name.StartsWith ("android-ndk", StringComparison.OrdinalIgnoreCase);
Expand Down
2 changes: 1 addition & 1 deletion external/xamarin-android-tools
18 changes: 13 additions & 5 deletions src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -349,14 +349,20 @@ IEnumerable<Config> GetAotConfigs (NdkTools ndk)
}

string toolchainLibDir;
if (ndk.UsesClang)
toolchainLibDir = GetNdkToolchainLibraryDir (ndk, toolchainPath, arch);
else
if (ndk.UsesClang) {
if (ndk.NoBinutils) {
toolchainLibDir = String.Empty;
} else {
toolchainLibDir = GetNdkToolchainLibraryDir (ndk, toolchainPath, arch);
}
} else
toolchainLibDir = GetNdkToolchainLibraryDir (ndk, toolchainPath);

var libs = new List<string>();
if (ndk.UsesClang) {
libs.Add ($"-L{toolchainLibDir.TrimEnd ('\\')}");
if (!String.IsNullOrEmpty (toolchainLibDir)) {
libs.Add ($"-L{toolchainLibDir.TrimEnd ('\\')}");
}
libs.Add ($"-L{androidLibPath.TrimEnd ('\\')}");

if (arch == AndroidTargetArch.Arm) {
Expand All @@ -366,7 +372,9 @@ IEnumerable<Config> GetAotConfigs (NdkTools ndk)
}
}

libs.Add (Path.Combine (toolchainLibDir, "libgcc.a"));
if (!String.IsNullOrEmpty (toolchainLibDir)) {
libs.Add (Path.Combine (toolchainLibDir, "libgcc.a"));
}
libs.Add (Path.Combine (androidLibPath, "libc.so"));
libs.Add (Path.Combine (androidLibPath, "libm.so"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void TestNdkUtil ()
Assert.IsTrue (ndk.ValidateNdkPlatform (arch, enableLLVM: false));
Assert.AreEqual (0, errors.Count, "NdkTools.ValidateNdkPlatform should not have returned false.");
int level = ndk.GetMinimumApiLevelFor (arch);
int expected = 16;
int expected = 19;
Assert.AreEqual (expected, level, $"Min Api Level for {arch} should be {expected}.");
var compilerNoQuotes = ndk.GetToolPath (NdkToolKind.CompilerC, arch, level);
Assert.AreEqual (0, errors.Count, "NdkTools.GetToolPath should not have errored.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Xml.Linq;
using Xamarin.Android.Build;
using Xamarin.Android.Tasks;
using Xamarin.ProjectTools;
using Microsoft.Android.Build.Tasks;
Expand All @@ -22,6 +24,8 @@ public class BaseTest

[SetUpFixture]
public class SetUp {
const string BinutilsSubdir = "ndk";

public static string DeviceAbi {
get;
private set;
Expand Down Expand Up @@ -75,6 +79,46 @@ public void BeforeAllTests ()
} catch (Exception ex) {
Console.Error.WriteLine ("Failed to determine whether there is Android target emulator or not: " + ex);
}

string hostNdkDir = GetHostBinutilsDir ();
string xabtDir = Path.GetDirectoryName (typeof (BuildApk).Assembly.Location);
string symlinkDir = Path.Combine (xabtDir, hostNdkDir);

// If directory exists then it's either a valid symlink or a real dir, don't touch anything in such instance
if (Directory.Exists (symlinkDir)) {
return;
}

// If a file exists and is a symlink, then it's probably a dangling link - recreate it
if (File.Exists (symlinkDir)) {
if (!SymbolicLink.IsPathSymlink (symlinkDir)) {
throw new InvalidOperationException ($"File named '{symlinkDir}' exists where a symbolic link to a directory should be.");
}

File.Delete (symlinkDir);
}

string binutilsDirFullPath = Path.Combine (XABuildPaths.PrefixDirectory, "lib", "xamarin.android", "xbuild", "Xamarin", "Android", hostNdkDir);
if (!SymbolicLink.Create (symlinkDir, binutilsDirFullPath)) {
throw new InvalidOperationException ($"Failed to create a symbolic link from '{symlinkDir}' to '{binutilsDirFullPath}'");
}
}

string GetHostBinutilsDir ()
{
if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) {
return BinutilsSubdir;
}

if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) {
return Path.Combine ("Linux", BinutilsSubdir);
}

if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX)) {
return Path.Combine ("Darwin", BinutilsSubdir);
}

throw new InvalidOperationException ($"Unsupported OS");
}

int GetSdkVersion ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ namespace Xamarin.Android.Tasks
{
class NdkToolsWithClangNoBinutils : NdkToolsWithClangNoPlatforms
{
const string BinutilsSubdir = "ndk";

public NdkToolsWithClangNoBinutils (string androidNdkPath, NdkVersion version, TaskLoggingHelper? log)
: base (androidNdkPath, version, log)
{
NdkToolNames[NdkToolKind.Linker] = "ld";
NoBinutils = true;

throw new NotSupportedException ($"NDK {Version} is not supported by this version of Xamarin.Android");
}

public override string GetToolPath (NdkToolKind kind, AndroidTargetArch arch, int apiLevel)
Expand All @@ -35,8 +35,9 @@ string GetEmbeddedToolPath (NdkToolKind kind, AndroidTargetArch arch)
{
string toolName = GetToolName (kind);
string triple = GetArchTriple (arch);
string binutilsDir = Path.Combine (MonoAndroidHelper.GetOSBinPath (), "ndk");

return $"[TODO]/{triple}-{toolName}";
return GetExecutablePath (Path.Combine (binutilsDir, $"{triple}-{toolName}"), mustExist: true);
}
}
}
1 change: 0 additions & 1 deletion src/monodroid/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,6 @@ endif()
if(ANDROID)
add_compile_definitions(HAVE_LZ4)
add_compile_definitions(PLATFORM_ANDROID)
add_compile_definitions(__ANDROID_API__=${ANDROID_NATIVE_API_LEVEL})

if(ANDROID_ABI MATCHES "^(arm64-v8a|x86_64)")
add_compile_definitions(ANDROID64)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<Compile Include="..\..\src\Xamarin.Android.Build.Tasks\Tests\Xamarin.Android.Build.Tests\Utilities\*.cs">
<Link>Utilities\%(FileName).cs</Link>
</Compile>
<Compile Include="..\..\tools\xabuild\SymbolicLink.cs" />
<None Include="..\..\src\Xamarin.Android.Build.Tasks\Tests\Xamarin.Android.Build.Tests\App.config" Link="App.config" />
</ItemGroup>

Expand Down

0 comments on commit 1b577aa

Please sign in to comment.