2010年5月8日 星期六

cross compile Android native C code

當需要建立一些指令列工具,需要自行 build code 在 Android
command line 上執行,或供應用程式透過 JNI 呼叫的函式庫時,
需要 cross compile android native C program

1. agcc, 一個幫你搞定 cross compile 所需複雜參數的 perl script,依照
Compiling for Android wiki 上的步驟,應該就可以成功

2. 如果幸運的話,你可以不用往下看,不然就繼續吧,假如 agcc
不能達要你的需求,網路上也有神人已經寫了 Makefile 再加上 1. 裡
面的其他設定設好,以及你所使用平台的 C runtime library,在
~android/bionic/libc/arch-arm/bionic 底下 copy crtbegin_dynamic.S,
crtend.S 到你的 utility source 目錄,一起 link 就可以從正確的 entry symbol
__start 執行。否則直接拿 x86 cross compile 給 arm 平台的程式時
會有類似以下的警告訊息:

warning: cannot find entry symbol _start; defaulting to 000082c8

3. add scripts to ease rebuild native C code and installation,要將 utility
包 到 system.img 時需要先移除 ~android/out/target/product/arm/system.img
再將新加的 utility 放到 ~android/out/target/product/arm/system/bin
重新 build android,因為前面已經將其他 object files build 完,所以只剩下
archive system.img 的工作。

因此再借用神人的 my_command_line utility Makefile 改成如下:


# ripped from http://forum.xda-developers.com/archive/index.php/t-623976.html
AR = arm-eabi-ar
AS = arm-eabi-as
CC = arm-eabi-gcc
CXX = arm-eabi-c++
LD = arm-eabi-ld

ANDROID_SOURCE_ROOT = /path/to/your/androidsource
NDK_KIT = $(ANDROID_SOURCE_ROOT)/ndk/
PLATF_KIT = build/platforms/android-4

ARM_INC = $(NDK_KIT)/$(PLATF_KIT)/arch-arm/usr/include
ARM_LIB = $(NDK_KIT)/$(PLATF_KIT)/arch-arm/usr/lib

PLATF_INC = $(NDK_KIT)/$(PLATF_KIT)/common/include

OUT_DIR = $(ANDROID_SOURCE_ROOT)/out/target/product/arm
OUT_SYSTEM_BIN = $(OUT_DIR)/system/bin/
ALL_SYSTEM_IMG = $(OUT_DIR)/system.img $(OUT_DIR)/obj/PACKAGING/systemimage_unopt_intermediates/system.img

PROJECT = my_command_line
SRCS = $(PROJECT).c util.c
OBJS = $(PROJECT).o util.o crtbegin_dynamic.o crtend.o
EXES = $(PROJECT)

all: $(EXES)
file $(EXES)

install: $(EXES)
cp -afv my_command_line $(OUT_SYSTEM_BIN)
cd ../; rm -fv $(ALL_SYSTEM_IMG)
@echo "Please re-run build_android.sh to rebuild system.img"

$(EXES): $(OBJS)
$(LD) \
--entry=_start \
--dynamic-linker /system/bin/linker -nostdlib \
-rpath /system/lib -rpath $(ARM_LIB) \
-L $(ARM_LIB) -lc $(OBJS) -o $(EXES)

$(OBJS): $(SRCS)
$(CC) -I $(ARM_INC) -I $(PLATF_INC) -c $(SRCS)
$(CC) -mthumb-interwork -o crtbegin_dynamic.o -c crtbegin_dynamic.S
$(CC) -mthumb-interwork -o crtend.o -c crtend.S
#crtbegin_dynamic.S and crtend.S copy from bionic/libc/arch-arm/bionic

clean:
rm -f $(OBJS) $(EXES)


另外寫程式要注意的是 ~android/bionic/libc/README 提到跟 standard C
library 差異處與特性:
- no support for locales
- no support for wide chars (i.e. multi-byte characters)
- its own smallish implementation of pthreads based on Linux futexes
- support for x86, ARM and ARM thumb CPU instruction sets and kernel interfaces

4. Thinker 發表的 Android Build System 分析一文相當值得細讀,善用
Android makefile 的 build system 可以省掉去瞭解這些編譯的細節。

5. Android Source Code 中的 NDK 也詳細介紹了使用 Android Java VM
的 JNI 介面與實作 shared library 的建議,在
~android/ndk/docs/OVERVIEW.TXT 中有說明,Google 一下也可以找到
中文翻譯資料,我就不翻了。 :P

結論是網路上神人很多,Google 搜尋跟這些神人也很熟。:P

相關連結:

Android 原生(Native) C 開發之八: Toolchain 環境搭建篇