Compile Kaldi for 64-bit Android on Ubuntu 18

Qianhui Wan
The Startup
Published in
5 min readOct 17, 2019

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 the PATH .
  • 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:

  1. Modify AndroidManifest.xml, change android:minSdkVersion=”10" to android:minSdkVersion=”21" , which is the right version of our NDK API.
  2. Modify prject.properties, change target=android-10 to target=android-21.
  3. Modify jni/Application.mk, change APP_ABI := armeabi armeabi-v7a to APP_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 in tools/Makefile.
  • I encountered a libfstfar.so not founderror when compiling src/extension/far, it can be solved by copy .so libs under src/extension/far/.libs to openfst-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 from preBuild.dependsOn mkdir, kaldi, swig.
  • Change abiFilters ‘armeabi-v7a’ to abiFilters ‘arm64-v8a’.
  • Modify CMakeList.txt, make sure the path to OpenBLAS, OpenFST libs are correctly. Also change libopenblas_armv7-r0.3.8.dev.a to libopenblas_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 in aars with the one we just built.
  • Create a folder called jniLibs under app/src/main, then create another folder called arm64-v8a under jniLibs. Here is where Android Studio look for libraries when running the project.
  • Copy libkaldi_jni.so and all files in kaldi/src/lib to arm64-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.

--

--

Qianhui Wan
The Startup

Machine Learning | Speech Recognition | Data Science