Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Link native shared libraries with 16k page alignment #104577

Merged
merged 6 commits into from
Jul 16, 2024

Conversation

grendello
Copy link
Contributor

Fixes: #103360
Context: https://developer.android.com/guide/practices/page-sizes
Context: https://github.com/android/ndk/wiki/Changelog-r27#announcements

Sometime next year Google will start requiring that all the .so libraries included
in applications submitted to the Play Store to be aligned to 16k page boundary (as
opposed to the current one of 4k).

Make changes to cmake scripts used to build both the BCL native libraries and the
MonoVM so that the resulting shared libraries have the correct alignment.

src/mono/CMakeLists.txt Outdated Show resolved Hide resolved
@jkotas
Copy link
Member

jkotas commented Jul 9, 2024

Do we need the same fix for native aot too? https://github.com/dotnet/runtime/blob/main/src/coreclr/nativeaot/docs/android-bionic.md

@grendello grendello force-pushed the dev/grendel/android-16k-alignment branch from 74938a2 to 11843c0 Compare July 9, 2024 09:04
@grendello
Copy link
Contributor Author

Do we need the same fix for native aot too? https://github.com/dotnet/runtime/blob/main/src/coreclr/nativeaot/docs/android-bionic.md

If NativeAOT binaries will be shipped to the Play Store, then yes. With MonoAOT it's not necessary to make changes here, .NET for Android build process takes care of that.

@ivanpovazan
Copy link
Member

@grendello

.NET for Android build process takes care of that

Could you explain this in more details?

@grendello
Copy link
Contributor Author

grendello commented Jul 9, 2024

@grendello

.NET for Android build process takes care of that

Could you explain this in more details?

Sure, it's quite simple really. MonoAOT is used via an MSBuild task, which is a front to the "old" Mono AOT interface, described in the Mono manpage (quoting just portions of it):

       --aot, --aot[=options]
              This option is used to precompile the CIL code in the specified assembly to native code.  The generated code is stored in a file with the extension .so.  This file will be automatically picked up by the runtime when the as‐
              sembly  is executed.  Ahead-of-Time compilation is most useful if you use it in combination with the -O=all,-shared flag which enables all of the optimizations in the code generator to be performed.  Some of those optimiza‐
              tions are not practical for Just-in-Time compilation since they might be very time consuming.  Unlike the .NET Framework, Ahead-of-Time compilation will not generate domain independent code: it generates the same code  that
              the  Just-in-Time  compiler  would  produce.   Since most applications use a single domain, this is fine.   If you want to optimize the generated code for use in multi-domain applications, consider using the -O=shared flag.
              This pre-compiles the methods, but the original assembly is still required to execute as this one contains the metadata and exception information which is not available on the generated file.  When  precompiling  code,  you
              might  want  to  compile with all optimizations (-O=all).  Pre-compiled code is position independent code.  Precompilation is just a mechanism to reduce startup time, increase code sharing across multiple mono processes and
              avoid just-in-time compilation program startup costs.  The original assembly must still be present, as the metadata is contained there.  AOT code typically can not be moved from one computer to another  (CPU-specific  opti‐
              mizations  that  are  detected  at runtime) so you should not try to move the pre-generated assemblies or package the pre-generated assemblies for deployment.  A few options are available as a parameter to the --aot command
              line option.   The options are separated by commas, and more than one can be specified:

              asmonly
                     Instructs the AOT compiler to output assembly code instead of an object file.

              ld-flags
                     Additional flags to pass to the C linker (if the current AOT mode calls for invoking it).

There are a lot of arguments, but what's relevant to us here is the ld-flags one. .NET for Android has this code which is used to gather flags to pass to the AOT compiler:

https://github.com/dotnet/android/blob/35f41dcc7cf5eb65dc12d7c0a3421e67c2bdb6d6/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs#L254-L329

The code that sets the alignment is still in a PR that's not yet merged, so you won't see it in the above code fragment.

The relevant MSBuild target in .NET for Android: https://github.com/dotnet/android/blob/35f41dcc7cf5eb65dc12d7c0a3421e67c2bdb6d6/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Aot.targets#L74-L175

@ivanpovazan
Copy link
Member

ivanpovazan commented Jul 9, 2024

I see, thanks. I was asking this because we have a library mode support for mobile (when users do not target net9.0-android, but instead target net9.0 and use android as the runtime identifier - ref).
In that case SDK for Android is not pulled in.
/cc: @steveisok

I think the ld-flags should be updated here:

buildOptions.LinkerArguments.Add($"--soname={libraryName}");

@grendello
Copy link
Contributor Author

@ivanpovazan I added the flag to library builder, but is there a way to tell which architecture is being targeted? It's important not only in this case, but also in cases when some architecture requires some special flags (e.g. aarch64 requires adding --fix-cortex-a53-843419 to args)

src/mono/CMakeLists.txt Outdated Show resolved Hide resolved
src/tasks/LibraryBuilder/LibraryBuilder.cs Outdated Show resolved Hide resolved
@akoeplinger
Copy link
Member

akoeplinger commented Jul 11, 2024

@grendello for the arch check you can use the RuntimeIdentifier property in LibraryBuilder.cs

grendello and others added 6 commits July 16, 2024 07:17
Fixes: dotnet#103360
Context: https://developer.android.com/guide/practices/page-sizes
Context: https://github.com/android/ndk/wiki/Changelog-r27#announcements

Sometime next year Google will start requiring that all the `.so`
libraries included in applications submitted to the Play Store to be
aligned to 16k page boundary (as opposed to the current one of 4k).

Make changes to cmake scripts used to build both the BCL native
libraries and the MonoVM so that the resulting shared libraries have the
correct alignment.
…e.Unix.targets

Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
@akoeplinger
Copy link
Member

/ba-g failures are on non-Android platforms and are not related.

@akoeplinger akoeplinger merged commit 8e6df8d into dotnet:main Jul 16, 2024
152 of 157 checks passed
@grendello grendello deleted the dev/grendel/android-16k-alignment branch July 16, 2024 15:19
@github-actions github-actions bot locked and limited conversation to collaborators Aug 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Build-mono community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Android] Runtime/BCL native libs need support for devices with 16k memory pages (arm64 and x64)
6 participants