The header libraries from the previous section provide the required files to compile the code. However, you also need the system image shared libraries for the linking process; that is, you need the *.so files stored in /system/lib in your device. For example, using the emulator shell, you can take a look at device file systems and some of the system libraries. Using the Android Debug Bridge (adb), connect to the device, and then run the df command to inspect the device file systems, as shown in the next fragment:
user@ubuntu:~$ adb shell
# df
/dev: 47284K total, 0K used, 47284K available (block size 4096)
/sqlite_stmt_journals: 4096K total, 0K used, 4096K available (block size 4096) /system: 65536K total, 43496K used, 22040K available (block size 4096)
/data: 65536K total, 43004K used, 22532K available (block size 4096) /cache: 65536K total, 1156K used, 64380K available (block size 4096) /sdcard: 40309K total, 34114K used, 6195K available (block size 512)
# ls -l /system/lib
-rw-r--r-- root root 9076 2008-11-20 00:10 libdl.so -rw-r--r-- root root 227480 2008-11-20 00:10 libc.so
-rw-r--r-- root root 13368 2008-11-20 00:10 libthread_db.so -rw-r--r-- root root 9220 2008-11-20 00:10 libstdc++.so -rw-r--r-- root root 140244 2008-11-20 00:10 libm.so -rw-r--r-- root root 79192 2008-11-20 00:10 libz.so -rw-r--r-- root root 92572 2008-11-20 00:10 libexpat.so -rw-r--r-- root root 767020 2008-11-20 00:10 libcrypto.so -rw-r--r-- root root 155760 2008-11-20 00:10 libssl.so [Other files...]
The df command displays information about the device file systems. From there, you can inspect the libraries stored in the device /system/lib folder. The ls command shows the most important libraries: C runtime (libc.so), Math runtime (libm.so), Gzip (libz.so), XML (libexpat.so), and others.
These are the files you need to extract to the local system for the linking step. To extract them, you can create a simple script and use the emulator tool adb pull command to pull a file from the device to the local file system.
First, create a folder in your home directory to store these libraries:
$ mkdir -p $HOME/tmp/android/system/lib
$ cd $HOME/tmp/android/system/lib
Next, create a simple script to fetch the files from the device to the $HOME/tmp/android/system/lib folder. The bash script in Listing 1-1 loops through the library names and pulls the file from the device /system/lib folder to the local file system current directory.
8
Listing 1-1. Script to Fetch Device Libraries from /system/lib into the Local File System
#!/bin/bash
# Device libraries for Emulator 1.5+
# These are located in/system/lib
libs="browsertestplugin.so libEGL.so libFFTEm.so
libGLESv1_CM.so libaes.so libagl.so libandroid_runtime.so libandroid_servers.so libaudioflinger.so libc.so libc_debug.so libcameraservice.so libcorecg.so libcrypto.so
libctest.so libcutils.so libdl.so libdrm1.so libdrm1_jni.so libdvm.so libemoji.so
libexif.so libexpat.so libhardware.so libhardware_legacy.so libicudata.so libicui18n.so libicuuc.so libjni_latinime.so libjni_pinyinime.so liblog.so libm.so libmedia.so libmedia_jni.so libmediaplayerservice.so libnativehelper.so libnetutils.so libopencoreauthor.so libopencorecommon.so libopencoredownload.so libopencoredownloadreg.so libopencoremp4.so libopencoremp4reg.so libopencorenet_support.so libopencoreplayer.so libopencorertsp.so libopencorertspreg.so libpagemap.so libpixelflinger.so
libpvasf.so libpvasfreg.so libreference-ril.so libril.so libsgl.so libskiagl.so libsonivox.so libsoundpool.so libsqlite.so
libsrec_jni.so libssl.so libstdc++.so libsurfaceflinger.so libsystem_server.so libthread_db.so libui.so
libutils.so libvorbisidec.so libwbxml.so libwbxml_jni.so libwebcore.so libwpa_client.so libxml2wbxml.so libz.so"
# Loop thru lib names
Installing the GNU Toolchain for ARM Processors
So far, so good. You have the Android source and the libraries for the device. The final software you need is a C compiler. This tool provides the C library, binary utilities, preprocessor, compiler, debugger, profiler, and linker required to build software for the ARM hardware used by the Android device. You will use the toolchain provided by the Sourcery G++ Lite Edition for ARM (http://www.codesourcery.com/
sgpp/lite/arm/portal/subscription?@template=lite).
You have two choices:
• Download the easy installer (see Figure 1-2).
• Get the tool in tar format and simply unzip it in your system. (I prefer to do it this way, as it is much faster).
If you choose to install from the tarball, you can unzip the archive on your desktop using the following command:
9
$ cd $HOME/Desktop
$ tar zxvf arm-2008q3-72-arm-none-linux-gnueabi.tar.gz
Either way you choose to install the toolchain, you must add the bin folder to your system path so the toolchain can be invoked from the console. Add the following text to your $HOME/.bashrc file:
ARM_HOME=$HOME/Desktop/arm-2008q3 export PATH=$PATH:$ARM_HOME/bin
Figure 1-2. Sourcery G++ Lite installer
Now you should have the toolchain ready for use. Perform a quick test by typing the following:
user@ubuntu:~$ arm-none-linux-gnueabi-gcc --version
arm-none-linux-gnueabi-gcc (Sourcery G++ Lite 2008q3-72) 4.3.2 Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
Let’s take a quick look at some of the most useful commands provided by the toolchain:
• arm-none-linux-gnueabi-gcc: This is the C compiler and is equivalent to the Linux gcc command. Most of the options are very close to those provided by its Linux counterpart.
• arm-none-linux-gnueabi-g++: This is the C++ compiler, which wraps the gcc command with extra options for C++.
• arm-none-linux-gnueabi-ld: This is the linker used to build a final binary, either as a monolithic file (statically) or as a shared library (dynamically).
• arm-none-linux-gnueabi-objdump: This displays information about binary files.
• arm-none-linux-gnueabi-strip: This removes symbols and sections from binary files, including symbol and relocation information, debugging symbols and sections, nonglobal symbols, and others. This can help to reduce the size of the final executable.
For example, arm-none-linux-gnueabi-objdump is a very useful tool for peeking into your binaries. It shows you information such as the following:
• Archive header information
• Contents of the overall file header
• Assembler contents of executable sections
• Intermix source code with disassembly
• Contents of the dynamic symbol table
• Relocation entries in the file
So, to display symbol table information about the device C runtime (libc.so) pulled from the device into $HOME/tmp/android/system/lib, use this command:
$ arm-none-linux-gnueabi-objdump -T ~/tmp/android/system/lib/libc.so
DYNAMIC SYMBOL TABLE:
00008560 l d .text 00000000 .text 0002c638 l d .rodata 00000000 .rodata 00032264 l d .ARM.extab 00000000 .ARM.extab 00035004 l d .data.rel.ro 00000000 .data.rel.ro 00035e58 l d .data 00000000 .data
000370e4 l d .bss 00000000 .bss 000195ec g DF .text 00000034 getwchar 0000d134 g DF .text 00000000 longjmp ...
A command like this can help you detect symbols used by your program but missing from the device standard libraries.
11
As you can see, the toolchain mirrors the GNU GCC toolchain. In fact, the only noticeable difference is that all the commands start with the prefix arm-none-linux-gnueabi.With the toolchain in place, the last piece is a set of custom scripts to invoke the preceding commands.