mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
209 lines
8.9 KiB
Markdown
209 lines
8.9 KiB
Markdown
# Getting Started with Swift on Android
|
|
|
|
The Swift stdlib can be compiled for Android armv7 and aarch64 targets, which
|
|
makes it possible to execute Swift code on a mobile device running Android.
|
|
This guide explains:
|
|
|
|
1. How to run a simple "Hello, world" program on your Android device.
|
|
2. How to run the Swift test suite on an Android device.
|
|
|
|
If you encounter any problems following the instructions below, please file a
|
|
bug using https://bugs.swift.org/.
|
|
|
|
## FAQ
|
|
|
|
Let's answer a few frequently asked questions right off the bat:
|
|
|
|
### Does this mean I can write Android applications in Swift?
|
|
|
|
No. Although the Swift compiler is capable of compiling Swift code that runs
|
|
on an Android device, it takes a lot more than just the Swift stdlib to write
|
|
an app. You'd need some sort of framework to build a user interface for your
|
|
application, which the Swift stdlib does not provide.
|
|
|
|
Alternatively, one could theoretically call into Java interfaces from Swift,
|
|
but unlike as with Objective-C, the Swift compiler does nothing to facilitate
|
|
Swift-to-Java bridging.
|
|
|
|
## Prerequisites
|
|
|
|
To follow along with this guide, you'll need:
|
|
|
|
1. A Linux environment capable of building Swift from source, specifically
|
|
Ubuntu 18.04 or Ubuntu 16.04. Before attempting to build for Android,
|
|
please make sure you are able to build for Linux by following the
|
|
instructions in the Swift project README.
|
|
2. The latest version of the Android NDK (r21 at the time of this writing),
|
|
available to download here:
|
|
https://developer.android.com/ndk/downloads/index.html.
|
|
3. An Android device with remote debugging enabled. We require remote
|
|
debugging in order to deploy built stdlib products to the device. You may
|
|
turn on remote debugging by following the official instructions:
|
|
https://developer.chrome.com/devtools/docs/remote-debugging.
|
|
|
|
## "Hello, world" on Android
|
|
|
|
### 1. Downloading (or building) the Swift Android stdlib dependencies
|
|
|
|
You may have noticed that, in order to build the Swift stdlib for Linux, you
|
|
needed to `apt-get install libicu-dev icu-devtools`. Similarly, building
|
|
the Swift stdlib for Android requires the libiconv and libicu libraries.
|
|
However, you'll need versions of these libraries that work on Android devices.
|
|
|
|
The steps are as follows:
|
|
|
|
1. Ensure you have `curl`, `autoconf`, `automake`, `libtool`, and
|
|
`git` installed.
|
|
2. Clone the [SwiftAndroid/libiconv-libicu-android](https://github.com/SwiftAndroid/libiconv-libicu-android)
|
|
project. From the command-line, run the following command:
|
|
`git clone https://github.com/SwiftAndroid/libiconv-libicu-android.git`.
|
|
3. From the command-line, run `which ndk-build`. Confirm that the path to
|
|
the `ndk-build` executable in the Android NDK you downloaded is displayed.
|
|
If not, you may need to add the Android NDK directory to your `PATH`.
|
|
4. Change directories into `libiconv-libicu-android`: `cd libiconv-libicu-android`
|
|
5. Run the Swift build script: `./build-swift.sh`
|
|
6. Confirm that the various `libicuXYZswift.so` libraries are located in the
|
|
`armeabi-v7a` directory.
|
|
|
|
### 2. Building the Swift stdlib for Android
|
|
|
|
Enter your Swift directory, then run the build script, passing paths to the
|
|
Android NDK, as well as the directories that contain the `libicuucswift.so` and
|
|
`libicui18nswift.so` you downloaded or built in step one:
|
|
|
|
```
|
|
$ ARM_DIR=path/to/libicu-libiconv-android
|
|
$ NDK_PATH=path/to/android-ndk21
|
|
$ utils/build-script \
|
|
-R \ # Build in ReleaseAssert mode.
|
|
--android \ # Build for Android.
|
|
--android-ndk $NDK_PATH \ # Path to an Android NDK.
|
|
--android-arch armv7 \ # Optionally specify Android architecture, alternately aarch64
|
|
--android-api-level 21 \ # The Android API level to target. Swift only supports 21 or greater.
|
|
--android-icu-uc ${ARM_DIR}/libicuucswift.so \
|
|
--android-icu-uc-include ${ARM_DIR}/icu/source/common \
|
|
--android-icu-i18n ${ARM_DIR}/libicui18nswift.so \
|
|
--android-icu-i18n-include ${ARM_DIR}/icu/source/i18n \
|
|
--android-icu-data ${ARM_DIR}/libicudataswift.so
|
|
```
|
|
|
|
### 3. Compiling `hello.swift` to run on an Android device
|
|
|
|
Create a simple Swift file named `hello.swift`:
|
|
|
|
```swift
|
|
print("Hello, Android")
|
|
```
|
|
|
|
Then use the built Swift compiler from the previous step to compile a Swift
|
|
source file, targeting Android:
|
|
|
|
```
|
|
$ NDK_PATH="path/to/android-ndk21"
|
|
$ build/Ninja-ReleaseAssert/swift-linux-x86_64/bin/swiftc \ # The Swift compiler built in the previous step.
|
|
# The location of the tools used to build Android binaries
|
|
-tools-directory ${NDK_PATH}/toolchains/llvm/prebuilt/linux-x86_64/bin/ \
|
|
-target armv7a-none-linux-androideabi \ # Targeting android-armv7.
|
|
-sdk ${NDK_PATH}/platforms/android-21/arch-arm \ # Use the same architecture and API version as you used to build the stdlib in the previous step.
|
|
-Xclang-linker -nostdlib++ \ # Don't link libc++, and supply the path to libgcc.
|
|
-L ${NDK_PATH}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a \
|
|
hello.swift
|
|
```
|
|
|
|
This should produce a `hello` executable in the directory you executed the
|
|
command. If you attempt to run this executable using your Linux environment,
|
|
you'll see the following error:
|
|
|
|
```
|
|
cannot execute binary file: Exec format error
|
|
```
|
|
|
|
This is exactly the error we want: the executable is built to run on an
|
|
Android device--it does not run on Linux. Next, let's deploy it to an Android
|
|
device in order to execute it.
|
|
|
|
### 4. Deploying the build products to the device
|
|
|
|
You can use the `adb push` command to copy build products from your Linux
|
|
environment to your Android device. If you haven't already installed `adb`,
|
|
you may do so via `apt-get`:
|
|
|
|
```
|
|
$ sudo apt-get install android-tools-adb
|
|
```
|
|
|
|
Once you have `adb` installed, verify your device is connected and is
|
|
listed when you run the `adb devices` command - **currently this example works only in devices / emulators with at least Android 7.0, API 24** - then run the following
|
|
commands to copy the Swift Android stdlib:
|
|
|
|
```
|
|
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftCore.so /data/local/tmp
|
|
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftGlibc.so /data/local/tmp
|
|
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftSwiftOnoneSupport.so /data/local/tmp
|
|
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftRemoteMirror.so /data/local/tmp
|
|
```
|
|
|
|
You will also need to push the icu libraries:
|
|
|
|
```
|
|
adb push /path/to/libicu-android/armeabi-v7a/libicudataswift.so /data/local/tmp
|
|
adb push /path/to/libicu-android/armeabi-v7a/libicui18nswift.so /data/local/tmp
|
|
adb push /path/to/libicu-android/armeabi-v7a/libicuucswift.so /data/local/tmp
|
|
```
|
|
|
|
In addition, you'll also need to copy the Android NDK's libc++:
|
|
|
|
```
|
|
$ adb push /path/to/android-ndk-r21/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++_shared.so /data/local/tmp
|
|
```
|
|
|
|
Finally, you'll need to copy the `hello` executable you built in the
|
|
previous step:
|
|
```
|
|
$ adb push hello /data/local/tmp
|
|
```
|
|
|
|
### 5. Running "Hello, world" on your Android device
|
|
|
|
You can use the `adb shell` command to execute the `hello` executable on
|
|
the Android device:
|
|
|
|
```
|
|
$ adb shell LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/hello
|
|
```
|
|
|
|
You should see the following output:
|
|
|
|
```
|
|
Hello, Android
|
|
```
|
|
|
|
Congratulations! You've just run your first Swift program on Android.
|
|
|
|
## Running the Swift test suite hosted on an Android device
|
|
|
|
When running the test suite, build products are automatically pushed to your
|
|
device. As in part four, you'll need to connect your Android device via USB:
|
|
|
|
1. Connect your Android device to your computer via USB. Ensure that remote
|
|
debugging is enabled for that device by following the official instructions:
|
|
https://developer.chrome.com/devtools/docs/remote-debugging.
|
|
2. Confirm the device is connected by running `adb devices`. You should see
|
|
your device listed.
|
|
3. Run the tests using the build script:
|
|
|
|
```
|
|
$ utils/build-script \
|
|
-R \ # Build in ReleaseAssert mode.
|
|
-T --host-test \ # Run all tests, including on the Android host.
|
|
--android \ # Build for Android.
|
|
--android-ndk ~/android-ndk-r21 \ # Path to an Android NDK.
|
|
--android-arch armv7 \ # Optionally specify Android architecture, alternately aarch64
|
|
--android-ndk-version 21 \
|
|
--android-icu-uc ~/libicu-android/armeabi-v7a/libicuuc.so \
|
|
--android-icu-uc-include ~/libicu-android/armeabi-v7a/icu/source/common \
|
|
--android-icu-i18n ~/libicu-android/armeabi-v7a/libicui18n.so \
|
|
--android-icu-i18n-include ~/libicu-android/armeabi-v7a/icu/source/i18n/ \
|
|
--android-icu-data ~/libicu-android/armeabi-v7a/libicudata.so
|
|
```
|