Skip to content

Commit

Permalink
[nativeaot] fix project builds on Windows (#9710)
Browse files Browse the repository at this point in the history
In 2fa7954, we got Android projects *building* for NativeAOT.
However, this didn't work at all on Windows.

Reviewing how NativeAOT's MSBuild targets are setup, they expect
various tooling to be available in `%PATH%`.

To fix this:

* Create a new `<SetNdkPathForIlc/>` MSBuild task.

* That simply sets the Android NDK "bin" directory to `%PATH%`.

NativeAOT apps now successfully build (and run) on Windows. I also
updated an integration test to verify this.

Unfortunately, we still have to set `$(DisableUnsupportedError)` or we
will get the message:

    D:\.nuget\packages\microsoft.dotnet.ilcompiler\10.0.0-alpha.1.25067.10\build\Microsoft.NETCore.Native.Publish.targets(61,5):
    error : Cross-OS native compilation is not supported. Please use the appropriate OS-specific target.

A future change might be needed here, or it might be fine to for the
Android workload to set this property:

* https://github.com/dotnet/runtime/blob/ea4a404ef8890f265780f798e7668d4710259e03/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets#L61-L62
  • Loading branch information
jonathanpeppers authored Jan 28, 2025
1 parent f4e405e commit ed0d8a0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
-->
<Project>

<UsingTask TaskName="Xamarin.Android.Tasks.SetNdkPathForIlc" AssemblyFile="$(_XamarinAndroidBuildTasksAssembly)" />

<!-- Default property values for NativeAOT -->
<PropertyGroup>
<_AndroidRuntimePackRuntime>NativeAOT</_AndroidRuntimePackRuntime>
<!-- NativeAOT's targets currently gives an error about cross-compilation -->
<DisableUnsupportedError Condition=" $([MSBuild]::IsOSPlatform('windows')) and '$(DisableUnsupportedError)' == '' ">true</DisableUnsupportedError>
</PropertyGroup>

<!-- Make IlcCompile depend on the trimmer -->
Expand All @@ -32,16 +36,14 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
<PropertyGroup>
<_NdkAbi Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">aarch64</_NdkAbi>
<_NdkAbi Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">x86_64</_NdkAbi>
<_NdkSysrootAbi>$(_NdkAbi)-linux-android</_NdkSysrootAbi>
<_NdkClangPrefix>$(_NdkAbi)-linux-android21-</_NdkClangPrefix>
<_NdkSysrootAbi>$(_NdkAbi)-linux-android</_NdkSysrootAbi>
<_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('windows')) ">windows-x86_64</_NdkPrebuiltAbi>
<_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('osx')) ">darwin-x86_64</_NdkPrebuiltAbi>
<_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('linux')) ">linux-x86_64</_NdkPrebuiltAbi>
<_NdkSysrootDir>$(_AndroidNdkDirectory)toolchains/llvm/prebuilt/$(_NdkPrebuiltAbi)/sysroot/usr/lib/$(_NdkSysrootAbi)/</_NdkSysrootDir>
<_NdkBinDir>$(_AndroidNdkDirectory)toolchains/llvm/prebuilt/$(_NdkPrebuiltAbi)/bin/</_NdkBinDir>
<CppCompilerAndLinker>$(_NdkBinDir)$(_NdkClangPrefix)clang++</CppCompilerAndLinker>
<CppLinker>$(CppCompilerAndLinker)</CppLinker>
<ObjCopyName>$(_NdkBinDir)llvm-objcopy</ObjCopyName>
<CppCompilerAndLinker>clang++</CppCompilerAndLinker>
<ObjCopyName>llvm-objcopy</ObjCopyName>

<!-- Example settings from: https://github.com/xamarin/xamarin-macios/blob/c43d4ea40bc777969e3b158cf46446df292d8449/dotnet/targets/Xamarin.Shared.Sdk.targets#L541-L550 -->
<RunILLink>true</RunILLink>
Expand All @@ -66,6 +68,8 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
<!-- HACK: prevents: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "__start___modules" -->
<LinkerFlavor Condition=" '$(LinkerFlavor)' == '' ">lld</LinkerFlavor>
</PropertyGroup>

<SetNdkPathForIlc NdkBinDirectory="$(_NdkBinDir)" />
</Target>

<Target Name="_AndroidComputeIlcCompileInputs">
Expand Down
27 changes: 27 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Tasks/SetNdkPathForIlc.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.IO;
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Xamarin.Android.Tasks;

/// <summary>
/// NativeAOT's compiler (ILC) expects to find tooling in $PATH
/// </summary>
public class SetNdkPathForIlc : AndroidTask
{
public override string TaskPrefix => "SILC";

[Required]
public string NdkBinDirectory { get; set; } = "";

public override bool RunTask ()
{
var ndkbin = Path.GetFullPath (NdkBinDirectory);
var path = $"{ndkbin}{Path.PathSeparator}{Environment.GetEnvironmentVariable ("PATH")}";
Log.LogDebugMessage ($"Setting $PATH to: {path}");
Environment.SetEnvironmentVariable ("PATH", path);
return !Log.HasLoggedErrors;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,6 @@ public void BuildBasicApplication ([Values (true, false)] bool isRelease, [Value
[Test]
public void NativeAOT ()
{
if (IsWindows) {
// Microsoft.NETCore.Native.Publish.targets(61,5): Cross-OS native compilation is not supported.
// Set $(DisableUnsupportedError)=true, Microsoft.NETCore.Native.Unix.targets(296,5): error : Platform linker ('C:\Android\android-sdk\ndk\26.3.11579264\toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang++' or 'gcc') not found in PATH. Ensure you have all the required prerequisites documented at https://aka.ms/nativeaot-prerequisites.
Assert.Ignore ("This test is not valid on Windows.");
}

var proj = new XamarinAndroidApplicationProject {
ProjectName = "Hello",
IsRelease = true,
Expand Down

0 comments on commit ed0d8a0

Please sign in to comment.