Skip to content

Put together an Android SDK bundle #80788

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

Open
5 tasks
finagolfin opened this issue Apr 13, 2025 · 5 comments
Open
5 tasks

Put together an Android SDK bundle #80788

finagolfin opened this issue Apr 13, 2025 · 5 comments
Assignees
Labels
Android Platform: Android cross-compilation Area → utils: Cross-compilation of project sources task

Comments

@finagolfin
Copy link
Member

Description

Mishal recently asked the Android workgroup to submit a Dockerfile which builds an Android SDK for the 6.2 and trunk branches, so @marcprux and I will be putting one together in the coming weeks. Here's a checklist of the decisions that have to be made:

  • What Android API should the Swift runtime be built against? We've tentatively decided on API 28, as that is when most of the posix_spawn APIs were added to the Bionic libc, which some parts of Foundation depend on.
  • Do we bundle the Android C/C++ sysroot from the NDK with the Swift SDK? Probably safest not to, which means we'll have to try out the existing SDK bundle support for using an external C/C++ sysroot now.
  • Do we support FoundationXML and FoundationNetworking, which will require cross-compiling their libxml2, libcurl, and BoringSSL dependencies also? We plan to look into cross-compiling all those libraries from source for Android.
  • The new Testing library and a few other toolchain product repos have shifted to using CMake Toolchain files when configuring their build for linux and mac. We need to investigate doing the same for Android.
  • Testing calls the backtrace() API, which wasn't added to Bionic till API 33. Investigate if that can be disabled for now, or if we want to add a backport library.

Additional information

Much of this already works in build-script and the corelibs, but a few tweaks will be needed.

@finagolfin finagolfin added Android Platform: Android cross-compilation Area → utils: Cross-compilation of project sources task labels Apr 13, 2025
@finagolfin finagolfin self-assigned this Apr 13, 2025
@finagolfin finagolfin moved this to Todo in Swift on Android Apr 13, 2025
@marcprux
Copy link
Contributor

My work-in-progress PR on this is at swift-android-sdk/swift-docker#1. It is modeled on the Musl (static Linux) build script (swiftlang/swift-docker#389).

My current assumptions – all of which are open to discussion – are:

What Android API should the Swift runtime be built against? We've tentatively decided on API 28, as that is when most of the posix_spawn APIs were added to the Bionic libc, which some parts of Foundation depend on.

28 supposedly covers 92% of Android devices, so I feel it is a good level.

Do we bundle the Android C/C++ sysroot from the NDK with the Swift SDK? Probably safest not to, which means we'll have to try out the existing SDK bundle support for using an external C/C++ sysroot now.

When we discussed this at finagolfin/swift-android-sdk#163 (comment), I think we determined that the subset of the NDK that would need to be bundled with the Swift SDK is redistributable.

If we do decide to exclude it, are we expecting that people will build with a command like:

~/Library/Developer/Toolchains/swift-6.1-RELEASE.xctoolchain/usr/bin/swift build --swift-sdk aarch64-unknown-linux-android24 -Xswiftc -sysroot -Xswiftc ~/Library/Android/sdk/ndk/27.0.12077973/prebuilt/darwin-x86_64

Has this been tested? I tried a quick experiment where I edit swift-sdk.json to remove the sdkRootPath and swiftResourcesPath for aarch64-unknown-linux-android24 and instead specify it with the command above, and it fails when those keys are missing.

Do we support FoundationXML and FoundationNetworking, which will require cross-compiling their libxml2, libcurl, and BoringSSL dependencies also? We plan to look into cross-compiling all those libraries from source for Android.

I've got those all building and linking, so I think we will be good for including FoundationXML and FoundationNetworking (notwithstanding issues like swiftlang/swift-corelibs-foundation#5163).

The new Testing library and a few other toolchain product repos have shifted to using CMake Toolchain files when configuring their build for linux and mac. We need to investigate doing the same for Android.

Testing seems to be building fine with build-script for me. Can you elaborate on this?

Testing calls the backtrace() API, which wasn't added to Bionic till API 33. Investigate if that can be disabled for now, or if we want to add a backport library.

I just patch out the call to backtrace() and it builds, but I don't know the consequences of this. Would it just be lacking cosmetic assistance with test failures? As I mentioned at finagolfin/swift-android-sdk#174 (comment), we could probably just pull execinfo.c into Testing and bring back support for it.

@finagolfin
Copy link
Member Author

My work-in-progress PR on this is at swift-android-sdk/swift-docker#1. It is modeled on the Musl (static Linux) build script

Thanks for working on this, 😄 I don't like that it's a bunch of bash scripts so far though. I understand why Alastair did that for the static linux SDK, as he didn't use build-script to build much of it, but you're only building a few libraries outside of build-script here.

Also, I just checked and it looks like @etcwilde added support for building curl and libxml2 from build-script a couple years ago, both using CMake toolchain files, would be better if we just modified that to cross-compile for Android instead.

we determined that the subset of the NDK that would need to be bundled with the Swift SDK is redistributable.

I said that I think it's open source and was willing to redistribute it, but I don't think that's a risk worth taking for the official SDK, especially since some have expressed that they'd like to use it with older NDKs too.

are we expecting that people will build with a command like

No, the SDK bundle spec explicitly discusses that since platform C/C++ SDKs are often proprietary and cannot be redistributed, that it supports configuring external C/C++ SDKs like the NDK too.

Has this been tested? I tried a quick experiment where I edit swift-sdk.json to remove the sdkRootPath and swiftResourcesPath for aarch64-unknown-linux-android24

No, I mentioned to you privately last week that I intend to try out "using an external NDK instead" later this week. I fully expect that we will find bugs in that external SDK logic that will need to be fixed too.

Testing seems to be building fine with build-script for me. Can you elaborate on this?

It only works because you're using my patches to pass those cross-compilation flags in, but we definitely need to switch over to the favored CMake toolchain file approach instead.

I just patch out the call to backtrace() and it builds, but I don't know the consequences of this. Would it just be lacking cosmetic assistance with test failures?

I don't know, that's what we need to check.

we could probably just pull execinfo.c into Testing and bring back support for it.

Since that file uses a BSD license instead, I doubt that they'd accept it, and I'm not sure if we should use it in this official SDK bundle either.

@xavgru12
Copy link

Thanks for working on this, 😄 I don't like that it's a bunch of bash scripts so far though. I understand why Alastair did that for the static linux SDK, as he didn't use build-script to build much of it, but you're only building a few libraries outside of build-script here.

What is the reason for using bash scripts for static Linux SDK?
Standalone and better maintainable?

I would love to see both the static Linux SDK as well as Android support inside the build scripts without using the bash scripts.

I asked here
and he mentioned that build scripts are being worked on. Hopefully the cmake toolchain file will be used for all components/libraries. Maybe ask for the state of the new build scripts/investigate them, so we combine forces here and work out a plan?

@etcwilde
Copy link
Contributor

I believe the other half of the reason that @al45tair did that for the static SDK was to avoid building the compiler as part of the SDK build. The static SDK builds are downstream from the nightly toolchain and use the nightly toolchain to build to ensure that the swift modules produced would work with a pre-downloaded nightly since the modules are tied to the compiler that built them.

This is both for performance and for convenience of folks using the SDK.

@marcprux
Copy link
Contributor

I've got the scripts building and packaging the SDK. You can see a successful run at https://github.com/swift-android-sdk/swift-docker/actions/runs/14585532437, which builds and tests both a full SDK (swift-6.1-RELEASE_android-0.1.artifactbundle.tar.gz) as well as a limited x86_64-only one (swift-6.1-RELEASE_android-0.1.artifactbundle-x86_64.tar.gz), which just exists to speed up the CI testing (since it builds in about half the time as the full 3-arch build).

I don't like that it's a bunch of bash scripts so far though

Me neither, but that's where we are at right now. The various moving parts are:

  1. The master build script that invokes fetch-source.sh, applies @finagolfin's patches, and then invokes build.sh
  2. fetch-source.sh which gets libxml2, curl, and boringssl, and swift (for the specific tag).
  3. build.sh which performs the build for each specified architecture and assembles it into an artifactbundle.
  4. The pull_request.yml CI which runs build, uploads the artifacts, installs the freshly-built SDK and build and tests swift-algorithms against an Android emulator.

The structure of the SDK is basically identical to @finagolfin's (https://github.com/finagolfin/swift-android-sdk/releases). I expect we will be changing this over time, but it was a quick and proven way to get started. However, the scripts only handle building the 6.1-release tag. Supporting devel and trunk would likely just require conditional patching (or hopefully no patching at all!)

One wart is that we need to manually un-set the ANDROID_NDK_ROOT environment variable in order to build anything (swiftlang/swift-driver#1879).

Sundry responses:

I just checked and it looks like @etcwilde added support for building curl and libxml2 from build-script a couple years ago, both using CMake toolchain files, would be better if we just modified that to cross-compile for Android instead.

I noticed, but the curl is built without SSL support, and there's no build script for OpenSSL or BoringSSL. I expect it could be added, I'd just need to dig into it. libxml2 should be usable as-is, though – it hadn't occurred to me to try it, just because the static-linux script was building its own libxml2, and I assumed there was some good reason for it.

I intend to try out "using an external NDK instead" later this week. I fully expect that we will find bugs in that external SDK logic that will need to be fixed too.

Great! Let me know if I can help with this in any way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Android Platform: Android cross-compilation Area → utils: Cross-compilation of project sources task
Projects
Status: Todo
Development

No branches or pull requests

4 participants