Posted on

Compiling C/C++ libraries for Android (updated)

There are a few forms a C/C++ library that you want to cross compile to Android might come in.

For instance:

  • An Autotools project
  • A CMake project

To get started let’s make a standalone Android toolchain (a toolchain being compilers, libraries and headers for cross compiling our source code to a specific target architecture and platform ABI) .

Making a standalone toolchain

Firstly you’ll need to download and install the Android NDK (see here). The Android NDK comes bundled with a script that will generate a standalone toolchain for cross compilation (see here). By default, specifying –arch=arm will default clang to target the armeabi-v7a ABI.

# set ANDROID_NDK_HOME
export ANDROID_NDK_HOME="/Users/benmorris/Library/Android/sdk/ndk-bundle/"

# make the toolchain
${ANDROID_NDK_HOME}/build/tools/make-standalone-toolchain.sh --arch=arm --platform=android-21 --install-dir=android-toolchain --stl=libc++

# add the toolchain to our path
export PATH="$PATH:`pwd -P`/android-toolchain/bin"

# set target architecture (used by ./configure)
export CHOST="arm-linux-androideabi"

Cross compiling an autotools based project to Android

Having made our standalone toolchain above, let’s compile zlib for Android using the toolchain (Zlib is precompiled and available in the standalone toolchain’s sysroot but lets recompile it here for demonstration purposes). In the same shell session that we used to create our toolchain we first need to set some variables (used by configure) to ensure our toolchain’s compiler (and supporting utilities) are detected:

export CC="arm-linux-androideabi-clang"
export CXX="arm-linux-androideabi-clang++"
export RANLIB="arm-linux-androideabi-ranlib"
export LD="arm-linux-androideabi-ld"
export AR="arm-linux-androideabi-ar"
export ARFLAGS="cr"
export CHOST="arm-linux-androideabi"

Now we are ready to go ahead and build the library.

# download and extract zlib
wget http://zlib.net/zlib-1.2.11.tar.gz
tar zxf zlib-1.2.11.tar.gz

# configure and make it
cd zlib-1.2.11
./configure
make

We can confirm that our library’s object file’s format is expected by inspecting it using the toolchain supplied nm tool:

../android-toolchain/bin/arm-linux-androideabi-nm libz.a

You should be able to see the library’s data, symbols, exported and imported function names.

Cross compiling a CMake based project to Android

For a CMake based project we’ll need to tell CMake how to find the standalone toolchain we created above. We do this by providing cmake with the path to the toolchain we want to use through the variables CMAKE_SYSTEM_NAME, CMAKE_SYSTEM_VERSION and CMAKE_ANDROID_STANDALONE_TOOLCHAIN. For demonstration purposes, in the same shell session that we created the standalone toolchain in let’s compile a CMake based project for Android using the toolchain we created above:

wget https://sourceforge.net/projects/assimp/files/assimp-3.1/assimp-3.1.1_no_test_models.zip
unzip assimp-3.1.1_no_test_models.zip
cd assimp-3.1.1

cmake ./ \
  -DCMAKE_SYSTEM_NAME=Android \
  -DCMAKE_SYSTEM_VERSION=21 \
  -DCMAKE_ANDROID_STANDALONE_TOOLCHAIN=`pwd -P`/../android-toolchain \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_INSTALL_PREFIX=`pwd -P`/build \
  -DASSIMP_BUILD_STATIC_LIB="On" \
  -DBUILD_SHARED_LIBS="Off"

cmake --build . --config Release && make install