Skip to content

Commit

Permalink
[XA.Build.Tasks] Add AndroidBinUtilsDirectory prop (#3567)
Browse files Browse the repository at this point in the history
Fixes: #3564

Install Visual Studio for Mac on macOS 10.15 Catalina Beta 7,
and build a project.

Expected results: it builds!

Actual results: not so much:

	Task Parameter:AndroidSdkBuildToolsPath=…/android-sdk-macosx/build-tools/28.0.3/ (TaskId:273)
	  [Native Linker] …/android-sdk-macosx/build-tools/28.0.3/aarch64-linux-android-ld --unresolved-symbols=ignore-in-shared-libs --export-dynamic -soname libxamarin-app.so -z relro -z noexecstack --enable-new-dtags --eh-frame-hdr -shared --build-id --warn-shared-textrel --fatal-warnings -o obj/Release/app_shared_libraries/arm64-v8a/libxamarin-app.so --fix-cortex-a53-843419 -m aarch64linux obj/Release/android/typemap.jm.arm64-v8a.o obj/Release/android/typemap.mj.arm64-v8a.o obj/Release/android/environment.arm64-v8a.o (TaskId:273)
	  [Native Linker] …/android-sdk-macosx/build-tools/28.0.3/arm-linux-androideabi-ld --unresolved-symbols=ignore-in-shared-libs --export-dynamic -soname libxamarin-app.so -z relro -z noexecstack --enable-new-dtags --eh-frame-hdr -shared --build-id --warn-shared-textrel --fatal-warnings -o obj/Release/app_shared_libraries/armeabi-v7a/libxamarin-app.so -X -m armelf_linux_eabi obj/Release/android/typemap.jm.armeabi-v7a.o obj/Release/android/typemap.mj.armeabi-v7a.o obj/Release/android/environment.armeabi-v7a.o (TaskId:273)
	/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets(2869,3):
	error XA3001: Could not link native shared library: libxamarin-app.so
	Done executing task "LinkApplicationSharedLibraries" -- FAILED.

The cause of the error is:

 1. `libxamarin-app.so` is required (see decfbcc), which
 2. Requires that we be able to execute `arm-linux-androideabi-ld`, and
 3. macOS 10.15 Catalina no longer executes 32-bit binaries.

As it happens™, the Android SDK Build-tools package still contains
32-bit native binaries, up through and including Build-tools 29.0.0.
(The Android NDK *does* contain 64-bit binaries.)

At this time, we don't know if there will *be* a Build-tools package
which contains 64-bit binaries before Catalina drops.

It is also moot: as of f0b1e8a we now redistribute *our own* `*-ld`
and `*-strip` utilities, which are 64-bit.  There is thus no need to
use the Build-tools versions of these files.

The problem here was that some of our tasks used the bundled NDK
tools, while some of our tasks didn't, and instead required that
they exist within `$(AndroidSdkBuildToolsPath)`, the Android SDK
Build-tools directory.

Add a new overridable `$(AndroidBinUtilsDirectory)` MSBuild property
which contains the `*-as`, `*-ld`, and `*-strip` utilities needed for
assembling and linking native code.  The value of this new property
defaults to inside the Xamarin.Android installation path,
`$(MonoAndroidBinDirectory)\ndk\`.

`$(AndroidBinUtilsDirectory)` is an overridable property because the
NDK utilities are GPL'd, and if someone wishes to use their own
version of these utilities, overriding `$(AndroidBinUtilsDirectory)`
will be much easier than replacing files within the installation
directory.

The result is that builds now use reliably 64-bit binaries:

	Task "LinkApplicationSharedLibraries"
	  [Native Linker] /Library/Frameworks/Xamarin.Android.framework/Libraries/xbuild/Xamarin/Android/Darwin/ndk/aarch64-linux-android-ld --unresolved-symbols=ignore-in-shared-libs --export-dynamic -soname libxamarin-app.so -z relro -z noexecstack --enable-new-dtags --eh-frame-hdr -shared --build-id --warn-shared-textrel --fatal-warnings -o obj/Release/app_shared_libraries/arm64-v8a/libxamarin-app.so --fix-cortex-a53-843419 -m aarch64linux obj/Release/android/typemap.jm.arm64-v8a.o obj/Release/android/typemap.mj.arm64-v8a.o obj/Release/android/environment.arm64-v8a.o
	  [Native Linker] /Library/Frameworks/Xamarin.Android.framework/Libraries/xbuild/Xamarin/Android/Darwin/ndk/arm-linux-androideabi-ld --unresolved-symbols=ignore-in-shared-libs --export-dynamic -soname libxamarin-app.so -z relro -z noexecstack --enable-new-dtags --eh-frame-hdr -shared --build-id --warn-shared-textrel --fatal-warnings -o obj/Release/app_shared_libraries/armeabi-v7a/libxamarin-app.so -X -m armelf_linux_eabi obj/Release/android/typemap.jm.armeabi-v7a.o obj/Release/android/typemap.mj.armeabi-v7a.o obj/Release/android/environment.armeabi-v7a.o
	Done executing task "LinkApplicationSharedLibraries".
  • Loading branch information
pjcollins authored and jonpryor committed Sep 4, 2019
1 parent 03cd478 commit 97f345a
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 12 deletions.
10 changes: 10 additions & 0 deletions Documentation/guides/BuildProcess.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,16 @@ when packaging Release applications.

Added in Xamarin.Android 6.1.

- **AndroidBinUtilsPath** – A path to a directory containing
the Android [binutils][binutils] such as `ld`, the native linker,
and `as`, the native assembler. These binaries a subset of the
Android NDK, and are bundled with the Xamarin.Android
installation. `$(MonoAndroidBinDirectory)\ndk\` by default.
Added in Xamarin.Android 10.0.
[binutils]: https://android.googlesource.com/toolchain/binutils/
- **AndroidBuildApplicationPackage** – A boolean value that
indicates whether to create and sign the package (.apk). Setting
this value to `True` is equivalent to using the
Expand Down
5 changes: 3 additions & 2 deletions src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public class Aot : AsyncTask

public ITaskItem [] Profiles { get; set; }

public string ToolsDirectory { get; set; }
[Required]
public string AndroidBinUtilsDirectory { get; set; }

[Output]
public string[] NativeLibrariesReferences { get; set; }
Expand Down Expand Up @@ -364,7 +365,7 @@ IEnumerable<Config> GetAotConfigs ()
int level = 0;
string toolPrefix = EnableLLVM
? NdkUtil.GetNdkToolPrefix (AndroidNdkDirectory, arch, level = GetNdkApiLevel (AndroidNdkDirectory, AndroidApiLevel, arch))
: Path.Combine (ToolsDirectory, "ndk", $"{NdkUtil.GetArchDirName (arch)}-");
: Path.Combine (AndroidBinUtilsDirectory, $"{NdkUtil.GetArchDirName (arch)}-");
var toolchainPath = toolPrefix.Substring(0, toolPrefix.LastIndexOf(Path.DirectorySeparatorChar));
var ldFlags = string.Empty;
if (EnableLLVM) {
Expand Down
12 changes: 7 additions & 5 deletions src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ sealed class Config
[Required]
public string WorkingDirectory { get; set; }

[Required]
public string AndroidBinUtilsDirectory { get; set; }

public override bool Execute ()
{
try {
Expand Down Expand Up @@ -134,32 +137,31 @@ bool RunAssembler (Config config)

IEnumerable<Config> GetAssemblerConfigs ()
{
string sdkBinDirectory = Path.Combine (MonoAndroidHelper.GetOSBinPath (), "ndk");
foreach (ITaskItem item in Sources) {
string abi = item.GetMetadata ("abi")?.ToLowerInvariant ();
string prefix = String.Empty;
AndroidTargetArch arch;

switch (abi) {
case "armeabi-v7a":
prefix = Path.Combine (sdkBinDirectory, "arm-linux-androideabi");
prefix = Path.Combine (AndroidBinUtilsDirectory, "arm-linux-androideabi");
arch = AndroidTargetArch.Arm;
break;

case "arm64":
case "arm64-v8a":
case "aarch64":
prefix = Path.Combine (sdkBinDirectory, "aarch64-linux-android");
prefix = Path.Combine (AndroidBinUtilsDirectory, "aarch64-linux-android");
arch = AndroidTargetArch.Arm64;
break;

case "x86":
prefix = Path.Combine (sdkBinDirectory, "i686-linux-android");
prefix = Path.Combine (AndroidBinUtilsDirectory, "i686-linux-android");
arch = AndroidTargetArch.X86;
break;

case "x86_64":
prefix = Path.Combine (sdkBinDirectory, "x86_64-linux-android");
prefix = Path.Combine (AndroidBinUtilsDirectory, "x86_64-linux-android");
arch = AndroidTargetArch.X86_64;
break;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ sealed class InputFiles
public bool DebugBuild { get; set; }

[Required]
public string AndroidSdkBuildToolsPath { get; set; }
public string AndroidBinUtilsDirectory { get; set; }

public override bool Execute ()
{
Expand Down Expand Up @@ -210,9 +210,9 @@ IEnumerable<Config> GetLinkerConfigs ()
linkerArgs.Add (QuoteFileName (file));
}

string ld = MonoAndroidHelper.GetExecutablePath (AndroidSdkBuildToolsPath, $"{NdkUtil.GetNdkToolchainPrefix (arch, false)}ld");
string ld = MonoAndroidHelper.GetExecutablePath (AndroidBinUtilsDirectory, $"{NdkUtil.GetNdkToolchainPrefix (arch, false)}ld");
yield return new Config {
LinkerPath = Path.Combine (AndroidSdkBuildToolsPath, ld),
LinkerPath = Path.Combine (AndroidBinUtilsDirectory, ld),
LinkerOptions = String.Join (" ", linkerArgs),
OutputSharedLibrary = inputs.OutputSharedLibrary,
};
Expand Down
5 changes: 5 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Tasks/ResolveSdksTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ public class ResolveSdks : Task
[Output]
public string MonoAndroidLibPath { get; set; }

[Output]
public string AndroidBinUtilsPath { get; set; }

public override bool Execute ()
{
// OS X: $prefix/lib/xamarin.android/xbuild/Xamarin/Android
Expand All @@ -68,6 +71,7 @@ public override bool Execute ()
}
MonoAndroidBinPath = MonoAndroidHelper.GetOSBinPath () + Path.DirectorySeparatorChar;
MonoAndroidLibPath = MonoAndroidHelper.GetOSLibPath () + Path.DirectorySeparatorChar;
AndroidBinUtilsPath = MonoAndroidBinPath + "ndk" + Path.DirectorySeparatorChar;

MonoAndroidHelper.RefreshSupportedVersions (ReferenceAssemblyPaths);

Expand Down Expand Up @@ -105,6 +109,7 @@ public override bool Execute ()
Log.LogDebugMessage ($" {nameof (JavaSdkPath)}: {JavaSdkPath}");
Log.LogDebugMessage ($" {nameof (MonoAndroidBinPath)}: {MonoAndroidBinPath}");
Log.LogDebugMessage ($" {nameof (MonoAndroidToolsPath)}: {MonoAndroidToolsPath}");
Log.LogDebugMessage ($" {nameof (AndroidBinUtilsPath)}: {AndroidBinUtilsPath}");

//note: this task does not error out if it doesn't find all things. that's the job of the targets
return !Log.HasLoggedErrors;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
<Output TaskParameter="MonoAndroidToolsPath" PropertyName="MonoAndroidToolsDirectory" />
<Output TaskParameter="MonoAndroidBinPath" PropertyName="MonoAndroidBinDirectory" />
<Output TaskParameter="MonoAndroidLibPath" PropertyName="MonoAndroidLibDirectory" />
<Output TaskParameter="AndroidBinUtilsPath" PropertyName="AndroidBinUtilsDirectory" Condition=" '$(AndroidBinUtilsDirectory)' == '' " />
</ResolveSdks>
<ResolveJdkJvmPath
JavaSdkPath="$(_JavaSdkDirectory)"
Expand Down Expand Up @@ -2830,6 +2831,7 @@ because xbuild doesn't support framework reference assemblies.
Sources="@(_TypeMapAssemblySource);@(_EnvironmentAssemblySource)"
DebugBuild="$(AndroidIncludeDebugSymbols)"
WorkingDirectory="$(_NativeAssemblySourceDir)"
AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)"
/>
<ItemGroup>
<FileWrites Include="@(_NativeAssemblyTarget)" />
Expand All @@ -2852,7 +2854,7 @@ because xbuild doesn't support framework reference assemblies.
ObjectFiles="@(_NativeAssemblyTarget)"
ApplicationSharedLibraries="@(_ApplicationSharedLibrary)"
DebugBuild="$(AndroidIncludeDebugSymbols)"
AndroidSdkBuildToolsPath="$(AndroidSdkBuildToolsPath)"
AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)"
/>
<ItemGroup>
<FileWrites Include="@(_ApplicationSharedLibrary)" />
Expand Down Expand Up @@ -2933,7 +2935,7 @@ because xbuild doesn't support framework reference assemblies.
Condition="'$(AotAssemblies)' == 'True'"
AndroidAotMode="$(AndroidAotMode)"
AndroidNdkDirectory="$(_AndroidNdkDirectory)"
ToolsDirectory="$(MonoAndroidBinDirectory)"
AndroidBinUtilsDirectory="$(AndroidBinUtilsDirectory)"
AndroidApiLevel="$(_AndroidApiLevel)"
ManifestFile="$(IntermediateOutputPath)android\AndroidManifest.xml"
SupportedAbis="@(_BuildTargetAbis)"
Expand Down

0 comments on commit 97f345a

Please sign in to comment.