编译环境搭建

编译Android前需要安装的软件包 以下内容摘自:http://source.android.com/source/download.html

Ubuntu Linux (64-bit x86)
This has not been as well tested. Please send success or failure reports to android-porting@googlegroups.com .
The Android build requires a 32-bit build environment as well as some other tools:Required Packages: Git, JDK, flex, and the other packages as listed above in the i386 instructions:
JDK 5.0, update 12 or higher.Java 6 is not supported, because of incompatibilities with @Override.
Pieces from the 32-bit cross-building environment
X11 development$ sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl sun-java5-jdk zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev ia32-libs x11proto-core-dev libx11-dev lib32readline5-dev lib32z-devSet the system to use the right version of java by default:
$ sudo update-java-alternatives -s java-1.5.0-sunX11: Ubuntu doesn't have packages for the X11 libraries, but that can be worked around with the following command:
$ sudo ln -s /usr/lib32/libX11.so.6 /usr/lib32/libX11.so

黄色背景的比较重要。X11的问题没有碰到。至于JDK,从 Android 的编译脚本来看,Android 2.1 以前(包括2.1)使用 1.5,2.2使用的 1.6。问题是 JDK 1.5现在不维护了,而且在Ubuntu 10.04里的源里只有JDK 1.6的包。

至于,Android交叉编译时所用的工具链是Android工程自带的,一般放在目录prebuilt/linux-x86/toolchain下,包括X86,ARM,以及SH (SuperH)等架构,具体以build/core/combo/目录下以”TARGET_linux”开头的mk文件中指定的变量“TARGET_TOOLS_PREFIX”为准。

可能出现的问题libstdc++.so 链接问题

现象: host SharedLib: libneo_util (out/host/linux-x86/obj/lib/libneo_util.so)

/usr/bin/ld: skipping incompatible /usr/lib/gcc/i486-linux-gnu/4.3.4/libstdc++.so when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/i486-linux-gnu/4.3.4/libstdc++.a when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/i486-linux-gnu/4.3.4/libstdc++.so when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/i486-linux-gnu/4.3.4/libstdc++.a when searching for -lstdc++
/usr/bin/ld: cannot find -lstdc++
collect2: ld returned 1 exit status

make: *** [out/host/linux-x86/obj/lib/libneo_util.so] 错误 1

解决方法: 缺少g++-multilib库,安装即可: sudo apt-get install g++-multilib    如果把 /usr/lib/gcc/x86_64-linux-gnu/4.4.3/libstdc++.so 链接到 ../../../../lib32/libstdc++.so.6,也可以解决问题,不推荐。

libz.so链接问题

host Executable: aapt (out/host/linux-x86/obj/EXECUTABLES/aapt_intermediates/aapt)
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../libz.so when searching for -lz
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../libz.a when searching for -lz
/usr/bin/ld: skipping incompatible /usr/lib/libz.so when searching for -lz
/usr/bin/ld: skipping incompatible /usr/lib/libz.a when searching for -lz
/usr/bin/ld: cannot find -lz
collect2: ld returned 1 exit status

解决方法:

缺少lib32z1-dev库,安装: sudo apt-get install lib32z1-dev

以上问题比较常见。只要按照官方的指导进行编译,就不会出现这些问题了。

工程编译

以下如果没有特别说明,默认的当前工作目录是工程的顶级目录。只需输入:

$make

就会编译整个Android工程的代码。这相当于:

$make PRODUCT-generic-eng

如果要编译 Android SDK,输入:

$make sdk

其他的一些编译命令:

$make modules #打印工程的所有模块。

$make ${LOCAL_MODULE} #编译模块${LOCAL_MODULE} ,如 make libc 编译libc(bionic/libc模)

$make clean-${LOCAL_MODULE} #清理模块${LOCAL_MODULE} 编译的目标文件和中间文件。

$make eng #也可以 user,userdebug。发布版本编译的一些变体,区别在安装模块、软件 #包和是否可以调试。在不同变体间切换前,请用 make installclean 清理安装。

$make clean #清除当前编译配置生成输出和中间文件。相当rm -f out/。

$make clobber #清除所有配置的输出和中间文件。 相当于 rm -f out

$make dataclean #

$make installclean # 清理安装的文件

$make snod #重新生成system.img

$make bootimage #

$make dist #

在以上的命令中,加上 “showcommands”,会打印编译时使用的命令, -j 指定多核同步编译。如:

$make sdk showcommands -j 4

多核编译,有时以为同步会出现依赖问题,这时去掉 -j 或直接重新编译即可解决。更多详细内容,请参考:

build/core/build-system.html

http://source.android.com/porting/build_system.html

$make -j8 PRODUCT-sdk-sdk showcommands dist

在build/core/main.mk 及build/core/Makefile两个文件中有许多伪目标:

otapackage , recoveryimage

模块编译

开发 Android应用时,借助 Eclipse ,编码、编译、运行、调试,一气呵成。但是如果修改Android 自带的程序,或者如 Frameworks 等代码的,就难以使用 Eclipse 开发,现在一般是在命令行操作。这时有什么方法可以减少编译、启动的时间呢?可以按下面步骤实施:

1. 加载脚本

$source build/envsetup.sh

或者

$ . build/envsetup.sh

这样mmm等命令就可以使用了。由于mmm是函数,只在当前的shell中有效,这也是用source加载脚本的原因。其他还有的命令

printconfig : 打印工程当前编译配置

lunch :选择编译配置

choosecombo :逐项选择编译配置

2. 编译模块

$mmm packages/app/Launcher2

mmm只需要指定目录即可,当然这个目录下必须有Android.mk的Makefile。编译,目标文件放在

/out/target/product/generic/system/app。重新挂载 /system

$adb remount

注意:把adb所在的目录放在环境变量PATH,或者指定路径,如out/host/linux-x86/bin/adb,并具有指向权限。如果是USB连接到开发板,请以超级用户的权限运行 adb server,再remount。

$adb kill-server #如果server没运行可以略过

$sudo adb start-server

默认情况,/system挂载的文件系统只读,需要重新挂载为可读写。

安装

$adb push out/target/product/generic/system/app/Launcher2.apk /system/app

或者

$adb install -r out/target/product/generic/system/app/Launcher2.apk

Android在发现程序文件被更新后,会重新启动应用程序,我们就可以调试了。以后,我们只需重复步骤2和4,快速编译,热更新模块,开发效率也很高,而不需要重新编译这个工程、重新烧录镜像文件、重启系统等费时的工作。

如果更新了framewok.apk 或者 共享库时,需要同步一下。

$adb shell sync

mmm frameworks/policies/base/phone/ showcommands

不能编译出 out/target/product/generic/system/framework/android.policy.jar

make android.policy -j 4

才可以。原因是, frameworks/policies/base/PolicyConfig.mk 配合 frameworks/policies/base/phone/Android.mk

共享库也可以热更新

$mmm frameworks/base/libs/binder

$adb push out/target/product/generic/system/lib/libbinder.so /system/lib

命令行定义变量:

$ DISABLE_AUTO_INSTALLCLEAN=true mmm frameworks/base/camera/tests/CameraServiceTest/

这个在编译SDK 和 eng之间切换时不会清理。

内核编译

主要是模拟器的内核编译。

prebuilt/android-x86/kernel/kernel获取代码

~/Android$git clone git://android.git.kernel.org/kernel/common.git

~/Android$git checkout origin/android-goldfish-2.6.27 -b goldfish

模拟器有自己的内核goldfish分支,默认分支编译后不能在qemu中启动。

更多的分支可以使用 git branch -a 查看。Goldfish 内核的源码导出到了目录~/Android/common

编译配置

从 SDK 中获取编译配置:

$emulator -avd myavd #启动虚拟机, 或者在 Ecplise 把虚拟机启动

$adb pull /proc/config.gz #从虚拟机的文件系统中拉出内核的编译配置

$gunzip config.gz;mv config ~/Android/common/.config

如果从源码里直接配置:

$make ARCH=arm goldfish_defconfig #生成默认配置

$make xconfig #作修改 (需要QT,安装libqt3-mt-dev 包即可) 或者

$make gconfig # (需安装libglade2-dev)

更详细的可以参照 README 或使用下面命令获取帮助:

$make help

$make ARCH=arm help

修改 Makefile 打开kernel目录下的Makefile文件,把   LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,   $(call ld-option, -Wl$(comma)?build-id,))   这一行注释掉,并且添加一个空的LDFLAGS_BUILD_ID定义,如下:   LDFLAGS_BUILD_ID =   编译内核 $make mrproper $make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- 编译开始,会有一些提示需要确认,一路回车键。 小帖士:“[Y/n]”这样字样的含义是,可以按“y”(yes)或者“n”(no), 大写的”Y”表示用户默认的选择,即直接回车就是表示选了”y”。 这里使用的交叉编译器是CodeSourcery (http://www.codesourcery.com/sgpp/lite/arm/portal/subscription?@template=lite),也可以使用 Android 自带的交叉编译器 (在prebuilt/linux-x86/toolchain/arm-eabi-4.4.0 ,相应的交叉编译器前缀要修改成 CROSS_COMPILE=arm-eabi-),当然把工具所在路径都要加入环境变量 PATH,在~/.bashrc 加入:

export PATH=${PATH}:~/CodeSourcery/Sourcery_G++_Lite/bin

模拟器的内核编译的源码很少,很快就能编译完成,生成的kernel 镜像路径是 arch/arm/boo/zImage, 拷贝到 prebuilt/android-arm/kernel/kernel-qemu