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

Beginnings of native Android build #110471

Open
wants to merge 34 commits into
base: main
Choose a base branch
from

Conversation

grendello
Copy link
Contributor

No description provided.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Dec 6, 2024
Copy link
Contributor

Tagging subscribers to 'arch-android': @vitek-karas, @simonrozsival, @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.

@grendello grendello force-pushed the dev/grendel/android-build-with-ndk branch from c25fbd9 to 3d9da10 Compare December 6, 2024 20:43
…stem.Security.Cryptography.Native.Android. It will incorrectly try to install in the coreclr build
@@ -80,7 +80,7 @@ build_native()

if [[ "$targetOS" == android || "$targetOS" == linux-bionic ]]; then
# Keep in sync with $(AndroidApiLevelMin) in Directory.Build.props in the repository rooot
local ANDROID_API_LEVEL=28
local ANDROID_API_LEVEL=29
Copy link
Member

Choose a reason for hiding this comment

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

@grendello has mentioned in #110470 that even API level 28 is unfortunate and that we will want to support older API level, e.g. the originally used level 21.
So I wonder if moving to the level 29 is a good thing.

Copy link
Member

Choose a reason for hiding this comment

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

It's not good in the long term and is something we should fix. Moving it to 29 for now allows us to not have to deal with emulated TLS usage.

Copy link
Member

Choose a reason for hiding this comment

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

Unless we can fix it now, I don't think this should block progress. We can do it sometime down the road.

Choose a reason for hiding this comment

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

In perspective, this would drop 12.8% of the devices (with API level from 21 to 29) according to https://apilevels.com/

Then again:
Level 21 is Android 5 and 6 years EOL
Level 29 is Android 10 and 2 years EOL (https://endoflife.date/android)
Level 34 or higher is necessary to publish apps to the Play Store (https://developer.android.com/google/play/requirements/target-sdk)

Copy link
Member

Choose a reason for hiding this comment

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

I think I can make the emulated TLS work without too much hassle. The question though is if we are worried about the perf implications of the emulated TLS vs the standard TLS and thus we would like to end up having support for both.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Perf is important, so I think the long-term solution should be that we have two builds of the runtime (alas): one with emulated TLS for the older devices (we mustn't ignore the older Android versions, 12.8% is still a lot of devices out there), and another targeting API 29 and onwards. It will increase nuget size and the runtime build times on CI, but I think it would be the best way forward.

Copy link
Member

Choose a reason for hiding this comment

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

I'd like to avoid runtime explosion if we can help it.

Comment on lines -81 to +82
<_CoreClrBuildArg Include="-DANDROID_STL=none"/>
<_CoreClrBuildArg Include="-DANDROID_CPP_FEATURES=&quot;no-rtti no-exceptions&quot;"/>
<_CoreClrBuildArg Include="-DANDROID_STL=c++_static"/>
<_CoreClrBuildArg Include="-DANDROID_CPP_FEATURES=&quot;no-rtti exceptions&quot;"/>
Copy link
Member

Choose a reason for hiding this comment

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

Does this affect size of native AOT runtime packs? (Build with ./build.sh -ci -arch x64 -os linux-bionic -c Release /p:DotNetBuildRuntimeNativeAOTRuntimePack=true and check the size of libRuntime.WorkstationGC.a). We'll likely have to move this part of configuration someplace else, native AOT is the most size sensitive workload we have. Native AOT doesn't need C++ runtime library and doesn't need exceptions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it will affect the size, but less than if we included the shared libc++ (which is something we cannot do anyway) and I think we just need to pay the price. NativeAOT will be but one of the supported ways to build the application, we need to keep that in mind. I don't like the fact that CoreCLR needs exceptions (Android runtime doesn't use exceptions nor RTTI), but that's what we have and we need to support it (at least for the foreseeable future).

Ideally, for NativeAOT we should be able to link the application .so at the app build time (from a set of .o or .a files), in which case this setting here won't matter at all.

Copy link
Member

Choose a reason for hiding this comment

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

My question is whether we could set this in the CMake files instead of as argument to CMake. That way pieces of this can still compile with exceptions turned off instead of globally forcing the VM policy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure we can? The variables are used by the Android toolchain definition file - I think they need to be set on the command line for this to work.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah this needs to be set at the CMake build level sadly. There's not a supported way to do it per-target. We could likely manually set flags to do it if we figure out how the toolchain file sets flags.

@@ -2,9 +2,36 @@
<PropertyGroup>
<StaticLibPrefix>lib</StaticLibPrefix>
<ExeSuffix Condition="'$(HostOS)' == 'windows'">.exe</ExeSuffix>
<Blah>$(HostOS)</Blah>
Copy link
Member

Choose a reason for hiding this comment

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

Remove :-)

Copy link
Member

Choose a reason for hiding this comment

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

Has this been removed?

* main:
  JIT: Model GT_RETURN kills with contained operand (dotnet#111230)
  Update dependencies from https://github.com/dotnet/runtime-assets build 20250110.2 (dotnet#111290)
  [NativeAOT/ARM64] Generate frames compatible with Apple compact unwinding (dotnet#107766)
  Cleanup unused JIT stubs in vm (dotnet#111237)
  Ensure that Shuffle is marked as HW_Flag_CanBenefitFromConstantProp (dotnet#111303)
  Fix CMP0173 policy warning with cmake 3.31 (dotnet#110522)
  [RISC-V] Fix HostActivation.Tests unknown-rid (dotnet#110687)
  Fix accidentally duplicated global-build-step.yml in runtime-official.yml (dotnet#111302)
  JIT: run extra SPMI queries for arrays (dotnet#111293)
  Split the Runtime Shared Framework project and combine legs in the official build (dotnet#111136)
  Do not ignore `MemoryMarshal.TryWrite` result (dotnet#108661)
  Update dependencies from https://github.com/dotnet/emsdk build 20250109.1 (dotnet#111263)
  Clean up in Number.Formatting.cs (dotnet#110955)
EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/i586-alpine-linux-musl OR
EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/x86_64-alpine-linux-musl OR
EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/riscv64-alpine-linux-musl)
if(NOT DEFINED ANDROID_PLATFORM)
Copy link
Member

Choose a reason for hiding this comment

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

@janvorli I changed the workaround so that we don't set DARWIN when cross-building. We still rely on setting ANDROID_PLATFORM externally though, what we should revisit in the follow-up PRs.

@grendello grendello marked this pull request as ready for review January 15, 2025 16:22
@grendello grendello requested review from AaronRobinsonMSFT and a team as code owners January 15, 2025 16:22
</PropertyGroup>

<!-- Add path globs specific to native binaries to exclude unnecessary files from packages. -->
<Choose>
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't this logic already exist?

@jkoritzinsky ?

Copy link
Member

Choose a reason for hiding this comment

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

I don't believe it exists elsewhere. I put this here because I found host / target confusion when crossgen2 was cross building android from a mac.

Copy link
Member

@jkoritzinsky jkoritzinsky Jan 15, 2025

Choose a reason for hiding this comment

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

The logic we have is for the "target" platform, not the host (and it's right below this).

Comment on lines +19 to +23
#ifdef __cplusplus
#define CORECLR_HOSTING_API_LINKAGE extern "C"
#else
#define CORECLR_HOSTING_API_LINKAGE
#endif
Copy link
Member

Choose a reason for hiding this comment

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

@@ -1,6 +1,7 @@
set(EVENT_MANIFEST ${VM_DIR}/ClrEtwAll.man)

if(CLR_CMAKE_HOST_LINUX)
# TODO: LTTNG is not supported on Android. We need a solution.
Copy link
Member

Choose a reason for hiding this comment

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

In lieu of a TODO, please file a github issue and provide a link in the comment.

<!-- No LTTNG on Android -->
<_CoreClrBuildArg Include="-cmakeargs -DFEATURE_EVENT_TRACE=0"/>
<!--
TODO: No LTTNG on Android, it's disabled at the eventprovider level. Will need an answer.
Copy link
Member

Choose a reason for hiding this comment

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

Same as above, please file an issue and add a link to the issue here.

@@ -12,7 +12,9 @@ check_symbol_exists(
HAVE_ACCEPT4)

# Use TCP for EventPipe on mobile platforms
if (CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR CLR_CMAKE_HOST_ANDROID)
#
# TODO: Resolve TCP/IP EventPipe support on CoreCLR Android
Copy link
Member

Choose a reason for hiding this comment

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

Please file a github issue and record the link here.

Comment on lines 14 to 15


Copy link
Member

Choose a reason for hiding this comment

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

Suggested change

Comment on lines +171 to +172
# Instead of patching libunwind, don't treat the handful of warnings it has as errors
add_compile_options(-Wno-error)
Copy link
Member

Choose a reason for hiding this comment

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

This should be an issue. We regularly upstream changes to libunwind. See libunwind/libunwind#734.

/cc @am11 @janvorli

Copy link
Member

Choose a reason for hiding this comment

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

Could you show the warnings? We should fix them here instead and upstream the patch simultaneously, and add a line in ../libunwind-version.txt.

Comment on lines 181 to 182


Copy link
Member

Choose a reason for hiding this comment

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

Suggested change

@@ -68,7 +68,7 @@
- src/tasks/MobileBuildTasks/Apple/AppleProject.cs
- https://github.com/dotnet/sdk repo > src/Installer/redist-installer/targets/GeneratePKG.targets
-->
<AndroidApiLevelMin>21</AndroidApiLevelMin>
<AndroidApiLevelMin>29</AndroidApiLevelMin>
Copy link
Member

Choose a reason for hiding this comment

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

this needs to be conditioned on CoreCLR so we don't change the Mono build. same in eng/native/build-commons.sh

Copy link
Member

Choose a reason for hiding this comment

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

Should this be 28? @janvorli tested it recently with 28 https://github.com/dotnet/arcade/blob/88a10ba00ed798ee289d786db9f6339acd682a99/eng/common/cross/build-android-rootfs.sh#L24. We can provide a fallback for that glob API to further lower the requirement.

Copy link
Member

Choose a reason for hiding this comment

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

I think 29 is necessary because that's the first that does not use emulated TLS.

Copy link
Member

Choose a reason for hiding this comment

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

We can add a run-time check for emulated TLS selection and still lower the requirement.

Copy link
Member

Choose a reason for hiding this comment

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

Did we add a workaround for that? When I ran things previously we only had that for NativeAOT. Assuming that's true, the build will fail.

Copy link
Member

Choose a reason for hiding this comment

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

Emulated TLS works on linux-bionic and has been for a while, so in theory it should work on older Androids, newer ones can use the real TLS. I have recently dealt with Emulated TLS on riscv64 (and later switched to real TLS but still having some issues #111317 (comment)). We can tweak things in asm code to select which path to take GETTHREAD_ETLS_1 vs. INLINE_GETTHREAD. Right now it's under the build condition FEATURE_EMULATED_TLS.

Copy link
Member

Choose a reason for hiding this comment

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

It appears that there is going to be some amount of work to get this right < API level 29. My preference would be to do any of that work in a follow up.

add_compile_definitions(NATIVE_LIBS_EMBEDDED)
# TODO: Android uses a separate System.Security.Cryptography lib that does not have
# the exported functions the singlefilehost expects.
# Figure out how that's going to work and turn this back on.
Copy link
Member

Choose a reason for hiding this comment

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

please file an issue for this, though I'm kinda surprised that the host depends on specific S.C.Cryptography functions?

Copy link
Member

@jkoritzinsky jkoritzinsky left a comment

Choose a reason for hiding this comment

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

Can we run a test official build to make sure the official build will build the CoreCLR assets in the android legs and that we won't have conflicts/double-writes with any package names?

@@ -9,11 +9,11 @@
<ProjectReference Include="ILCompiler.Reflection.ReadyToRun.Experimental\ILCompiler.Reflection.ReadyToRun.Experimental.pkgproj" />
</ItemGroup>

<ItemGroup Condition="'$(RuntimeFlavor)' == 'CoreCLR'">
<ItemGroup Condition="'$(RuntimeFlavor)' == 'CoreCLR' and '$(TargetsAndroid)' != 'true' ">
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
<ItemGroup Condition="'$(RuntimeFlavor)' == 'CoreCLR' and '$(TargetsAndroid)' != 'true' ">
<ItemGroup Condition="'$(RuntimeFlavor)' == 'CoreCLR' and '$(TargetsMobile)' != 'true' ">

<ProjectReference Include="Microsoft.NETCore.TestHost\Microsoft.NETCore.TestHost.proj" />
</ItemGroup>

<ItemGroup>
<ItemGroup Condition=" '$(TargetsAndroid)' != 'true' ">
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
<ItemGroup Condition=" '$(TargetsAndroid)' != 'true' ">
<ItemGroup Condition=" '$(TargetsMobile)' != 'true' ">

@@ -250,8 +250,10 @@ if(NOT CLR_CMAKE_HOST_MACCATALYST AND NOT CLR_CMAKE_HOST_IOS AND NOT CLR_CMAKE_H
add_subdirectory(utilcode)
add_subdirectory(inc)

add_subdirectory(ilasm)
add_subdirectory(ildasm)
if (NOT CLR_CMAKE_TARGET_ANDROID)
Copy link
Member

Choose a reason for hiding this comment

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

Could we instead define a property for "build executables" instead of per-platform?
And also define one for the case above for "NativeAOT-only"?

@@ -1,6 +1,7 @@
set(EVENT_MANIFEST ${VM_DIR}/ClrEtwAll.man)

if(CLR_CMAKE_HOST_LINUX)
# TODO: LTTNG is not supported on Android. We need a solution.
if(CLR_CMAKE_HOST_LINUX AND NOT CLR_CMAKE_TARGET_ANDROID)
Copy link
Member

Choose a reason for hiding this comment

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

This should also use the host defines.

Suggested change
if(CLR_CMAKE_HOST_LINUX AND NOT CLR_CMAKE_TARGET_ANDROID)
if(CLR_CMAKE_HOST_LINUX AND NOT CLR_CMAKE_HOST_ANDROID)

Comment on lines -81 to +82
<_CoreClrBuildArg Include="-DANDROID_STL=none"/>
<_CoreClrBuildArg Include="-DANDROID_CPP_FEATURES=&quot;no-rtti no-exceptions&quot;"/>
<_CoreClrBuildArg Include="-DANDROID_STL=c++_static"/>
<_CoreClrBuildArg Include="-DANDROID_CPP_FEATURES=&quot;no-rtti exceptions&quot;"/>
Copy link
Member

Choose a reason for hiding this comment

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

Yeah this needs to be set at the CMake build level sadly. There's not a supported way to do it per-target. We could likely manually set flags to do it if we figure out how the toolchain file sets flags.

Comment on lines +94 to +98
<!--
Unsure if something like this is actually defined. We need this to differentiate between
features that are enabled in mono android, but not in coreclr.
-->
<_CoreClrBuildArg Include="-cmakeargs -DRUNTIME_CORECLR=1" />
Copy link
Member

Choose a reason for hiding this comment

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

Is this used anywhere?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, one spot. Is there a better existing way to do this?

if (CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR (CLR_CMAKE_HOST_ANDROID AND NOT RUNTIME_CORECLR))

Copy link
Member

Choose a reason for hiding this comment

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

Could we add a general feature flag that the Mono vs CoreCLR builds would set?

Is this expected to work for the NativeAOT build?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.