The previous recipe covered how to port a command-line executable to Android with an NDK build system. This recipe describes how to do it by using the Android NDK toolchain as a standalone compiler.
It is recommended that you read the Porting a library with its existing build system recipe in Chapter 8, Porting and Using Existing Libraries with Android NDK, before continuing.
The following steps describe how to port the fusch
program to Android by using the NDK toolchain directly:
cookbook.chapter9.portingexecutablebuildsystem
. Refer to the Loading native libraries and registering native methods recipe of Chapter 2, Java Native Interface, if you want more detailed instructions.jni
folder of the project.fusch
library and the command-line application from http://fugenschnitzer.sourceforge.net/main_en.html. Extract the archive files and put them into the jni/fusch
and jni/fusch_lib
folders respectively.libpng 1.2.50
from http://sourceforge.net/projects/libpng/files/libpng12/1.2.50/ and extract the files to the jni/libpng-1.2.50
folder. The latest version of libpng
won't work because the interface has changed. Replace the config.guess
script under libpng-1.2.50
with the one at http://gcc.gnu.org/svn/gcc/branches/cilkplus/config.guess and config.sub
with the script at http://gcc.gnu.org/svn/gcc/branches/cilkplus/config.sub.build_android.sh
file under the jni/libpng-1.2.50
folder to build libpng
. The file has the following content:#!/bin/bash NDK=~/Desktop/android/android-ndk-r8b SYSROOT=$NDK/platforms/android-8/arch-arm/ export CFLAGS="-fpic -ffunction-sections -funwind-tables -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -DANDROID -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64" export LDFLAGS="-lz" export CC="$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc --sysroot=$SYSROOT" ./configure --host=arm-linux-androideabi --prefix=$(pwd) --exec-prefix=$(pwd) --enable-shared=false --enable-static=true make clean make make install
build_android.sh
file under the jni/fusch_lib
folder to build the library libseamcarv
. The file content is as follows:#!/bin/bash NDK=~/Desktop/android/android-ndk-r8b SYSROOT=$NDK/platforms/android-8/arch-arm/ export CFLAGS="-fpic -ffunction-sections -funwind-tables -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -std=c99 -DANDROID " export CC="$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc --sysroot=$SYSROOT" AR="$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-ar" SRC_FILES=" sc_core.c sc_carve.c sc_color.c sc_shift.c sc_mgmnt.c seamcarv.c" $CC $SRC_FILES $CFLAGS -c $AR cr libseamcarv.a *.o
build_android.sh
file under the jni/fusch
folder to build the fusch
executable, which uses the two static libraries built at the two folders libpng-1.2.50
and fusch_lib
.#!/bin/bash NDK=~/Desktop/android/android-ndk-r8b SYSROOT=$NDK/platforms/android-8/arch-arm CUR_D=$(pwd) export CFLAGS="-fpic -ffunction-sections -funwind-tables -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -std=c99 -DANDROID -I$CUR_D/../fusch_lib -I$CUR_D/../libpng-1.2.50/include" export LDFLAGS="-Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -lz -lc -lm -lpng -lseamcarv -L$CUR_D/../fusch_lib -L$CUR_D/../libpng-1.2.50/lib" export CC="$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc --sysroot=$SYSROOT" SRC_FILES="fusch.c" $CC $SRC_FILES $CFLAGS $LDFLAGS -o fusch
libpng
and libseamcarv
and the fusch
executable by executing the build_android.sh
script in the three subfolders libpng-1.2.50
, fusch_lib
, and fusch
. We shall find libpng.a
under the libpng-1.2.50/lib
folder, libseamcarv.a
under the fusch_lib
folder, and the fusch
executable under the fusch
folder.fusch
to a rooted Android device or an emulator with the following command:$ cd <path to project folder>/PortingExecutableBuildSystem/jni/fusch $ adb push fusch /data/data/
$ adb shell # cd /data/data # chmod 755 fusch # ./fusch
cookbook_ch9_test.png
(available under the assets
folder of the sample project's source code) to the testing device or emulator with the following command:$ adb push cookbook_ch9_test.png /data/data/
fusch
program again with the following command:# ./fusch cookbook_ch9_test.png 1.png v-200
$ adb pull /data/data/1.png .
The sample project shows how to port a command-line executable to Android by using the NDK toolchain as a standalone compiler.
The steps to port the executable are similar to those in the previous recipe where we used the Android NDK build system. The key here is to pass proper options to the standalone compiler.
libpng
comes with its own build scripts. We can get a list of options to configure the building process with the following command:
$ ./configure –help
The compiler command, compiler flags, and linker flags can be configured with the environment variables CC
, CFLAGS
, and LDFLAGS
respectively. In the build_android.sh
script under the libpng-1.2.50
folder, we set these variables to use the NDK compiler to build for the ARM architecture. For a detailed explanation of how to port a library, we can refer to the Porting a library with its existing build system using Android NDK toolchain recipe in Chapter 8, Porting a Library with its Existing Build System.
We will now cover a few compilation options. Since the Android NDK toolchain is based on GCC, we can refer to http://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html for a detailed explanation of each option.
-fpic
: It generates position-independent code suitable for building a shared library.-ffunction-sections
: This option asks the linker to perform optimizations to improve the locality of reference in the code.-funwind-tables
: It generates static data for unwinding the call stack.-D__ARM_ARCH_5__
, -D__ARM_ARCH_5T
, -D__ARM_ARCH_5E__
, -D__ARM_ARCH_5TE
,-DANDROID
defines __ARM_ARCH_5__
, __ARM_ARCH_5T
, __ARM_ARCH_5E__
, __ARM_ARCH_5TE
, and ANDROID
as macro, with definition equal to 1
. For example, -DANDROID
is equivalent to -D ANDROID=1
.-Wno-psabi
: It suppresses the warning message about va_list
and so on.-march=armv5te
: It specifies the target ARM architecture as ARMv5te
.-mtune=xscale
: It tunes the performance of the code as it will be running on the xscale processor. Note that xscale is a processor name.-msoft-float
: It uses software floating point functions.-mthumb
: It generates code using the Thumb instruction set.-Os
: It provides optimization for size.-fomit-frame-pointer
: It helps avoid saving frame pointers in registers if possible.-fno-strict-aliasing
: No strict aliasing rules can be applied. This prevents the compiler from unwanted optimizations.-finline-limit=64
: It sets the limit size of functions that can be inlined as 64
pseudo instructions.-std=c99
: It accepts c99
standard syntax.When the build executes successfully, we can find the libpng.a
static library under the libpng-1.2.50/lib
folder and the header files under the libpng-1.2.50/include
folder.
The Android NDK build system essentially figures out the proper compilation options for us and invokes the cross compiler for us. Therefore, we can learn the options to pass to the compiler from the NDK build system output. For example, we can invoke the command ndk-build -B V=1
or ndk-build -B -n
in the previous recipe to see how the NDK build system handles the building of libpng
, libseamcarv
, and fusch
, and apply similar options in this recipe.
libseamcarv
comes with a Makefile but no configure file. We can either modify the Makefile or write a build script from scratch. Since the library only contains a few files, we will write the build script directly. There are two steps to be followed:
"-c
" option at compilation.arm-linux-androideabi-ar
from the NDK toolchain.As we have explained in Chapter 8, Porting and Using Existing Libraries with Android NDK, a static library is simply an archive of object files, which can be created by the archiver
program.
We need to link to the two libraries we built, namely libpng
and libseamcarv
. This is done by passing the following options to the linker:
-lpng -lseamcarv -L$CUR_D/../fusch_lib -L$CUR_D/../libpng-1.2.50/lib
This "-L
" option adds fusch_lib
and libpng-1.2.50/lib
to the library's search path and "-l
" tells the linker to link to the libpng
and libseamcarv
libraries. The build script will output a binary file named fusch
under the fusch
folder.
The fusch
program is fairly simple. Therefore, we can use either the Android NDK build system or a standalone compiler to port it. If an application has more dependencies, it can be difficult to describe everything in Android.mk
files. Therefore, it is helpful that we can use the NDK toolchain as a standalone compiler and make use of a library's existing build scripts.