{"id":13872318,"url":"https://github.com/finagolfin/swift-android-sdk","last_synced_at":"2025-04-04T17:05:55.766Z","repository":{"id":37078082,"uuid":"309586742","full_name":"finagolfin/swift-android-sdk","owner":"finagolfin","description":"Android SDKs for Swift","archived":false,"fork":false,"pushed_at":"2025-03-26T22:51:13.000Z","size":484,"stargazers_count":180,"open_issues_count":5,"forks_count":16,"subscribers_count":14,"default_branch":"main","last_synced_at":"2025-03-26T23:31:25.634Z","etag":null,"topics":["android","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/finagolfin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-03T05:48:03.000Z","updated_at":"2025-03-25T22:08:56.000Z","dependencies_parsed_at":"2023-09-23T21:32:08.766Z","dependency_job_id":"86cc4e06-4fca-41d7-8abd-0360a2bf325b","html_url":"https://github.com/finagolfin/swift-android-sdk","commit_stats":{"total_commits":445,"total_committers":5,"mean_commits":89.0,"dds":0.3595505617977528,"last_synced_commit":"3493a85cd1ae767792ba01c8634e3d9456d19901"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finagolfin%2Fswift-android-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finagolfin%2Fswift-android-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finagolfin%2Fswift-android-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finagolfin%2Fswift-android-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/finagolfin","download_url":"https://codeload.github.com/finagolfin/swift-android-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247217174,"owners_count":20903008,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","swift"],"created_at":"2024-08-05T23:00:39.572Z","updated_at":"2025-04-04T17:05:55.747Z","avatar_url":"https://github.com/finagolfin.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"# Swift cross-compilation SDK bundle for Android\n\nThe patches used to build this SDK bundle are open source and listed below. I\nmaintain [a daily CI on github Actions](https://github.com/finagolfin/swift-android-sdk/actions?query=event%3Aschedule)\nthat [cross-compiles the SDK bundle from the release and development source branches of\nthe Swift toolchain for AArch64, armv7, and x86_64, builds several Swift\npackages against those SDKs, and then runs their tests in the Android x86_64\nemulator](https://github.com/finagolfin/swift-android-sdk/blob/main/.github/workflows/sdks.yml).\n\n## Cross-compiling and testing Swift packages with the Android SDK bundle\n\nTo build with the Swift 6 SDK bundle, first download [the official open-source\nSwift 6.0.3 toolchain for linux or macOS](https://swift.org/install)\n(make sure to install the Swift dependencies linked there). Install the OSS\ntoolchain on macOS as detailed in [the instructions for using the static linux\nMusl SDK bundle at swift.org](https://www.swift.org/documentation/articles/static-linux-getting-started.html).\nOn linux, simply download the toolchain, unpack it, and add it to your `PATH`.\n\nNext, install the Android SDK bundle by having the Swift toolchain directly\ndownload it:\n```\nswift sdk install https://github.com/finagolfin/swift-android-sdk/releases/download/6.0.3/swift-6.0.3-RELEASE-android-24-0.1.artifactbundle.tar.gz --checksum 4566f23ae2d36dc5c02e915cd67d83b2af971faca4b2595fdd75cf0286acfac1\n```\nor alternately, download the SDK bundle with your favorite downloader and install\nit separately:\n```\n\u003e wget https://github.com/finagolfin/swift-android-sdk/releases/download/6.0.3/swift-6.0.3-RELEASE-android-24-0.1.artifactbundle.tar.gz\n\u003e sha256sum swift-6.0.3-RELEASE-android-24-0.1.artifactbundle.tar.gz\n4566f23ae2d36dc5c02e915cd67d83b2af971faca4b2595fdd75cf0286acfac1 swift-6.0.3-RELEASE-android-24-0.1.artifactbundle.tar.gz\n\u003e swift sdk install swift-6.0.3-RELEASE-android-24-0.1.artifactbundle.tar.gz\n```\nYou can check if it was properly installed by running `swift sdk list`.\n\nNow you're ready to cross-compile a Swift package and run its tests on Android.\nI'll demonstrate with the swift-argument-parser package:\n```\ngit clone --depth 1 https://github.com/apple/swift-argument-parser.git\n\ncd swift-argument-parser/\n\nswift build --build-tests --swift-sdk aarch64-unknown-linux-android24\n```\n\nNote: On macOS, building for Android requires specifying an OSS toolchain like so:\n```\nswift build --build-tests --swift-sdk aarch64-unknown-linux-android24 --toolchain \u003cPATH_TO_OSS_TOOLCHAIN\u003e\n```\n\nThis will cross-compile the package for Android aarch64 at API 24 and produce a\ntest runner executable with the `.xctest` extension, in this case at\n`.build/aarch64-unknown-linux-android24/debug/swift-argument-parserPackageTests.xctest`.\n\nSometimes the test runner will depend on additional files or executables: this\none depends on the example executables `color`, `generate-manual`, `math`,\n`repeat`, and `roll` in the same build directory. Other packages use `#file` to\npoint at test data in the repo: I've had success moving this data with the test\nrunner, after modifying the test source so it has the path to this test data in\nthe Android test environment. See the example of [swift-crypto on the\nCI](https://github.com/finagolfin/swift-android-sdk/blob/6.0.3/.github/workflows/sdks.yml#L506).\n\nYou can copy these executables and the Swift runtime libraries to [an emulator\nor a USB debugging-enabled device with adb](https://github.com/swiftlang/swift/blob/release/6.0/docs/Android.md#3-deploying-the-build-products-to-the-device),\nor put them on an Android device with [a terminal emulator app like Termux](https://termux.dev/en/).\nI test aarch64 with Termux so I'll show how to run the test runner there, but\nthe process is similar with adb, [as can be seen on the CI](https://github.com/finagolfin/swift-android-sdk/blob/6.0.3/.github/workflows/sdks.yml#L454).\n\nCopy the test executables to the same directory as the Swift 6 runtime libraries:\n```\ncp .build/aarch64-unknown-linux-android24/debug/{swift-argument-parserPackageTests.xctest,color,generate-manual,math,repeat,roll} ..\ncp ~/.swiftpm/swift-sdks/swift-6.0.3-RELEASE-android-24-0.1.artifactbundle/swift-6.0.3-release-android-24-sdk/android-27c-sysroot/usr/lib/aarch64-linux-android/lib*.so ..\n```\nYou can copy the test executables and Swift 6 runtime libraries to Termux using\nscp from OpenSSH, run these commands in Termux on the Android device:\n```\nuname -m # check if you're running on the right architecture, should say `aarch64`\ncd       # move to the Termux app's home directory\npkg install openssh\n\nscp yourname@192.168.1.1:\"lib*.so\" .\nscp yourname@192.168.1.1:{swift-argument-parserPackageTests.xctest,color,generate-manual,math,repeat,roll} .\n\n./swift-argument-parserPackageTests.xctest\n```\nI've tried several Swift packages, including some mostly written in C or C++,\nand all the cross-compiled tests passed. Note that while this SDK bundle is\ncompiled against Android API 24, there was a regression in Swift 6 so that\nFoundation can only be run on Android API 29 or later, finagolfin/swift-android-sdk#175.\nI will update the SDK bundle when I find a fix for that new issue.\n\nYou can even run armv7 tests on an aarch64 device, though Termux may require\nrunning `unset LD_PRELOAD` before invoking an armv7 test runner on aarch64.\nRevert that with `export LD_PRELOAD=/data/data/com.termux/files/usr/lib/libtermux-exec.so`\nwhen you're done running armv7 tests and want to go back to the normal aarch64\nmode.\n\n## Porting Swift packages to Android\n\nThe most commonly needed change is to import the new Android overlay, so add\nthese two lines for Android when calling Android's C APIs:\n```\n#if canImport(Android)\nimport Android\n```\nYou may also need to add some Android-specific support using `#if canImport(Android)`,\nfor example, since FILE is an opaque struct since Android 7, you will [have to\nrefer to any FILE pointers like this](https://github.com/swiftlang/swift-tools-support-core/pull/243/files):\n```\n#if canImport(Android)\ntypealias FILEPointer = OpaquePointer\n```\nThose changes are all I had to do [to port swift-argument-parser to\nAndroid](https://github.com/apple/swift-argument-parser/pull/651/files).\n\n## Building an Android app with Swift\n\nSome people have reported an issue with using previous libraries from this SDK in\ntheir Android app, that the Android toolchain strips `libdispatch.so` and\ncomplains that it has an `empty/missing DT_HASH/DT_GNU_HASH`. You can [work\naround this issue by adding the following to your `build.gradle`](https://github.com/finagolfin/swift-android-sdk/issues/67#issuecomment-1227460068):\n```\npackagingOptions {\n    doNotStrip \"*/arm64-v8a/libdispatch.so\"\n    doNotStrip \"*/armeabi-v7a/libdispatch.so\"\n    doNotStrip \"*/x86_64/libdispatch.so\"\n}\n```\n\n## Building an Android SDK from source\n\nDownload the Swift 6.0.3 compiler as above and Android NDK 27c (only building\nthe Android SDKs on linux works for now). Check out this repo and run\n`SWIFT_TAG=swift-6.0.3-RELEASE ANDROID_ARCH=aarch64 swift get-packages-and-swift-source.swift`\nto get some prebuilt Android libraries and the Swift source to build an AArch64\nSDK. If you pass in a different tag like `swift-DEVELOPMENT-SNAPSHOT-2025-01-05-a`\nfor the latest Swift trunk snapshot and pass in the path to the corresponding\nprebuilt Swift toolchain to `build-script` below, you can build a Swift trunk\nSDK too, as seen on the CI.\n\nNext, apply two patches from this repo to the Swift source, which make\nmodifications for NDK 27 and [the Foundation rewrite in Swift 6 that was merged\nthis summer](https://www.swift.org/blog/foundation-preview-now-available/), and\nsubstitute a string for NDK 27:\n```\ngit apply swift-android.patch swift-android-foundation-release.patch\nperl -pi -e 's%r26%r27%' swift/stdlib/cmake/modules/AddSwiftStdlib.cmake\n```\n\nAfter making sure [needed build tools like python 3, CMake, and ninja](https://github.com/swiftlang/swift/blob/release/6.0/docs/HowToGuides/GettingStarted.md#linux)\nare installed, run the following `build-script` command with your local paths\nsubstituted instead:\n```\n./swift/utils/build-script -RA --skip-build-cmark --build-llvm=0 --android\n--android-ndk /home/finagolfin/android-ndk-r27c/ --android-arch aarch64 --android-api-level 24\n--build-swift-tools=0 --native-swift-tools-path=/home/finagolfin/swift-6.0.3-RELEASE-ubuntu22.04/usr/bin/\n--native-clang-tools-path=/home/finagolfin/swift-6.0.3-RELEASE-ubuntu22.04/usr/bin/\n--host-cc=/usr/bin/clang-13 --host-cxx=/usr/bin/clang++-13\n--cross-compile-hosts=android-aarch64 --cross-compile-deps-path=/home/finagolfin/swift-release-android-aarch64-24-sdk\n--skip-local-build --xctest --swift-install-components='clang-resource-dir-symlink;license;stdlib;sdk-overlay'\n--install-swift --install-libdispatch --install-foundation --install-xctest\n--install-destdir=/home/finagolfin/swift-release-android-aarch64-24-sdk --skip-early-swiftsyntax\n--cross-compile-append-host-target-to-destdir=False --build-swift-static-stdlib -j9\n```\nMake sure you have an up-to-date CMake and not something old like 3.16. The\n`--host-cc` and `--host-cxx` flags are not needed if you have a `clang` and\n`clang++` in your `PATH` already, but I don't and they're unused for this build\nanyway but required by `build-script`. Substitute armv7 or x86_64 for aarch64\ninto these commands to build SDKs for those architectures instead.\n\nFinally, copy `libc++_shared.so` from the NDK and modify the cross-compiled\nSwift corelibs to include `$ORIGIN` and other relative directories in their rpaths:\n```\ncp /home/yourname/android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so swift-release-android-aarch64-24-sdk/usr/lib\npatchelf --set-rpath \\$ORIGIN/../..:\\$ORIGIN swift-release-android-aarch64-24-sdk/usr/lib/swift/android/lib*.so\n```\n\nHere is a description of what the above Swift script is doing:\n\nThis prebuilt SDK was compiled against Android API 24, because the Swift\nFoundation libraries require some libraries like libcurl, that are pulled from the\nprebuilt library packages used by the Termux app, which are built against Android\nAPI 24. Specifically, it downloads the libandroid-spawn, libcurl, and libxml2\npackages and their handful of dependencies from the [Termux package\nrepository](https://packages.termux.dev/apt/termux-main/pool/main/).\n\nEach one is unpacked with `ar x libcurl_8.10.1-1_aarch64.deb; tar xf data.tar.xz` and\nthe resulting files moved to a newly-created Swift release SDK directory:\n```\nmkdir swift-release-android-aarch64-24-sdk\nmv data/data/com.termux/files/usr swift-release-android-aarch64-24-sdk\n```\nIt removes two config scripts in `usr/bin`, runs `patchelf` to remove the\nTermux rpath from all Termux shared libraries, removes some unused libraries\nand config files, and modifies the libraries to get rid of the versioning and\nsymlinks, which can't always be used on Android:\n```\nrm swift-release-android-aarch64-24-sdk/usr/bin/*-config\ncd swift-release-android-aarch64-24-sdk/usr/lib\n\npatchelf --set-rpath \\$ORIGIN libandroid-spawn.so libcurl.so libxml2.so\n\n# repeat the following for all versioned Termux libraries, as needed\nrm libxml2.so libxml2.so.2\nreadelf -d libxml2.so.2.13.4\nmv libxml2.so.2.13.4 libxml2.so\npatchelf --set-soname libxml2.so libxml2.so\npatchelf --replace-needed libz.so.1 libz.so libxml2.so\n```\nThe libcurl and libxml2 packages are [only needed for the FoundationNetworking\nand FoundationXML libraries respectively](https://github.com/swiftlang/swift-corelibs-foundation/blob/release/5.10/Docs/ReleaseNotes_Swift5.md),\nso you don't have to deploy them on the Android device if you don't use those\nextra Foundation libraries.\n\nThis Swift SDK for Android could be built without using any prebuilt Termux\npackages, by compiling against a more recent Android API that doesn't need the\n`libandroid-spawn` backport, and by cross-compiling libcurl/libxml2 and their\ndependencies yourself or not using FoundationNetworking and FoundationXML.\n\nFinally, it gets [the 6.0.3 source](https://github.com/swiftlang/swift/releases/tag/swift-6.0.3-RELEASE)\ntarballs for ten Swift repos and renames them to `llvm-project/`, `swift/`,\n`swift-syntax`, `swift-experimental-string-processing`, `swift-corelibs-libdispatch`,\n`swift-corelibs-foundation`, `swift-collections`, `swift-foundation`,\n`swift-foundation-icu`, and `swift-corelibs-xctest`, as required by the Swift\n`build-script`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinagolfin%2Fswift-android-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffinagolfin%2Fswift-android-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinagolfin%2Fswift-android-sdk/lists"}