[NativeAOT] Fix application linking with API level > 21 - #10812

Merged
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level
Feb 18, 2026
Merged

[NativeAOT] Fix application linking with API level > 21#10812
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level

Conversation

@grendello

@grendellogrendello commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Context: bef768d
Context: dotnet/runtime#124461

Follow up to bef768d which puts the non-mono builds API level in
several more locations throughout the source. This is necessary for
NativeAOT builds to correctly link as they must use the same API
level .NET for Android was built with. Failure to do so may result
in missing native symbols when linking.

NativeAOT builds now use full path to the linker (in our case clang++)
and pass the --target=${ARCH}-linux-android${API} argument to it, just
like the toolchain wrapper scripts in the NDK do. Without the parameter,
the lowest supported API level will be used (currently 21).

CopilotAI review requested due to automatic review settings February 13, 2026 12:14
@grendellogrendello mentioned this pull request Feb 13, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the .NET for Android NativeAOT build/link pipeline so that non-Mono (NativeAOT/CoreCLR) builds consistently use the same Android API level that the runtime pack was built with, avoiding missing native symbols at link time (especially when targeting API > 21).

Changes:

  • Add “non-mono” NDK API level placeholders and propagate them into generated MSBuild props/projitems.
  • Update NativeAOT linking to use the NDK’s clang++ via full path and pass an explicit --target=${ARCH}-linux-android${API} linker argument.
  • Split minimum-supported API metadata for arm64/x86_64 based on runtime flavor.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.inAdds non-mono API level properties and runtime-conditional minimum API items (currently with issues).
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targetsWires new placeholder replacements into Common.props generation.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targetsUses NDK clang++ full path and adds --target=... to linker args.
build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.csAdds new placeholder values for non-mono API levels when generating Ndk.projitems.
build-tools/scripts/Ndk.projitems.inIntroduces properties/metadata for non-mono API levels for arm64/x64.

Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadbuild-tools/scripts/Ndk.projitems.in Outdated

@jonathanpeppersjonathanpeppers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

@grendello

Copy link
Copy Markdown
ContributorAuthor

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

This is odd, it works fine locally. I'll investigate.

@grendello
grendelloforce-pushed the dev/grendel/naot-link-api-level branch from 72b35dc to 3381021CompareFebruary 16, 2026 10:28
@grendello

Copy link
Copy Markdown
ContributorAuthor

So the reason for NAOT tests failing on Windows was that the <Exec> task is confused by the mixture of Unix and Windows path separator chars in $(_NdkBinDir):

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". [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BindingCustomJavaApplicationClassNativeAOT\App\UnnamedProject.csproj]
The command "where /Q "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/bin/clang++"" exited with code 2.
where /Q "gcc"
"gcc" -fuse-ld=lld -Wl,--version

@grendello
grendello merged commit a4e565c into mainFeb 18, 2026
6 checks passed
@grendello
grendello deleted the dev/grendel/naot-link-api-level branch February 18, 2026 08:21
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Mar 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[NativeAOT] Fix application linking with API level > 21 - #10812

Merged
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level
Feb 18, 2026
Merged

[NativeAOT] Fix application linking with API level > 21#10812
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level

Conversation

@grendello

@grendellogrendello commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Context: bef768d
Context: dotnet/runtime#124461

Follow up to bef768d which puts the non-mono builds API level in
several more locations throughout the source. This is necessary for
NativeAOT builds to correctly link as they must use the same API
level .NET for Android was built with. Failure to do so may result
in missing native symbols when linking.

NativeAOT builds now use full path to the linker (in our case clang++)
and pass the --target=${ARCH}-linux-android${API} argument to it, just
like the toolchain wrapper scripts in the NDK do. Without the parameter,
the lowest supported API level will be used (currently 21).

CopilotAI review requested due to automatic review settings February 13, 2026 12:14
@grendellogrendello mentioned this pull request Feb 13, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the .NET for Android NativeAOT build/link pipeline so that non-Mono (NativeAOT/CoreCLR) builds consistently use the same Android API level that the runtime pack was built with, avoiding missing native symbols at link time (especially when targeting API > 21).

Changes:

  • Add “non-mono” NDK API level placeholders and propagate them into generated MSBuild props/projitems.
  • Update NativeAOT linking to use the NDK’s clang++ via full path and pass an explicit --target=${ARCH}-linux-android${API} linker argument.
  • Split minimum-supported API metadata for arm64/x86_64 based on runtime flavor.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.inAdds non-mono API level properties and runtime-conditional minimum API items (currently with issues).
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targetsWires new placeholder replacements into Common.props generation.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targetsUses NDK clang++ full path and adds --target=... to linker args.
build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.csAdds new placeholder values for non-mono API levels when generating Ndk.projitems.
build-tools/scripts/Ndk.projitems.inIntroduces properties/metadata for non-mono API levels for arm64/x64.

Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadbuild-tools/scripts/Ndk.projitems.in Outdated

@jonathanpeppersjonathanpeppers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

@grendello

Copy link
Copy Markdown
ContributorAuthor

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

This is odd, it works fine locally. I'll investigate.

@grendello
grendelloforce-pushed the dev/grendel/naot-link-api-level branch from 72b35dc to 3381021CompareFebruary 16, 2026 10:28
@grendello

Copy link
Copy Markdown
ContributorAuthor

So the reason for NAOT tests failing on Windows was that the <Exec> task is confused by the mixture of Unix and Windows path separator chars in $(_NdkBinDir):

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". [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BindingCustomJavaApplicationClassNativeAOT\App\UnnamedProject.csproj]
The command "where /Q "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/bin/clang++"" exited with code 2.
where /Q "gcc"
"gcc" -fuse-ld=lld -Wl,--version

@grendello
grendello merged commit a4e565c into mainFeb 18, 2026
6 checks passed
@grendello
grendello deleted the dev/grendel/naot-link-api-level branch February 18, 2026 08:21
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Mar 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[NativeAOT] Fix application linking with API level > 21 - #10812

Merged
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level
Feb 18, 2026
Merged

[NativeAOT] Fix application linking with API level > 21#10812
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level

Conversation

@grendello

@grendellogrendello commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Context: bef768d
Context: dotnet/runtime#124461

Follow up to bef768d which puts the non-mono builds API level in
several more locations throughout the source. This is necessary for
NativeAOT builds to correctly link as they must use the same API
level .NET for Android was built with. Failure to do so may result
in missing native symbols when linking.

NativeAOT builds now use full path to the linker (in our case clang++)
and pass the --target=${ARCH}-linux-android${API} argument to it, just
like the toolchain wrapper scripts in the NDK do. Without the parameter,
the lowest supported API level will be used (currently 21).

CopilotAI review requested due to automatic review settings February 13, 2026 12:14
@grendellogrendello mentioned this pull request Feb 13, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the .NET for Android NativeAOT build/link pipeline so that non-Mono (NativeAOT/CoreCLR) builds consistently use the same Android API level that the runtime pack was built with, avoiding missing native symbols at link time (especially when targeting API > 21).

Changes:

  • Add “non-mono” NDK API level placeholders and propagate them into generated MSBuild props/projitems.
  • Update NativeAOT linking to use the NDK’s clang++ via full path and pass an explicit --target=${ARCH}-linux-android${API} linker argument.
  • Split minimum-supported API metadata for arm64/x86_64 based on runtime flavor.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.inAdds non-mono API level properties and runtime-conditional minimum API items (currently with issues).
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targetsWires new placeholder replacements into Common.props generation.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targetsUses NDK clang++ full path and adds --target=... to linker args.
build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.csAdds new placeholder values for non-mono API levels when generating Ndk.projitems.
build-tools/scripts/Ndk.projitems.inIntroduces properties/metadata for non-mono API levels for arm64/x64.

Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadbuild-tools/scripts/Ndk.projitems.in Outdated

@jonathanpeppersjonathanpeppers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

@grendello

Copy link
Copy Markdown
ContributorAuthor

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

This is odd, it works fine locally. I'll investigate.

@grendello
grendelloforce-pushed the dev/grendel/naot-link-api-level branch from 72b35dc to 3381021CompareFebruary 16, 2026 10:28
@grendello

Copy link
Copy Markdown
ContributorAuthor

So the reason for NAOT tests failing on Windows was that the <Exec> task is confused by the mixture of Unix and Windows path separator chars in $(_NdkBinDir):

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". [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BindingCustomJavaApplicationClassNativeAOT\App\UnnamedProject.csproj]
The command "where /Q "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/bin/clang++"" exited with code 2.
where /Q "gcc"
"gcc" -fuse-ld=lld -Wl,--version

@grendello
grendello merged commit a4e565c into mainFeb 18, 2026
6 checks passed
@grendello
grendello deleted the dev/grendel/naot-link-api-level branch February 18, 2026 08:21
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Mar 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[NativeAOT] Fix application linking with API level > 21 - #10812

Merged
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level
Feb 18, 2026
Merged

[NativeAOT] Fix application linking with API level > 21#10812
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level

Conversation

@grendello

@grendellogrendello commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Context: bef768d
Context: dotnet/runtime#124461

Follow up to bef768d which puts the non-mono builds API level in
several more locations throughout the source. This is necessary for
NativeAOT builds to correctly link as they must use the same API
level .NET for Android was built with. Failure to do so may result
in missing native symbols when linking.

NativeAOT builds now use full path to the linker (in our case clang++)
and pass the --target=${ARCH}-linux-android${API} argument to it, just
like the toolchain wrapper scripts in the NDK do. Without the parameter,
the lowest supported API level will be used (currently 21).

CopilotAI review requested due to automatic review settings February 13, 2026 12:14
@grendellogrendello mentioned this pull request Feb 13, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the .NET for Android NativeAOT build/link pipeline so that non-Mono (NativeAOT/CoreCLR) builds consistently use the same Android API level that the runtime pack was built with, avoiding missing native symbols at link time (especially when targeting API > 21).

Changes:

  • Add “non-mono” NDK API level placeholders and propagate them into generated MSBuild props/projitems.
  • Update NativeAOT linking to use the NDK’s clang++ via full path and pass an explicit --target=${ARCH}-linux-android${API} linker argument.
  • Split minimum-supported API metadata for arm64/x86_64 based on runtime flavor.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.inAdds non-mono API level properties and runtime-conditional minimum API items (currently with issues).
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targetsWires new placeholder replacements into Common.props generation.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targetsUses NDK clang++ full path and adds --target=... to linker args.
build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.csAdds new placeholder values for non-mono API levels when generating Ndk.projitems.
build-tools/scripts/Ndk.projitems.inIntroduces properties/metadata for non-mono API levels for arm64/x64.

Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadbuild-tools/scripts/Ndk.projitems.in Outdated

@jonathanpeppersjonathanpeppers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

@grendello

Copy link
Copy Markdown
ContributorAuthor

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

This is odd, it works fine locally. I'll investigate.

@grendello
grendelloforce-pushed the dev/grendel/naot-link-api-level branch from 72b35dc to 3381021CompareFebruary 16, 2026 10:28
@grendello

Copy link
Copy Markdown
ContributorAuthor

So the reason for NAOT tests failing on Windows was that the <Exec> task is confused by the mixture of Unix and Windows path separator chars in $(_NdkBinDir):

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". [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BindingCustomJavaApplicationClassNativeAOT\App\UnnamedProject.csproj]
The command "where /Q "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/bin/clang++"" exited with code 2.
where /Q "gcc"
"gcc" -fuse-ld=lld -Wl,--version

@grendello
grendello merged commit a4e565c into mainFeb 18, 2026
6 checks passed
@grendello
grendello deleted the dev/grendel/naot-link-api-level branch February 18, 2026 08:21
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Mar 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[NativeAOT] Fix application linking with API level > 21 - #10812

Merged
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level
Feb 18, 2026
Merged

[NativeAOT] Fix application linking with API level > 21#10812
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level

Conversation

@grendello

@grendellogrendello commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Context: bef768d
Context: dotnet/runtime#124461

Follow up to bef768d which puts the non-mono builds API level in
several more locations throughout the source. This is necessary for
NativeAOT builds to correctly link as they must use the same API
level .NET for Android was built with. Failure to do so may result
in missing native symbols when linking.

NativeAOT builds now use full path to the linker (in our case clang++)
and pass the --target=${ARCH}-linux-android${API} argument to it, just
like the toolchain wrapper scripts in the NDK do. Without the parameter,
the lowest supported API level will be used (currently 21).

CopilotAI review requested due to automatic review settings February 13, 2026 12:14
@grendellogrendello mentioned this pull request Feb 13, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the .NET for Android NativeAOT build/link pipeline so that non-Mono (NativeAOT/CoreCLR) builds consistently use the same Android API level that the runtime pack was built with, avoiding missing native symbols at link time (especially when targeting API > 21).

Changes:

  • Add “non-mono” NDK API level placeholders and propagate them into generated MSBuild props/projitems.
  • Update NativeAOT linking to use the NDK’s clang++ via full path and pass an explicit --target=${ARCH}-linux-android${API} linker argument.
  • Split minimum-supported API metadata for arm64/x86_64 based on runtime flavor.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.inAdds non-mono API level properties and runtime-conditional minimum API items (currently with issues).
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targetsWires new placeholder replacements into Common.props generation.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targetsUses NDK clang++ full path and adds --target=... to linker args.
build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.csAdds new placeholder values for non-mono API levels when generating Ndk.projitems.
build-tools/scripts/Ndk.projitems.inIntroduces properties/metadata for non-mono API levels for arm64/x64.

Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadbuild-tools/scripts/Ndk.projitems.in Outdated

@jonathanpeppersjonathanpeppers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

@grendello

Copy link
Copy Markdown
ContributorAuthor

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

This is odd, it works fine locally. I'll investigate.

@grendello
grendelloforce-pushed the dev/grendel/naot-link-api-level branch from 72b35dc to 3381021CompareFebruary 16, 2026 10:28
@grendello

Copy link
Copy Markdown
ContributorAuthor

So the reason for NAOT tests failing on Windows was that the <Exec> task is confused by the mixture of Unix and Windows path separator chars in $(_NdkBinDir):

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". [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BindingCustomJavaApplicationClassNativeAOT\App\UnnamedProject.csproj]
The command "where /Q "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/bin/clang++"" exited with code 2.
where /Q "gcc"
"gcc" -fuse-ld=lld -Wl,--version

@grendello
grendello merged commit a4e565c into mainFeb 18, 2026
6 checks passed
@grendello
grendello deleted the dev/grendel/naot-link-api-level branch February 18, 2026 08:21
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Mar 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[NativeAOT] Fix application linking with API level > 21 - #10812

Merged
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level
Feb 18, 2026
Merged

[NativeAOT] Fix application linking with API level > 21#10812
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level

Conversation

@grendello

@grendellogrendello commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Context: bef768d
Context: dotnet/runtime#124461

Follow up to bef768d which puts the non-mono builds API level in
several more locations throughout the source. This is necessary for
NativeAOT builds to correctly link as they must use the same API
level .NET for Android was built with. Failure to do so may result
in missing native symbols when linking.

NativeAOT builds now use full path to the linker (in our case clang++)
and pass the --target=${ARCH}-linux-android${API} argument to it, just
like the toolchain wrapper scripts in the NDK do. Without the parameter,
the lowest supported API level will be used (currently 21).

CopilotAI review requested due to automatic review settings February 13, 2026 12:14
@grendellogrendello mentioned this pull request Feb 13, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the .NET for Android NativeAOT build/link pipeline so that non-Mono (NativeAOT/CoreCLR) builds consistently use the same Android API level that the runtime pack was built with, avoiding missing native symbols at link time (especially when targeting API > 21).

Changes:

  • Add “non-mono” NDK API level placeholders and propagate them into generated MSBuild props/projitems.
  • Update NativeAOT linking to use the NDK’s clang++ via full path and pass an explicit --target=${ARCH}-linux-android${API} linker argument.
  • Split minimum-supported API metadata for arm64/x86_64 based on runtime flavor.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.inAdds non-mono API level properties and runtime-conditional minimum API items (currently with issues).
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targetsWires new placeholder replacements into Common.props generation.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targetsUses NDK clang++ full path and adds --target=... to linker args.
build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.csAdds new placeholder values for non-mono API levels when generating Ndk.projitems.
build-tools/scripts/Ndk.projitems.inIntroduces properties/metadata for non-mono API levels for arm64/x64.

Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadbuild-tools/scripts/Ndk.projitems.in Outdated

@jonathanpeppersjonathanpeppers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

@grendello

Copy link
Copy Markdown
ContributorAuthor

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

This is odd, it works fine locally. I'll investigate.

@grendello
grendelloforce-pushed the dev/grendel/naot-link-api-level branch from 72b35dc to 3381021CompareFebruary 16, 2026 10:28
@grendello

Copy link
Copy Markdown
ContributorAuthor

So the reason for NAOT tests failing on Windows was that the <Exec> task is confused by the mixture of Unix and Windows path separator chars in $(_NdkBinDir):

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". [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BindingCustomJavaApplicationClassNativeAOT\App\UnnamedProject.csproj]
The command "where /Q "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/bin/clang++"" exited with code 2.
where /Q "gcc"
"gcc" -fuse-ld=lld -Wl,--version

@grendello
grendello merged commit a4e565c into mainFeb 18, 2026
6 checks passed
@grendello
grendello deleted the dev/grendel/naot-link-api-level branch February 18, 2026 08:21
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Mar 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[NativeAOT] Fix application linking with API level > 21 - #10812

Merged
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level
Feb 18, 2026
Merged

[NativeAOT] Fix application linking with API level > 21#10812
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level

Conversation

@grendello

@grendellogrendello commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Context: bef768d
Context: dotnet/runtime#124461

Follow up to bef768d which puts the non-mono builds API level in
several more locations throughout the source. This is necessary for
NativeAOT builds to correctly link as they must use the same API
level .NET for Android was built with. Failure to do so may result
in missing native symbols when linking.

NativeAOT builds now use full path to the linker (in our case clang++)
and pass the --target=${ARCH}-linux-android${API} argument to it, just
like the toolchain wrapper scripts in the NDK do. Without the parameter,
the lowest supported API level will be used (currently 21).

CopilotAI review requested due to automatic review settings February 13, 2026 12:14
@grendellogrendello mentioned this pull request Feb 13, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the .NET for Android NativeAOT build/link pipeline so that non-Mono (NativeAOT/CoreCLR) builds consistently use the same Android API level that the runtime pack was built with, avoiding missing native symbols at link time (especially when targeting API > 21).

Changes:

  • Add “non-mono” NDK API level placeholders and propagate them into generated MSBuild props/projitems.
  • Update NativeAOT linking to use the NDK’s clang++ via full path and pass an explicit --target=${ARCH}-linux-android${API} linker argument.
  • Split minimum-supported API metadata for arm64/x86_64 based on runtime flavor.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.inAdds non-mono API level properties and runtime-conditional minimum API items (currently with issues).
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targetsWires new placeholder replacements into Common.props generation.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targetsUses NDK clang++ full path and adds --target=... to linker args.
build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.csAdds new placeholder values for non-mono API levels when generating Ndk.projitems.
build-tools/scripts/Ndk.projitems.inIntroduces properties/metadata for non-mono API levels for arm64/x64.

Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadbuild-tools/scripts/Ndk.projitems.in Outdated

@jonathanpeppersjonathanpeppers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

@grendello

Copy link
Copy Markdown
ContributorAuthor

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

This is odd, it works fine locally. I'll investigate.

@grendello
grendelloforce-pushed the dev/grendel/naot-link-api-level branch from 72b35dc to 3381021CompareFebruary 16, 2026 10:28
@grendello

Copy link
Copy Markdown
ContributorAuthor

So the reason for NAOT tests failing on Windows was that the <Exec> task is confused by the mixture of Unix and Windows path separator chars in $(_NdkBinDir):

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". [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BindingCustomJavaApplicationClassNativeAOT\App\UnnamedProject.csproj]
The command "where /Q "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/bin/clang++"" exited with code 2.
where /Q "gcc"
"gcc" -fuse-ld=lld -Wl,--version

@grendello
grendello merged commit a4e565c into mainFeb 18, 2026
6 checks passed
@grendello
grendello deleted the dev/grendel/naot-link-api-level branch February 18, 2026 08:21
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Mar 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[NativeAOT] Fix application linking with API level > 21 - #10812

Merged
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level
Feb 18, 2026
Merged

[NativeAOT] Fix application linking with API level > 21#10812
grendello merged 4 commits into
mainfrom
dev/grendel/naot-link-api-level

Conversation

@grendello

@grendellogrendello commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Context: bef768d
Context: dotnet/runtime#124461

Follow up to bef768d which puts the non-mono builds API level in
several more locations throughout the source. This is necessary for
NativeAOT builds to correctly link as they must use the same API
level .NET for Android was built with. Failure to do so may result
in missing native symbols when linking.

NativeAOT builds now use full path to the linker (in our case clang++)
and pass the --target=${ARCH}-linux-android${API} argument to it, just
like the toolchain wrapper scripts in the NDK do. Without the parameter,
the lowest supported API level will be used (currently 21).

CopilotAI review requested due to automatic review settings February 13, 2026 12:14
@grendellogrendello mentioned this pull request Feb 13, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the .NET for Android NativeAOT build/link pipeline so that non-Mono (NativeAOT/CoreCLR) builds consistently use the same Android API level that the runtime pack was built with, avoiding missing native symbols at link time (especially when targeting API > 21).

Changes:

  • Add “non-mono” NDK API level placeholders and propagate them into generated MSBuild props/projitems.
  • Update NativeAOT linking to use the NDK’s clang++ via full path and pass an explicit --target=${ARCH}-linux-android${API} linker argument.
  • Split minimum-supported API metadata for arm64/x86_64 based on runtime flavor.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.inAdds non-mono API level properties and runtime-conditional minimum API items (currently with issues).
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targetsWires new placeholder replacements into Common.props generation.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targetsUses NDK clang++ full path and adds --target=... to linker args.
build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.csAdds new placeholder values for non-mono API levels when generating Ndk.projitems.
build-tools/scripts/Ndk.projitems.inIntroduces properties/metadata for non-mono API levels for arm64/x64.

Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadsrc/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in Outdated
Comment threadbuild-tools/scripts/Ndk.projitems.in Outdated

@jonathanpeppersjonathanpeppers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

@grendello

Copy link
Copy Markdown
ContributorAuthor

There are some errors building NativeAOT projects like:

gcc : error : unrecognized command-line option '--target=x86_64-linux-android21' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
gcc : error : unrecognized command-line option '--target=x86_64-linux-android24' [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]
C:\Users\cloudtest\.nuget\packages\microsoft.dotnet.ilcompiler\11.0.0-preview.1.26076.102\build\Microsoft.NETCore.Native.targets(391,5): error MSB3073: The command ""gcc" "obj\Release\android-x64\native\UnnamedProject.o" -o "bin\Release\android-x64\native\UnnamedProject.so" -Wl,--version-script="obj\Release\android-x64\native\UnnamedProject.exports" -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Globalization.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.IO.Compression.Native.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libSystem.Security.Cryptography.Native.Android.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbootstrapperdll.o C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.WorkstationGC.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libeventpipe-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libRuntime.VxsortDisabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libstandalonegc-disabled.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libaotminipal.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlienc.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlidec.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libbrotlicommon.a C:\Users\cloudtest\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.android-x64\11.0.0-preview.1.26076.102/runtimes/android-x64/\native\libzstd.a --target=x86_64-linux-android21 -g -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 --target=x86_64-linux-android24 "-Wl,-soname,libUnnamedProject.so" -Wl,--error-unresolved-symbols -Wl,--no-undefined "C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Runtime.NativeAOT.36.android-x64\36.1.99-ci.dev-grendel-naot-link-api-level.147\runtimes\android-x64\native\libnaot-android.release-static-release.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_static.a" "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++abi.a" obj\Release\android-x64\android\jni_init_funcs.x86_64.o obj\Release\android-x64\android\environment.x86_64.o -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BuildApplicationAndCleanTrueapkNativeAOT\UnnamedProject.csproj]

This is odd, it works fine locally. I'll investigate.

@grendello
grendelloforce-pushed the dev/grendel/naot-link-api-level branch from 72b35dc to 3381021CompareFebruary 16, 2026 10:28
@grendello

Copy link
Copy Markdown
ContributorAuthor

So the reason for NAOT tests failing on Windows was that the <Exec> task is confused by the mixture of Unix and Windows path separator chars in $(_NdkBinDir):

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". [C:\a\_work\1\a\TestRelease\02-13_14.27.07\temp\BindingCustomJavaApplicationClassNativeAOT\App\UnnamedProject.csproj]
The command "where /Q "C:\Android\android-sdk\ndk\29.0.14206865\toolchains/llvm/prebuilt/windows-x86_64/bin/clang++"" exited with code 2.
where /Q "gcc"
"gcc" -fuse-ld=lld -Wl,--version

@grendello
grendello merged commit a4e565c into mainFeb 18, 2026
6 checks passed
@grendello
grendello deleted the dev/grendel/naot-link-api-level branch February 18, 2026 08:21
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Mar 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@grendello@jonathanpeppers