这几天第一次尝试编译andorid,顺利编译了android-4.0.4_r2.1和android-2.3.7_r1,这两个分别是4.0和2.3的最后版本。
也尝试编译最新的android-4.1.1_r6,但是没成功,好像android-4.1要求要在64位的系统上编译,而我的32位系统上编译没多长时间就出错了。
CPU:Intel® Pentium(R) Dual CPU E2180 @ 2.00GHz × 2 Memory:3.0 GiB System:Ubuntu 12.04 (precise) 32 位 GCC:4.6.3 JDK:jdk-6-linux-i586.bin (32 位)
已经非常老的机器了,编译起来慢的要死,双线程全开,CPU 100%的跑,整整5个小时才跑玩,内存一直维持在1.3GB以上,到后期达到2.4GB。
android源代码:https://android.googlesource.com/
platform/manifest.git
android开发指南:http://source.android.com/source/index.html
Getting Started
Navigating the Source
Contributing
Reference
这个是android官方的开发指南,也是最标准的,android项目不停的更新变化,很多书和博客都已经过时了。
另外参考:http://blog.csdn.net/xnwyd/article/details/7086414
Detailed instructions for Ubuntu and MacOS follow. In general you will need:
Python 2.5 -- 2.7, which you can download from python.org.
GNU Make 3.81 -- 3.82, which you can download from gnu.org,
JDK 6 if you wish to build Gingerbread or newer; JDK 5 for Froyo or older. You can download both from java.sun.com.
Git 1.7 or newer. You can find it at git-scm.com.
The Sun JDK is no longer in Ubuntu's main package repository. In order to download it, you need to add the appropriate repository and indicate to the system which JDK should be used.
编译android2.3以上需要JDK6,如果编译2.2以下需要JDK5。
请参看我之前的博客:http://blog.csdn.net/niyufeng/article/details/7957156
以及 Initializing the Build Environment 中关于安装JDK的部分
在Ubuntu 12.04上需要安装如下的开发工具:
$ sudo apt-get install git git-core gnupg flex bison gperf build-essential \ zip curl libc6-dev libncurses5-dev:i386 x11proto-core-dev \ libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx:i386 \ libgl1-mesa-dev g++-multilib mingw32 openjdk-6-jdk tofrodos \ python-markdown libxml2-utils xsltproc zlib1g-dev:i386 $ sudo ln -s /usr/lib/i386-linux-gnu/mesa/libGL.so.1 /usr/lib/i386-linux-gnu/libGL.so最后一步是修正OpenGL的位置。
同时,在一直linux kernel时可能还需要:
$sudo apt-get install fakeroot valgrind libsdl-dev libesd0-dev libwxgtk2.6-dev \ liblzo2-dev uboot-mkimage libstdc++6-4.6-dev $sudo apt-get install vim gcc \ fortran77-compiler make gawk automake autoconf \ minicom lrzsz linux-headers-$(uname -r) ncurses-dev \ libncursesw5-dev libncurses5-dev netpbm libnetpbm10 \ libnetpbm10-dev libtool bison flex texinfo \ binutils-dev libc6-dev linux-libc-dev \ manpages manpages-dev manpages-posix manpages-posix-dev
请参看 Initializing the Build Environment 中关于USB的配置部分
$cd ~ $mkdir bin $curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo $chmod a+x ~/bin/repo $exportPATH=$PATH:~/bin(导出环境变量)或者可以不使用curl工具,而是到
https://dl-ssl.google.com/dl/googlesource/git-repo/repo ,或者
https://www.google.com/dl/googlesource/git-repo/repo ,直接下载repo脚本工具。
$mkdir android $cd android $ repo init -u https://android.googlesource.com/platform/manifest ...(按照提示输入用户名和邮箱名) $repo sync -j5
此处用5个线程开始同步、下载源码,下载过程及其漫长,需要耐心等待。最终下载完毕.repo/中的大小为11GB。
还有一步验证git tags可参照官网。下完后就可以在刚才文件夹下看见已下载的源码。
注:源码下载过程中经常会遇到下载失败的情况,非常浪费时间,所以编写一个失败重传的脚本可以减少很多不必要的麻烦。将下面的shell脚本保存为download.sh文件放到源代码目录中,执行./download.sh开始下载(替代文档中最后一步repo sync,其余步骤必须按照文档中介绍的一步一步来)
#!/bin/bash echo "======start repo sync======" repo sync while [ $? == 1 ]; do echo "======sync failed, re-sync again======" sleep 3 repo sync done
当通过上面repo sync把源代码下载到本地PC后,可以通过-b参数来指定某一android分支,下面是android-2.3.7_r1,它是2.3的最后版本。
repo init --config-name -b android-2.3.7_r1 repo sync
最后编译完成大约为18.3GB:
.repo:11GB out:4.3GB 真正的andorid-2.3.7_r1源代码才3.0GB左右的大小
3.2.2 使用android-4.0.4_r2.1
同样可以切换到android-4.0最后的版本android-4.0.4_r2.1。
repo init --config-name -b android-4.0.4_r2.1 repo sync
最后编译完成大约为29GB:
.repo:11GB out:14GB 真正的andorid-4.0.4_r2.1源代码才4GB左右的大小
$ source build/envsetup.sh $ lunch full-eng $ make-j2
build/envsetup.sh中定义了很多函数,例如lunch, mm, m等等
lunch 选择编译厂商版本 - m: Makes from the top of the tree. m即为make - mm: Builds all of the modules in the current directory. mm编译当前目录下所有模块 - mmm: Builds all of the modules in the supplied directories. mmm编译指定目录下所有模块
编译完成后,会看到类似的输出:
Processing target/product/generic/obj/APPS/Settings_intermediates/package.apk Done! Install: out/target/product/generic/system/app/Settings.odex Install: out/target/product/generic/system/app/Settings.apk Finding NOTICE files: out/target/product/generic/obj/NOTICE_FILES/hash-timestamp Combining NOTICE files: out/target/product/generic/obj/NOTICE.html Installed file list: out/target/product/generic/installed-files.txt Target system fs image: out/target/product/generic/obj/PACKAGING/systemimage_intermediates/system.img Install system fs image: out/target/product/generic/system.img
至此编译完毕,make编译的并不是所有内容,不包含内核kernel和SDK。
很多情况下android是不能够一次就顺利编译成功的,而在我的机器上错误主要来自与两个方面,
一是我使用的Ubuntu版本为12.04,GCC为4.6.3,GCC及其Glibc版本稍高(比较推荐使用gcc4.4,可参考 http://blog.csdn.net/xnwyd/article/details/7086414 中关于更改gcc的部分);
二是我使用的Ubuntu是32位系统,而android的编译默认使用64位系统,特别是4.1目前只能在64位系统上编译。
针对如上的错误,我制作了5个补丁:
001-gcc4.6.x.patch
#由于使用gcc 4.6.x,最好换为4.4的gcc --- android-4.0.4_r2.1/build/core/combo/HOST_linux-x86.mk.orig 2012-10-03 18:54:52.805379013 +0800 +++ android-4.0.4_r2.1/build/core/combo/HOST_linux-x86.mk 2012-10-03 18:56:28.773376791 +0800 @@ -53,6 +53,6 @@ -include $(call select-android-config-h,linux-x86) # Disable new longjmp in glibc 2.11 and later. See bug 2967937. -HOST_GLOBAL_CFLAGS += -D_FORTIFY_SOURCE=0 +HOST_GLOBAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 HOST_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined --- android-4.0.4_r2.1/frameworks/base/libs/utils/Android.mk.orig 2012-10-03 19:01:32.273369759 +0800 +++ android-4.0.4_r2.1/frameworks/base/libs/utils/Android.mk 2012-10-03 19:02:27.041368492 +0800 @@ -61,7 +61,7 @@ LOCAL_MODULE:= libutils -LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) +LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) -fpermissive LOCAL_C_INCLUDES += external/zlib ifeq ($(HOST_OS),windows)
# # Problem comes from host libstdc++. Since version 4.6 <cstdio> does not include <cstddef> anymore. # Downgrade host package to libstdc++ 4.5 or add '#include <cstddef>' into linker.cpp # --- android-4.0.4_r2.1/external/mesa3d/src/glsl/linker.cpp.orig 2012-10-04 12:12:52.625898520 +0800 +++ android-4.0.4_r2.1/external/mesa3d/src/glsl/linker.cpp 2012-10-04 12:14:46.209895889 +0800 @@ -67,6 +67,7 @@ #include <cstdio> #include <cstdarg> #include <climits> +#include <cstddef> #include <pixelflinger2/pixelflinger2_interface.h> --- android-4.0.4_r2.1/external/gtest/include/gtest/internal/gtest-param-util.h.orig 2012-10-04 12:33:56.153869253 +0800 +++ android-4.0.4_r2.1/external/gtest/include/gtest/internal/gtest-param-util.h 2012-10-04 12:35:30.713867064 +0800 @@ -38,6 +38,8 @@ #include <utility> #include <vector> +#include <cstddef> + #include <gtest/internal/gtest-port.h> #if GTEST_HAS_PARAM_TEST
--- android-4.0.4_r2.1/frameworks/compile/slang/Android.mk.orig 2012-10-04 09:17:27.799397306 +0800 +++ android-4.0.4_r2.1/frameworks/compile/slang/Android.mk 2012-10-04 09:18:01.764370516 +0800 @@ -19,7 +19,7 @@ LOCAL_PATH := $(call my-dir) -local_cflags_for_slang := -Wno-sign-promo -Wall -Wno-unused-parameter -Werror +local_cflags_for_slang := -Wno-sign-promo -Wall -Wno-unused-parameter ifneq ($(TARGET_BUILD_VARIANT),eng) local_cflags_for_slang += -D__DISABLE_ASSERTS endif
--- android-4.0.4_r2.1/external/llvm/llvm-host-build.mk.orig 2012-10-04 12:39:04.209862117 +0800 +++ android-4.0.4_r2.1/external/llvm/llvm-host-build.mk 2012-10-04 12:39:58.181860867 +0800 @@ -1,3 +1,4 @@ +LOCAL_LDLIBS := -lpthread -ldl LOCAL_CFLAGS := \ -D_GNU_SOURCE \ -D__STDC_LIMIT_MACROS \
--- android-4.0.4_r2.1/external/oprofile/libpp/format_output.h.orig 2012-10-04 12:24:24.025882506 +0800 +++ android-4.0.4_r2.1/external/oprofile/libpp/format_output.h 2012-10-04 12:25:09.349881455 +0800 @@ -91,7 +91,7 @@ symbol_entry const & symbol; sample_entry const & sample; size_t pclass; - mutable counts_t & counts; + counts_t & counts; extra_images const & extra; double diff; };
$ export ANDROID_PRODUCT_OUT=$PWD/out/target/product/generic $ export PATH=$PWD/out/host/linux-x86/bin:$PATH $ emulator emulator:WARNING: system partition size adjusted to match image file (162 MB >66 MB)
映像生成在out/target/product/generic下,android源码编译后得到system.img,ramdisk.img,userdata.img三个映像文件,emulator加载这3个映像文件。其中:
ramdisk.img是一个分区映像文件,在kernel启动时,ramdisk被用来调用init,以及把真正的rootfs mount起来;
system.img包括了主要系统,系统app等,会被挂载于/system,可对应查看./system该目录,可以发现在其下app/下有一些系统自带的应用程序。
userdata.img包括了一些用户数据,被挂载到/data下,对应可查看./data/目录。
另外还有root,system,data三个文件夹,其实就是上述三个img解压之后的内容而已。
root/对应ramdisk.img
system/对应system.img
data/对应userdata.img
$ build/envsetup.sh这样会生成一些命令
m即make mm编译当前目录下所有模块 mmm编译指定目录下所有模块
$ mmm packages/apps/Music在out/target/product/generic/system/app中就可以看见Music.apk,然后执行:
$ make snod
重新生成system.img
参看:http://bbs.imp3.net/thread-10502182-1-1.html
然后再顺便把android 4.0的SDK编译出来,因为make编译并不包含kernel和SDK。
编译SDK可以得到与源码同步的SDK,还会生成一些tools,在源码根目录下:
$ make PRODUCT-sdk-sdk编译生成的SDK在out/host/linux-x86/SDK下。
之后如果在ubuntu下使用eclipse进行开发,可以使用你编译的SDK。
下面就在模拟器中运行镜像,建议切到root用户下,首先配置几个环境变量,将自己编译的SDK设为优先级最高,在源码根目录下执行:
$ sudo update-alternatives --install /usr/bin/AndroidSDK AndroidSDK out/host/linux-x86/sdk/android-sdk_eng.root_linux-x86255这样会在/etc/alternatives下生成一个指向该sdk目录的软连接AndroidSDK,而/usr/bin/AndroidSDK就指向这个软连接(/etc/alternatives相当于中转站)。/etc/alternatives这个目录主要存放一些系统默认打开的程序的信息和配置。
接着执行:
vi ~/.bashrc在文件末尾添加:
export ANDROID_SDK_HOME=/usr/bin/AndroidSDK export PATH=$ANDROID_SDK_HOME/tools:$PATH export ANDROID_PRODUCT_OUT=$PWD/out/target/product/generic
$ emulator运行的就是你编译的映像。
执行emulator 命令时,如果不带任何参数,则Linux Kernel镜像默认使用prebuilt/android-arm/kernel目录下的kernel-qemu文件,而Android镜像文件则默认使用ANDROID_PRODUCT_OUT目录下的system.img,userdata.img和ramdisk.img,模拟器运行需要这四个文件。如果你编译了内核则可以使用自己的kernel镜像(如goldfish的内核镜像),可用于android移植等。
$ emulator -system system.img -data userdata.img -ramdisk ramdisk.img -kernel kernel/goldfish/arch/arm/boot/zImage就可以看到android 4.0的虚拟机了。
看一下系统信息,可发现kernel版本是2.6.29的,可以下载新的内核3.0.1重新编译。
参看:http://blog.csdn.net/xnwyd/article/details/7086414
Building Kernels , Building for Devices
AOSP中kernel和device是有对应关系的,例如:
device/generic/goldfish对应于kernel/goldfish.git device/ti/panda对应于kernel/omap.git device/samsung/crespo对应于kernel/samsung.git
等。
kernel/common |
CommonAndroid Kernel Tree |
kernel/exynos |
|
kernel/goldfish |
|
kernel/msm |
Kerneltree for Qualcomm chipsets |
kernel/omap |
|
kernel/samsung |
Kerneltree for Samsung systems on Android. |
kernel/tegra |
Kerneltree for NVIDIA Tegra family SOICs on Android. |
直接使用repo来下载kernel,这里我下载了kernel/common.git和kernel/goldfish.git,同时也定义了checkout的版本:
local_manifest.xml:
<?xml version="1.0" encoding="UTF-8"?> <manifest> <project path="kernel/common" name="kernel/common" revision="refs/heads/android-2.6.39" /> <project path="kernel/goldfish" name="kernel/goldfish" revision="refs/heads/android-goldfish-2.6.29" /> </manifest>
$ cp -vf local_manifest.xml .repo/ $ repo sync
$ export PATH=$PWD/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin:$PATH $ make -C kernel/goldfish/ ARCH=arm SUBARCH=arm CROSS_COMPILE=arm-eabi- goldfish_armv7_defconfig $ make -C kernel/goldfish/ ARCH=arm SUBARCH=arm CROSS_COMPILE=arm-eabi-
android4.0.4使用goldfish_armv7_defconfig;
不能混乱使用!
OBJCOPY arch/arm/boot/zImage Kernel: arch/arm/boot/zImage is ready
$ export ANDROID_PRODUCT_OUT=$PWD/out/target/product/generic $ export PATH=$PWD/out/host/linux-x86/bin:$PATH $ emulator -kernel kernel/goldfish/arch/arm/boot/zImage emulator:WARNING: system partition size adjusted to match image file (69 MB >66 MB)
这是自己编译的goldfish内核:
这是原始prebuilt/android-arm/kernel/kernel-qemu内核:
其他参考:
http://bbs.imp3.net/thread-10502182-1-1.html
http://blog.csdn.net/xnwyd/article/details/7086414
http://blog.csdn.net/zjmdp/article/details/7737802
http://blog.csdn.net/gexueyuan/article/details/7772387
http://blog.csdn.net/hudan2714/article/details/7926924