From 0b49070da0f0ea46e35730bda9ea9a476870e437 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 13 Feb 2026 13:01:20 +0100 Subject: [PATCH 1/4] Fix linking NAOT apps with API level > 21 --- build-tools/scripts/Ndk.projitems.in | 4 ++++ .../xaprepare/xaprepare/Steps/Step_GenerateFiles.cs | 2 ++ .../targets/Microsoft.Android.Sdk.NativeAOT.targets | 12 +++++++++++- .../Xamarin.Android.Build.Tasks.targets | 2 ++ .../Xamarin.Android.Common.props.in | 13 +++++++++++-- 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/build-tools/scripts/Ndk.projitems.in b/build-tools/scripts/Ndk.projitems.in index e767b8c460f..c00022546fe 100644 --- a/build-tools/scripts/Ndk.projitems.in +++ b/build-tools/scripts/Ndk.projitems.in @@ -11,6 +11,8 @@ @NDK_X86_API_NET@ @NDK_X86_64_API@ @NDK_X86_64_API_NET@ + @NDK_ARM64_V8A_API_NON_MONO@ + @NDK_X86_64_API_NON_MONO@ @@ -30,6 +32,7 @@ Condition=" $(AndroidSupportedTargetJitAbisForConditionalChecks.Contains (':arm64-v8a:')) "> $(AndroidNdkApiLevel_ArmV8a) $(AndroidNdkApiLevel_Arm64) + $(AndroidNdkAPiLevelNonMono_Arm64) android-arm64 True True @@ -52,6 +55,7 @@ Condition=" $(AndroidSupportedTargetJitAbisForConditionalChecks.Contains (':x86_64:')) "> $(AndroidNdkApiLevel_X86_64) $(AndroidNdkApiLevel_X64) + $(AndroidNdkAPiLevelNonMono_X64) android-x64 True True diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs b/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs index 332dc162de7..41f04b00258 100644 --- a/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs +++ b/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs @@ -255,6 +255,8 @@ GeneratedFile Get_Ndk_projitems (Context context) { "@NDK_X86_API_NET@", BuildAndroidPlatforms.NdkMinimumAPI.ToString () }, { "@NDK_X86_64_API@", BuildAndroidPlatforms.NdkMinimumAPI.ToString () }, { "@NDK_X86_64_API_NET@", BuildAndroidPlatforms.NdkMinimumAPI.ToString () }, + { "@NDK_ARM64_V8A_API_NON_MONO@", BuildAndroidPlatforms.NdkMinimumNonMonoAPI }, + { "@NDK_X86_64_API_NON_MONO@", BuildAndroidPlatforms.NdkMinimumNonMonoAPI }, }; return new GeneratedPlaceholdersFile ( 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 8fcdee6c961..f3a165b2325 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 @@ -72,7 +72,8 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. <_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/ - clang++ + $(_NdkBinDir)clang++ + $(_NdkBinDir)clang++ llvm-objcopy @@ -97,8 +98,17 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. $(_OriginalSuppressTrimAnalysisWarnings) + <_NDKApiLevel Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">$(AndroidNdkApiLevel_Arm64) + <_NDKArch Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">aarch64 + <_NDKApiLevel Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">$(AndroidNdkAPiLevel_X64) + <_NDKArch Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">x86_64 + + diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets index bdd02019827..56a342bcdef 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets @@ -150,8 +150,10 @@ <_XACommonPropsReplacement Include="@NDK_PKG_REVISION@=26.3.11579264" /> <_XACommonPropsReplacement Include="@NDK_ARM64_V8A_API@=$(AndroidNdkApiLevel_ArmV8a)" /> + <_XACommonPropsReplacement Include="@NDK_ARM64_V8A_API_NON_MONO@=$(AndroidNdkAPiLevelNonMono_Arm64)" /> <_XACommonPropsReplacement Include="@NDK_ARMEABI_V7_API@=$(AndroidNdkApiLevel_ArmV7a)" /> <_XACommonPropsReplacement Include="@NDK_X86_64_API@=$(AndroidNdkApiLevel_X86_64)" /> + <_XACommonPropsReplacement Include="@NDK_X86_64_API_NON_MONO@=$(AndroidNdkAPiLevelNonMono_X64)" /> <_XACommonPropsReplacement Include="@NDK_X86_API@=$(AndroidNdkApiLevel_X86)" /> <_XACommonPropsReplacement Include="@PACKAGE_VERSION_BUILD@=$(XAVersionCommitCount)" /> <_XACommonPropsReplacement Include="@PACKAGE_VERSION@=$(ProductVersion)" /> diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in index 559599e9ec9..6f3e9f58235 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in @@ -33,19 +33,28 @@ true + + @NDK_ARM64_V8A_API_NON_MONO@ + @NDK_X86_64_API_NON_MONO@ @NDK_ARMEABI_V7_API@ - + @NDK_ARM64_V8A_API@ + + @NDK_ARM64_V8A_API_NON_MONO@ + @NDK_X86_API@ - + @NDK_X86_64_API@ + + @NDK_X86_64_API_NON_MONO@ + From 8592c817635fb644be29253a6c5ce917293c2ad7 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 13 Feb 2026 13:59:01 +0100 Subject: [PATCH 2/4] Address feedback --- build-tools/scripts/Ndk.projitems.in | 8 ++++---- .../Xamarin.Android.Build.Tasks.targets | 4 ++-- .../Xamarin.Android.Common.props.in | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build-tools/scripts/Ndk.projitems.in b/build-tools/scripts/Ndk.projitems.in index c00022546fe..fbc98d84a4b 100644 --- a/build-tools/scripts/Ndk.projitems.in +++ b/build-tools/scripts/Ndk.projitems.in @@ -11,8 +11,8 @@ @NDK_X86_API_NET@ @NDK_X86_64_API@ @NDK_X86_64_API_NET@ - @NDK_ARM64_V8A_API_NON_MONO@ - @NDK_X86_64_API_NON_MONO@ + @NDK_ARM64_V8A_API_NON_MONO@ + @NDK_X86_64_API_NON_MONO@ @@ -32,7 +32,7 @@ Condition=" $(AndroidSupportedTargetJitAbisForConditionalChecks.Contains (':arm64-v8a:')) "> $(AndroidNdkApiLevel_ArmV8a) $(AndroidNdkApiLevel_Arm64) - $(AndroidNdkAPiLevelNonMono_Arm64) + $(AndroidNdkApiLevelNonMono_Arm64) android-arm64 True True @@ -55,7 +55,7 @@ Condition=" $(AndroidSupportedTargetJitAbisForConditionalChecks.Contains (':x86_64:')) "> $(AndroidNdkApiLevel_X86_64) $(AndroidNdkApiLevel_X64) - $(AndroidNdkAPiLevelNonMono_X64) + $(AndroidNdkApiLevelNonMono_X64) android-x64 True True diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets index 56a342bcdef..d748d54138d 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets @@ -150,10 +150,10 @@ <_XACommonPropsReplacement Include="@NDK_PKG_REVISION@=26.3.11579264" /> <_XACommonPropsReplacement Include="@NDK_ARM64_V8A_API@=$(AndroidNdkApiLevel_ArmV8a)" /> - <_XACommonPropsReplacement Include="@NDK_ARM64_V8A_API_NON_MONO@=$(AndroidNdkAPiLevelNonMono_Arm64)" /> + <_XACommonPropsReplacement Include="@NDK_ARM64_V8A_API_NON_MONO@=$(AndroidNdkApiLevelNonMono_Arm64)" /> <_XACommonPropsReplacement Include="@NDK_ARMEABI_V7_API@=$(AndroidNdkApiLevel_ArmV7a)" /> <_XACommonPropsReplacement Include="@NDK_X86_64_API@=$(AndroidNdkApiLevel_X86_64)" /> - <_XACommonPropsReplacement Include="@NDK_X86_64_API_NON_MONO@=$(AndroidNdkAPiLevelNonMono_X64)" /> + <_XACommonPropsReplacement Include="@NDK_X86_64_API_NON_MONO@=$(AndroidNdkApiLevelNonMono_X64)" /> <_XACommonPropsReplacement Include="@NDK_X86_API@=$(AndroidNdkApiLevel_X86)" /> <_XACommonPropsReplacement Include="@PACKAGE_VERSION_BUILD@=$(XAVersionCommitCount)" /> <_XACommonPropsReplacement Include="@PACKAGE_VERSION@=$(ProductVersion)" /> diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in index 6f3e9f58235..02589ee9384 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in @@ -35,25 +35,25 @@ true @NDK_ARM64_V8A_API_NON_MONO@ - @NDK_X86_64_API_NON_MONO@ + @NDK_X86_64_API_NON_MONO@ @NDK_ARMEABI_V7_API@ - + @NDK_ARM64_V8A_API@ - + @NDK_ARM64_V8A_API_NON_MONO@ @NDK_X86_API@ - + @NDK_X86_64_API@ - + @NDK_X86_64_API_NON_MONO@ From 33810213a699687acbc2a5dfce3dd17cbb0445a3 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 16 Feb 2026 11:27:48 +0100 Subject: [PATCH 3/4] Fix NAOT builds on Windows --- .../Microsoft.Android.Sdk.NativeAOT.targets | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) 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 f3a165b2325..0a80eb658f2 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 @@ -66,14 +66,39 @@ 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 + <_NDKApiLevel Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">$(AndroidNdkApiLevel_Arm64) + <_NDKApiLevel Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">$(AndroidNdkAPiLevel_X64) <_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 + + + <_NdkWrapperScriptExt Condition=" $([MSBuild]::IsOSPlatform('windows')) ">.cmd <_NdkSysrootDir>$(_AndroidNdkDirectory)toolchains/llvm/prebuilt/$(_NdkPrebuiltAbi)/sysroot/usr/lib/$(_NdkSysrootAbi)/ <_NdkBinDir>$(_AndroidNdkDirectory)toolchains/llvm/prebuilt/$(_NdkPrebuiltAbi)/bin/ - $(_NdkBinDir)clang++ - $(_NdkBinDir)clang++ + + + $(_NdkAbi)-linux-android$(_NDKApiLevel)-clang$(_NdkWrapperScriptExt) + $(_NdkAbi)-linux-android$(_NDKApiLevel)-clang$(_NdkWrapperScriptExt) llvm-objcopy @@ -98,17 +123,8 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. $(_OriginalSuppressTrimAnalysisWarnings) - <_NDKApiLevel Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">$(AndroidNdkApiLevel_Arm64) - <_NDKArch Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">aarch64 - <_NDKApiLevel Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">$(AndroidNdkAPiLevel_X64) - <_NDKArch Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">x86_64 - - From 37ff01301fe27d735529c026abc041963786e62d Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 16 Feb 2026 11:33:04 +0100 Subject: [PATCH 4/4] Update comments --- .../targets/Microsoft.Android.Sdk.NativeAOT.targets | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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 0a80eb658f2..13f050da1b4 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 @@ -91,11 +91,18 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. confused by the forward slash in the path (even though it's a valid path separator character on Windows) and signal the following error: - EXEC : error : Invalid pattern is specified in "path:pattern". + SetupOSSpecificProps: + where /Q "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/bin/clang++" + 1>EXEC : error : Invalid pattern is specified in "path:pattern". + The command "where /Q "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/bin/clang++"" exited with code 2. This could be fixed by making sure $(_NdkBinDir) path is fixed-up to use the canonical form of path separation for the host OS, but it's simpler to just use the NDK-specific compiler/linker wrapper script name. + + Also, do NOT use `clang++` here because it will link the dynamic libc++ library into the + application. If, for some reason, `clang++` has to be used, `` need to be + added to pass `-nostdlib` to it. --> $(_NdkAbi)-linux-android$(_NDKApiLevel)-clang$(_NdkWrapperScriptExt) $(_NdkAbi)-linux-android$(_NDKApiLevel)-clang$(_NdkWrapperScriptExt)