Difference between revisions of "Build LDC for Android"
(Update to use forked llvm) |
(Link to steps for buiding sample programs on other page) |
||
Line 96: | Line 96: | ||
More info about the Android/ARM patches can be [https://github.com/joakim-noah/android/releases/tag/tea found with their release]. | More info about the Android/ARM patches can be [https://github.com/joakim-noah/android/releases/tag/tea found with their release]. | ||
− | + | You can now try [[Build D for Android#Build_a_command-line_executable|cross-compiling a sample program as shown here]]. You will need a terminal emulator Android app and to set the path to the LDC cross-compiler and libraries you just built: | |
− | |||
− | |||
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
− | + | export LDC=/path/to/your/ldc/build | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | ==Run the druntime and phobos unit tests== | |
− | + | You can build the druntime and phobos unit tests and run the command-line test runner binaries on Android (don't add the -j5 flag to build in parallel unless you have gigabytes of memory available, as compiling some of the phobos modules' tests takes a fair amount of RAM): | |
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
− | + | make druntime-test-runner phobos2-test-runner | |
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Copy the test runners to your device and run them. Assuming you have an SSH server set up on the computer where you're building with the linux shell and its IP address is 192.168.35.7, you can scp the binaries into [https://play.google.com/store/apps/details?id=com.termux&hl=en the Termux Android app] with these commands and run the tests: | |
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
− | + | apt install openssh | |
− | + | scp jo@192.168.35.7:"/path/to/your/ldc/build/runtime/{druntime,phobos2}-test-runner" . | |
+ | ./druntime-test-runner | ||
+ | ./phobos2-testrunner | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | The tests take about 25 seconds to run on my quad-core tablet: all should pass. One module, core.sync.semaphore, will fail for any Android older than 6.0, [https://github.com/D-Programming-Language/druntime/pull/784#issuecomment-42777328 because sem_destroy used to work differently in bionic]. You can also run the tests for specified modules by passing their names to the test runner: | |
− | |||
− | |||
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
− | + | ./druntime-test-runner core.thread core.sync.semaphore | |
− | + | ./phobos2-testrunner std.datetime std.random | |
− | |||
− | |||
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | ==Run the druntime and phobos unit tests in an apk== | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | You can also run the tests as part of a GUI app, ie an apk, which is a slightly different runtime environment. First, you can try [[Build D for Android#Build_a_sample_OpenGL_ES_1.0_GUI_app_ported_to_D|cross-compiling a sample GUI app from the NDK that has been translated from C to D, as shown here]]. That simple OpenGLES 1.0 GUI app can be modified to run all the tests, which is what we'll do next. Clone my Android repo, if you haven't already, go to the native-activity sample app, and create the output directory the SDK expects: | |
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
cd ../../ | cd ../../ | ||
git clone https://github.com/joakim-noah/android.git | git clone https://github.com/joakim-noah/android.git | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
cd android/samples/native-activity/ | cd android/samples/native-activity/ | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
mkdir -p libs/armeabi-v7a/ | mkdir -p libs/armeabi-v7a/ | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Download and apply [https://gist.github.com/joakim-noah/8ba3cd4958266f357295 a small patch to have the sample app invoke the test runner] and [https://gist.github.com/joakim-noah/348edc378d47fb90e32708be19286a2e a patch for the test runner in druntime], then build the tests into a shared library this time: | |
− | |||
− | |||
− | |||
− | |||
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
Line 204: | Line 144: | ||
git apply native_ldc_arm | git apply native_ldc_arm | ||
− | cd ../../../ldc/build/ | + | cd ../../../ldc/runtime/druntime/ |
+ | curl -O https://gist.githubusercontent.com/joakim-noah/348edc378d47fb90e32708be19286a2e/raw/2b473ff45ff4abc68852ebb1868354b8528026e0/druntime_1.3_ldc_arm | ||
+ | git apply druntime_1.3_ldc_arm | ||
+ | |||
+ | cd ../../build/ | ||
make test-runner-apk | make test-runner-apk | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 214: | Line 158: | ||
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
cd ../../android/samples/native-activity/ | cd ../../android/samples/native-activity/ | ||
+ | export SDK=/path/to/your/android-sdk-linux | ||
+ | $SDK/tools/android update project -p . -s --target 1 | ||
ant debug | ant debug | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Transfer the resulting bin/NativeActivity-debug.apk to your device | + | Transfer the resulting bin/NativeActivity-debug.apk to your device and install it. Also, copy [https://github.com/joakim-noah/android/releases/download/tea/test.list the list of modules to test] to the /sdcard/ directory. The app will append its results to /sdcard/test.log, so if you happen to have a file with that name, move it. |
− | + | The app should show a black screen for about a minute, while all the tests run. A touch after that and it should start flashing a bunch of colors. If not, look at the output in /sdcard/test.log and check if the app hung after any particular tested module. You can remove that module from test.list and try running again. | |
==Directions for future work== | ==Directions for future work== | ||
* You may notice that I added an empty main function in the D translation of the C sample app: that's a hack to build a shared library. The linux shared library support in druntime's rt.sections_elf_shared may eventually be integrated with Android to get rid of that. | * You may notice that I added an empty main function in the D translation of the C sample app: that's a hack to build a shared library. The linux shared library support in druntime's rt.sections_elf_shared may eventually be integrated with Android to get rid of that. | ||
− | * Now that we can write D code for Android, it'll make building easier if the D cross-compilers are integrated with a build tool, like [https://github.com/atilaneves/reggae reggae] or [http://jasonwhite.github.io/button | + | * Now that we can write D code for Android, it'll make building easier if the D cross-compilers are integrated with a build tool, like [https://github.com/dlang/dub dub], |
+ | [https://github.com/atilaneves/reggae reggae], or [http://jasonwhite.github.io/button Button]. | ||
[[Category:LDC]] | [[Category:LDC]] | ||
[[Category: Android]] | [[Category: Android]] |
Revision as of 10:07, 25 August 2017
This page will show you how to build an ldc cross-compiler for Android/ARM on linux or Windows 10 (by using the new bash on linux subsystem), along with how to build and run the standard library's tests using the cross-compiler, both as a command-line binary and as a GUI Android app. Prebuilt native and cross-compilers are available here.
All of the standard library's unit tests and the full compiler testsuite passes on Android/ARM. Remaining work to be done is listed last.
Contents
Prerequisites
- linux/x64 shell, where you'll build and run ldc
- You can use a virtual machine like VirtualBox/VMware, with at least 512 MB of memory and 1 GB of swap, particularly if building the phobos unit tests, and 10 GB of disk space.
- Windows 10: You can alternately use Bash on Windows (the Windows Subsystem for Linux)
- C++ compiler and toolchain, to build a slightly patched llvm and parts of ldc
- A pre-built D compiler for linux, as the ldc frontend is written in D.
- You can get the official dmd release for linux or one of the ldc releases for linux. Many distros also have D compiler packages.
- Common development tools, such as CMake and git
- ldc/druntime/phobos source
- Get the source using git, as these Android patches were tested on the release-1.3.x branch
- llvm 4.0.1 source, lightly tweaked for ldc
- Android native toolchain, the NDK and optionally the SDK
- The SDK is only needed if you want to package a GUI app; the NDK is enough if you just want to build a command-line binary, such as a test runner.
- Android/ARM, whether a device or emulator
- The SDK comes with an emulator. I use actual hardware, so that's what I'll discuss.
Notes for Bash on Ubuntu on Windows
- Necessary packages
sudo apt-get install build-essential
sudo apt-get install git
sudo apt-get install cmake
sudo apt-get install unzip
sudo apt-get install libconfig-dev
- DMD Compiler
cd ~
curl -L -O http://downloads.dlang.org/releases/2.x/2.075.1/dmd_2.075.1-0_amd64.deb
sudo dpkg -i dmd_2.075.1-0_amd64.deb
- Android Native Development Kit
sudo mkdir -p /opt/android-sdk/ndk-bundle
curl -L -O https://dl.google.com/android/repository/android-ndk-r15c-linux-x86_64.zip
sudo unzip android-ndk-r15c-linux-x86_64.zip 'android-ndk-r15c/*' -d /opt/android-sdk/ndk-bundle
export NDK=/opt/android-sdk/ndk-bundle/android-ndk-r15c
As Windows Subsystem for Linux does not support USB, you have to install Android SDK and Ant on your Windows system and execute the commands "android" and "ant" from your DOS console.
Compile llvm
Get the source for llvm, either this lightly tweaked llvm 4.0.1 source tarfile or the git repository for that tweaked branch. Build llvm as you would normally, with the ARM, AArch64, and X86 targets, for Android/ARM as the default target, and leaving out tools and utilities you don't need:
curl -L -O https://github.com/ldc-developers/llvm/releases/download/ldc-v4.0.1/llvm-4.0.1.src.tar.xz
tar xvf llvm-4.0.1.src.tar.xz
cd llvm-4.0.1.src/
mkdir build
cd build/
cmake .. -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="ARM;AArch64;X86" -DLLVM_DEFAULT_TARGET_TRIPLE=armv7-none-linux-android -DLLVM_BUILD_TOOLS=OFF -DLLVM_BUILD_UTILS=OFF
make all llvm-config -j5
Build ldc for Android/ARM
Clone the ldc repository, apply the Android patch, set the DMD and NDK environment variables to the paths of your pre-built D compiler and NDK install, and build ldc as usual:
cd ../../
git clone --recursive https://github.com/ldc-developers/ldc.git
cd ldc/
git checkout -b ldc13 origin/release-1.3.x
git submodule update
curl -O https://gist.githubusercontent.com/joakim-noah/d74af3cf1355492557a9c56ef1bf2636/raw/a0ac30302b5d7cc47049fb5ef88a87ec9afab824/ldc_1.3_android_arm
git apply ldc_1.3_android_arm
mkdir build
cd build/
export DMD=/path/to/your/dmd2/linux/bin64/dmd
export NDK=/path/to/your/android-ndk-r15b
cmake .. -DLLVM_CONFIG=../../llvm-4.0.1.src/build/bin/llvm-config
make ldc2 -j5
Download and apply a small patch for the standard library, phobos, before building the D runtime and stdlib:
cd ../runtime/phobos/
curl -O https://gist.githubusercontent.com/joakim-noah/09a59bdd6e04dd2f3d3ad6e15573ad97/raw/ba5bd391f1e9b669599c4d4939542512400ac934/phobos_1.3_ldc_arm
git apply phobos_1.3_ldc_arm
cd ../../build/
make druntime-ldc phobos2-ldc -j5
More info about the Android/ARM patches can be found with their release.
You can now try cross-compiling a sample program as shown here. You will need a terminal emulator Android app and to set the path to the LDC cross-compiler and libraries you just built:
export LDC=/path/to/your/ldc/build
Run the druntime and phobos unit tests
You can build the druntime and phobos unit tests and run the command-line test runner binaries on Android (don't add the -j5 flag to build in parallel unless you have gigabytes of memory available, as compiling some of the phobos modules' tests takes a fair amount of RAM):
make druntime-test-runner phobos2-test-runner
Copy the test runners to your device and run them. Assuming you have an SSH server set up on the computer where you're building with the linux shell and its IP address is 192.168.35.7, you can scp the binaries into the Termux Android app with these commands and run the tests:
apt install openssh
scp jo@192.168.35.7:"/path/to/your/ldc/build/runtime/{druntime,phobos2}-test-runner" .
./druntime-test-runner
./phobos2-testrunner
The tests take about 25 seconds to run on my quad-core tablet: all should pass. One module, core.sync.semaphore, will fail for any Android older than 6.0, because sem_destroy used to work differently in bionic. You can also run the tests for specified modules by passing their names to the test runner:
./druntime-test-runner core.thread core.sync.semaphore
./phobos2-testrunner std.datetime std.random
Run the druntime and phobos unit tests in an apk
You can also run the tests as part of a GUI app, ie an apk, which is a slightly different runtime environment. First, you can try cross-compiling a sample GUI app from the NDK that has been translated from C to D, as shown here. That simple OpenGLES 1.0 GUI app can be modified to run all the tests, which is what we'll do next. Clone my Android repo, if you haven't already, go to the native-activity sample app, and create the output directory the SDK expects:
cd ../../
git clone https://github.com/joakim-noah/android.git
cd android/samples/native-activity/
mkdir -p libs/armeabi-v7a/
Download and apply a small patch to have the sample app invoke the test runner and a patch for the test runner in druntime, then build the tests into a shared library this time:
curl -O https://gist.githubusercontent.com/joakim-noah/8ba3cd4958266f357295/raw/a52fcf1e63715f8b1bd3527afaa85872087b0f30/native_ldc_arm
git apply native_ldc_arm
cd ../../../ldc/runtime/druntime/
curl -O https://gist.githubusercontent.com/joakim-noah/348edc378d47fb90e32708be19286a2e/raw/2b473ff45ff4abc68852ebb1868354b8528026e0/druntime_1.3_ldc_arm
git apply druntime_1.3_ldc_arm
cd ../../build/
make test-runner-apk
This assumes that the ldc and android repositories are in the same directory, as shown in these instructions. If not, modify ANDROID_DIR in the CMake build script to use the path you want.
Finally, package the test runner apk:
cd ../../android/samples/native-activity/
export SDK=/path/to/your/android-sdk-linux
$SDK/tools/android update project -p . -s --target 1
ant debug
Transfer the resulting bin/NativeActivity-debug.apk to your device and install it. Also, copy the list of modules to test to the /sdcard/ directory. The app will append its results to /sdcard/test.log, so if you happen to have a file with that name, move it.
The app should show a black screen for about a minute, while all the tests run. A touch after that and it should start flashing a bunch of colors. If not, look at the output in /sdcard/test.log and check if the app hung after any particular tested module. You can remove that module from test.list and try running again.
Directions for future work
- You may notice that I added an empty main function in the D translation of the C sample app: that's a hack to build a shared library. The linux shared library support in druntime's rt.sections_elf_shared may eventually be integrated with Android to get rid of that.
- Now that we can write D code for Android, it'll make building easier if the D cross-compilers are integrated with a build tool, like dub,
reggae, or Button.