Compile Kaldi for 64-bit Android on Ubuntu 18
- This note is based on this amazing blog post and this amazing github repo with a few modifications towards 64-bit ARM architecture.
Recently I spent quite a lot of time learning how to run kaldi on Android with absolutely no idea about Android development or Java. After reading a few blog posts, github repos and running into a lot of problems, here is some notes on how I got it working at last. I hope this post will be helpful for anyone who is facing the same challenge as I did.
Setup Android NDK r17 arm64 toolchain
Download Android NDK r17 package
A list of Android NDK packages can be found here, use the following command to download the r17 package:
wget -q --output-document=android-ndk.zip https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip
Make toolchain
After unzipping android-ndk.zip
, make the standalone toolchain by running:
$NDK/build/tools/make_standalone_toolchain.py \
--arch arm64 \
--api 21 \
--install-dir=arm64-toolchain
where $NDK
is the unzipped folder of android ndk, arm64-toolchain
is where you want to output your toolchain to.
Compile OpenBLAS
Download and checkout the right release
git clone https://github.com/xianyi/OpenBLAS
cd OpenBLAS
git checkout release-0.2.21
Install gfortran
sudo apt-get install gfortran
Build for ARMV8 use CLANG
First we need to add the toolchain into PATH
:
export ANDROID_TOOLCHAIN_PATH=/path/to/arm64-toolchain
export PATH=$ANDROID_TOOLCHAIN_PATH/bin:$PATH
Setup clang flags:
export CLANG_FLAGS="-target aarch64-linux-android --sysroot ${ANDROID_TOOLCHAIN_PATH}/sysroot -gcc-toolchain ${ANDROID_TOOLCHAIN_PATH}"
Compile:
make TARGET=ARMV8 ONLY_CBLAS=1 AR=ar CC="clang ${CLANG_FLAGS}" HOSTCC=gcc -j4
Make install:
make install NO_SHARED=1 PREFIX=`pwd`/install
Notes:
- If you see an error message says
1 at ./c_check line 29
. Make sure your toolchain is in thePATH
. - The instructions provided by OpenBLAS is meant for NDK r19 or newer, which follows a different procesds for build toolchains. For some reason I could not compile with r20 suceessfully follow the instructions, a stdio.h not found error kept popping up.
Compile CLAPACK
git clone https://github.com/simonlynen/android_libs.git
cd android_libs/lapack
# remove some compile instructions related to tests
sed -i 's/LOCAL_MODULE:= testlapack/#LOCAL_MODULE:= testlapack/g' jni/Android.mk
sed -i 's/LOCAL_SRC_FILES:= testclapack.cpp/#LOCAL_SRC_FILES:= testclapack.cpp/g' jni/Android.mk
sed -i 's/LOCAL_STATIC_LIBRARIES := lapack/#LOCAL_STATIC_LIBRARIES := lapack/g' jni/Android.mk
sed -i 's/include $(BUILD_SHARED_LIBRARY)/#include $(BUILD_SHARED_LIBRARY)/g' jni/Android.mk
There is a few things we need to modify here before building it:
- Modify
AndroidManifest.xml
, changeandroid:minSdkVersion=”10"
toandroid:minSdkVersion=”21"
, which is the right version of our NDK API. - Modify
prject.properties
, changetarget=android-10
totarget=android-21
. - Modify
jni/Application.mk
, changeAPP_ABI := armeabi armeabi-v7a
toAPP_ABI := arm64-v8a
.
Then we should be able to build it by running:
$NDK/ndk-build
where $NDK
is the unzipped folder of android ndk.
If it is successfully built, we will be able to find a bunch if .a
libs inside obj/local/arm64-v8a
. Copy all libs to OpenBLAS/insall/lib
.
Compile kaldi
There are two steps in compiling Kaldi, compile OpenFST and compile kaldi source.
Download kaldi
git clone https://github.com/kaldi-asr/kaldi.git kaldi-android
Compile OpenFST
export PATH=/path/to/arm64-toolchain/bin:$PATH
cd kaldi-android/tools
wget -T 10 -t 1 http://openfst.cs.nyu.edu/twiki/pub/FST/FstDownload/openfst-1.6.7.tar.gz
tar -zxvf openfst-1.6.7.tar.gz
cd openfst-1.6.7/
CXX=clang++ ./configure --prefix=`pwd` --enable-static --enable-shared --enable-far --enable-ngram-fsts --host=aarch64-linux-android LIBS="-ldl"
make -j 4
make install
cd ..
ln -s openfst-1.6.7 openfst
Notes:
- OpenFST version might change based on Kaldi version, it can be found by searching
OPENFST_VERSION
intools/Makefile
. - I encountered a
libfstfar.so not found
error when compilingsrc/extension/far
, it can be solved by copy.so
libs undersrc/extension/far/.libs
toopenfst-1.6.7/libs
.
Compile kaldi source
cd ../src
CXX=clang++ ./configure --static --android-incdir=$NDK_TOOLCHAIN/sysroot/usr/include/ --host=aarch64-linux-android --openblas-root=$OPENBLAS/install --use-cuda=no --shared
make clean -j
make depend -j
make -j
Make sure to set $NDK_TOOLCHAIN
and $OPENBLAS
correctly. You will be able to find .so
libs under src/lib
after compilation.
So far we have already successfully compiled kaldi for 64-bit Android, I will include a short walkthrough on how to run an amazing demo on Android Studio.
Compile libkaldi_jni.so
Download the source
In order to run the demo, we need to compile a libkaldi_jni.so
first.
git clone https://github.com/alphacep/kaldi-android.git
Note: make sure to change the folder name or clone to a different folder, so that it won’t conflict with the previouskaldi-android
repo.
Prepare files
Create a local.properties
file with the following line in it:
sdk.dir = /path/to/Android/Sdk
where /path/to/Android/Sdk
is where your Android Sdk is, for example mine is at /home/qianhui/Android/Sdk
.
Modify build.gradle
:
- Comment out the following block since we already built kaldi.
task kaldi(type: Exec) {
commandLine ‘./build-kaldi.sh’
}
- Remove
kaldi
frompreBuild.dependsOn mkdir, kaldi, swig
. - Change
abiFilters ‘armeabi-v7a’
toabiFilters ‘arm64-v8a’
. - Modify
CMakeList.txt
, make sure the path to OpenBLAS, OpenFST libs are correctly. Also changelibopenblas_armv7-r0.3.8.dev.a
tolibopenblas_armv8p-r0.2.20.a
(you can verify the filename by looking into$OPENBLAS/install/lib
).
Build
Build the library use gradle
, here is a blog post on how to install gradle
and jdk
on Ubuntu18.04.
gradle build
Two files created are needed for later:
build/library_and_local_jars_jni/release/arm64-v8a/libkaldi_jni.so
build/outputs/aar/kaldi-android-5.2.aar
Run kaldi-android-demo
kaldi-android-demo
is a runnable demo for Kaldi android, it’s a very good start point to learn about kaldi android development.
Download the source
git clone https://github.com/alphacep/kaldi-android-demo.git
Copy and replace libs
- First replace
kaldi-android-5.2.aar
inaars
with the one we just built. - Create a folder called
jniLibs
underapp/src/main
, then create another folder calledarm64-v8a
underjniLibs
. Here is where Android Studio look for libraries when running the project. - Copy
libkaldi_jni.so
and all files inkaldi/src/lib
toarm64-v8a
we just created.
Import the project into Android Studio
Connect your 64-bit Android device or use a 64-bit ARM emulator (which can be very slow) then hit Run (green triangle play button).
The project will start building and you can see logs under Build and Logcat incase there is any error message.
If the app is successfully built and installed, you will be able to see a kaldi-android app on your phone and test it right away!
This has been a very good learning experience for me to get familiar with Android development. If I were to sum up the process in a few steps:
- Compile dependencies (OpenBLAS, OpenFST, Kaldi, etc.) with the right architecture (armv7, armv8, x86, etc.)
- Write module, build it with gradle.
- Use the module to write the final app.