From ed0d8a08fa5852534b24006fbdaa7aa6910bcbc8 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 28 Jan 2025 08:52:58 -0600 Subject: [PATCH] [nativeaot] fix project builds on Windows (#9710) In 2fa79549, 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 `` 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 --- .../Microsoft.Android.Sdk.NativeAOT.targets | 14 ++++++---- .../Tasks/SetNdkPathForIlc.cs | 27 +++++++++++++++++++ .../Xamarin.Android.Build.Tests/BuildTest2.cs | 6 ----- 3 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/SetNdkPathForIlc.cs diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets index de6970db4d0..685e42403f5 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets @@ -7,9 +7,13 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. --> + + <_AndroidRuntimePackRuntime>NativeAOT + + true @@ -32,16 +36,14 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. <_NdkAbi Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">aarch64 <_NdkAbi Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">x86_64 - <_NdkSysrootAbi>$(_NdkAbi)-linux-android - <_NdkClangPrefix>$(_NdkAbi)-linux-android21- + <_NdkSysrootAbi>$(_NdkAbi)-linux-android <_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('windows')) ">windows-x86_64 <_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('osx')) ">darwin-x86_64 <_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('linux')) ">linux-x86_64 <_NdkSysrootDir>$(_AndroidNdkDirectory)toolchains/llvm/prebuilt/$(_NdkPrebuiltAbi)/sysroot/usr/lib/$(_NdkSysrootAbi)/ <_NdkBinDir>$(_AndroidNdkDirectory)toolchains/llvm/prebuilt/$(_NdkPrebuiltAbi)/bin/ - $(_NdkBinDir)$(_NdkClangPrefix)clang++ - $(CppCompilerAndLinker) - $(_NdkBinDir)llvm-objcopy + clang++ + llvm-objcopy true @@ -66,6 +68,8 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. lld + + diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/SetNdkPathForIlc.cs b/src/Xamarin.Android.Build.Tasks/Tasks/SetNdkPathForIlc.cs new file mode 100644 index 00000000000..d301d8b12cb --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tasks/SetNdkPathForIlc.cs @@ -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; + +/// +/// NativeAOT's compiler (ILC) expects to find tooling in $PATH +/// +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; + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index 59f618eb39c..539142c14b8 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -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,