安卓系统源码编译系列——安卓系统源码编译教程

Posted 心砚thu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓系统源码编译系列——安卓系统源码编译教程相关的知识,希望对你有一定的参考价值。

折腾了两天终于完成了安卓系统源码的下载,虽然说中间遇到了不少波折,但总算顺利完成,有兴趣的朋友可以参考我的上一篇博文《安卓系统源码编译系列(一)——下载安卓系统源码教程》。完成了源码下载之后,本人又马不停蹄的开始了源码编译的旅途,抱着与上篇文章同样的目的,写下这篇博文,那就是希望大家可以通过本人的教程一次性完成安卓系统源码的编译!

同时,也欢迎大家将编译过程中遇到的问题及解决方案告诉我,一起完善本教程。


编译前的准备

由于在上一篇博文中我们已经对编译环境做了一些配置,如安装jdk、git、python等,所以这里就不再重复。 首先,如果是按照我上一篇博文配置jdk环境的朋友,可以再执行以下命令增加几个映射,避免出现找不到命令的情况:
cd /usr/bin
ln -s -f /usr/local/java/jdk1.6.0_31/bin/javah
ln -s -f /usr/local/java/jdk1.6.0_31/bin/jar
ln -s -f /usr/local/java/jdk1.6.0_31/bin/javadoc

其次,因为Ubuntu12.04自带的gcc和g++是4.6版本的,我们需要安装4.4版本的gcc和g++,避免出现版本兼容性问题,在终端依次输入以下命令:
sudo apt-get install gcc-4.4
sudo apt-get install g++-4.4

cd /usr/bin
sudo mv gcc gcc.bak
sudo ln -s gcc-4.4 gcc
sudo mv g++ g++.bak
sudo ln -s g++-4.4 g++
执行完成可以在终端输入以下命令来检查版本是否正确:
gcc -v
g++ -v

然后,我们可以进行USB访问的权限配置。个人感觉这是在将编译好的系统放到真机上时使用的,如果仅仅是在模拟器上运行自己编译的系统可以跳过。以下内容是对官方教程的翻译: 在GNU/Linux系统下(特别是Ubuntu系统),默认一般用户是不能直接访问USB设备的。我们需要对系统进行一些配置来允许USB访问。 推荐的做法是以root的身份创建一个文件(路径是/etc/udev/rules.d/51-android.rules),并将以下内容拷贝到里面。其中<username>应该被替换为需要授权通过USB访问手机的用户名称。
# adb protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTRidVendor=="18d1", ATTRidProduct=="4e12", MODE="0600", OWNER="<username>"
# fastboot protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTRidVendor=="0bb4", ATTRidProduct=="0fff", MODE="0600", OWNER="<username>"
# adb protocol on crespo/crespo4g (Nexus S)
SUBSYSTEM=="usb", ATTRidVendor=="18d1", ATTRidProduct=="4e22", MODE="0600", OWNER="<username>"
# fastboot protocol on crespo/crespo4g (Nexus S)
SUBSYSTEM=="usb", ATTRidVendor=="18d1", ATTRidProduct=="4e20", MODE="0600", OWNER="<username>"
# adb protocol on stingray/wingray (Xoom)
SUBSYSTEM=="usb", ATTRidVendor=="22b8", ATTRidProduct=="70a9", MODE="0600", OWNER="<username>"
# fastboot protocol on stingray/wingray (Xoom)
SUBSYSTEM=="usb", ATTRidVendor=="18d1", ATTRidProduct=="708c", MODE="0600", OWNER="<username>"
# adb protocol on maguro/toro (Galaxy Nexus)
SUBSYSTEM=="usb", ATTRidVendor=="04e8", ATTRidProduct=="6860", MODE="0600", OWNER="<username>"
# fastboot protocol on maguro/toro (Galaxy Nexus)
SUBSYSTEM=="usb", ATTRidVendor=="18d1", ATTRidProduct=="4e30", MODE="0600", OWNER="<username>"
# adb protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTRidVendor=="0451", ATTRidProduct=="d101", MODE="0600", OWNER="<username>"
# adb protocol on panda (PandaBoard ES)
SUBSYSTEM=="usb", ATTRidVendor=="18d1", ATTRidProduct=="d002", MODE="0600", OWNER="<username>"
# fastboot protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTRidVendor=="0451", ATTRidProduct=="d022", MODE="0600", OWNER="<username>"
# usbboot protocol on panda (PandaBoard)
SUBSYSTEM=="usb", ATTRidVendor=="0451", ATTRidProduct=="d00f", MODE="0600", OWNER="<username>"
# usbboot protocol on panda (PandaBoard ES)
SUBSYSTEM=="usb", ATTRidVendor=="0451", ATTRidProduct=="d010", MODE="0600", OWNER="<username>"
# adb protocol on grouper/tilapia (Nexus 7)
SUBSYSTEM=="usb", ATTRidVendor=="18d1", ATTRidProduct=="4e42", MODE="0600", OWNER="<username>"
# fastboot protocol on grouper/tilapia (Nexus 7)
SUBSYSTEM=="usb", ATTRidVendor=="18d1", ATTRidProduct=="4e40", MODE="0600", OWNER="<username>"
# adb protocol on manta (Nexus 10)
SUBSYSTEM=="usb", ATTRidVendor=="18d1", ATTRidProduct=="4ee2", MODE="0600", OWNER="<username>"
# fastboot protocol on manta (Nexus 10)
SUBSYSTEM=="usb", ATTRidVendor=="18d1", ATTRidProduct=="4ee0", MODE="0600", OWNER="<username>"
这些规则将在设备下一次连接到系统的时候生效,因此需要将设备拔掉重新连接。 这个方法在Ubuntu Hardy Heron(8.04 x LTS)和Lucid Lynx(10.04 x LTS)系统上有效。其他版本的Ubuntu或者其他的Linux系统可能需要不同的配置。
接下来,我们需要配置编译使用的缓存。以下内容是对官方教程的翻译: 在编译的过程中我们可以让编译器使用编译缓存池Ccache。编译缓存池可以加快二次编译的速度。当你经常使用“make clean”操作或者经常在不同版本之间切换来编译,编译缓存池会给你带来很大的效率提升。 将以下内容放到你的.bashrc(路径:~/.bashrc)或者相同作用的文件中:
export USE_CCACHE=1
缓存默认存储在~/.ccache路径下。如果你的源码存储在网络服务器上,或者其他非本地的文件系统中,你可以在.bashrc文件中设置缓存的目录:
export CCACHE_DIR=<path-to-your-cache-directory>
推荐的缓存大小是50-100G,你可以在下载完源码后在源码目录下运行以下命令:
prebuilts/misc/linux-x86/ccache/ccache -M 50G
当你需要编译Ice Cream Sandwich(4.0.x)或者更老的安卓系统时,Ccache文件的路径在另一个位置,可以运行以下命令:
prebuilt/linux-x86/ccache/ccache -M 50G
这个设置会保存在CCACHE_DIR路径下,并且是永久的。
最后,我们可以设置一下swap文件,避免出现“其他问题”中的第四个:
mkdir /opt/other
sudo dd if=/dev/zero of=/opt/other/swapfile bs=1024 count=512K
mkswap /opt/other/swapfile
swapon /opt/other/swapfile
swapon -s

除此之外,官网教程中还提到了“使用单独的输出目录”(Using a separate output directory),个人感觉意义不是很大,如果有需要的话可以到 官网上查看。

开始编译

在完成了以上配置后,我们就可以开始进行源码编译了。请大家在编译之前再次确认虚拟机的配置,内存最好是2个G以上(本人是用的4个G),硬盘空间100G以上(本人用的是200G,反正VMware硬盘空间是动态增长的,设多点没坏处)。 首先,我们需要在源码根目录运行一个脚本进行初始化:
$ source build/envsetup.sh
然后是选择需要编译的目标,如:
$ lunch full-eng
该命令主要由两个参数组成,第一个参数可选的值有full、full_maguro、full_panda,分别代表模拟器、手机和开发板PandaBoard(开发板是一个单片机或者称为开发板,如果不好理解的话你可以将它想象成一个没安外壳的设备,这是专门提供给开发者的开发工具)。第二个参数可选的值有user、userdebug和eng。user版本没有root权限,类似于手机上的操作系统;userdebug版本类似于user版本,但是有root权限,可以用于调试;eng版本主要用于调试,同时带有很多调试工具。 在这里,我们选择在模拟器上运行的调试版本,所以使用参数full-eng。 最后,我们需要运行一个命令来开始编译:
make -j4
make之后的参数jN代表编译使用的线程数,与CPU的内核总数有关,正好是CPU内核总数的两倍。如果你的CPU是单核的就应该运行make -j2,当然线程数越多编译的速度越快,所以如果是用虚拟机的话,可以在电脑配置允许的情况下使用尽量多的核数。 注意,线程数越高的话需要的内存也越高,如果内存不足编译到一半会出错,所以如果内存比较小的话,虽然时间长一些,但是建议直接使用make。 最后编译成功的截图如下:

运行编译结果

走到这里,我们历尽千难万苦成功下载并编译完成了安卓系统,终于到了最激动人心的时刻了,让我们把编译完成的系统运行起来。 这时只要在源码目录下输入emulator即可,但是直接输入会报错,所以我们先运行两个命令:
source build/envsetup.sh
lunch full-eng
最后运行:
emulator

就可以看到模拟器运行起来的效果了



总结

从开始编译到编译成功,中间两次出错重新编译,最后一次编译成功花了3个半小时。编译完成源码目录共35G,虚拟机物理文件大小为74G(包括两次快照)。 个人感觉整个下载编译过程还是比较顺利的,如果按照本教程的话,应该一天就可以走完整个流程。

其他问题

1.jar、javadoc或者javah命令找不到
/bin/bash: jar: command not found
make: *** [out/host/common/obj/JAVA_LIBRARIES/antlr-runtime_intermediates/javalib.jar] Error 127
或者
/bin/bash: javah: command not found
可以执行以下命令:
cd /usr/bin
ln -s -f /usr/local/java/jdk1.6.0_31/bin/javah
ln -s -f /usr/local/java/jdk1.6.0_31/bin/jar
ln -s -f /usr/local/java/jdk1.6.0_31/bin/javadoc


2.

collect2: ld terminated with signal 9 [Killed]
make: *** [out/host/linux-x86/obj/EXECUTABLES/clang_intermediates/clang] Error 1
make: *** Waiting for unfinished jobs....
内存不足,建议增加虚拟机内存或者改用“make”进行编译。


3.

mon/docs/api-stubs-timestamp] Error 45
执行以下命令:

make clean
make

4.

target SharedLib: libwebcore (out/target/product/generic/obj/SHARED_LIBRARIES/libwebcore_intermediates/LINKED/libwebcore.so)
collect2: error: ld terminated with signal 9 [Killed]
make: *** [out/target/product/generic/obj/SHARED_LIBRARIES/libwebcore_intermediates/LINKED/libwebcore.so] Error 1
这是由于没有创建swap文件引起的,可以执行以下命令创建一个:
mkdir /opt/other
sudo dd if=/dev/zero of=/opt/other/swapfile bs=1024 count=512K
mkswap /opt/other/swapfile
swapon /opt/other/swapfile
swapon -s

如果还是不行的话,可以考虑增加虚拟机内存之后重新编译

之后遇到问题会持续补充。



如果大家觉得对自己有帮助的话,还希望能帮顶一下,谢谢:) 个人博客: http://blog.csdn.net/zhaoxy2850 本文地址: http://blog.csdn.net/zhaoxy_thu/article/details/12683403 转载请注明出处,谢谢!

以上是关于安卓系统源码编译系列——安卓系统源码编译教程的主要内容,如果未能解决你的问题,请参考以下文章

自己可以编译安卓源码吗?

Android源码编译

Android源码编译

使用Android Studio调试安卓系统源代码:将AOSP源码整体导入到AS

Android.mk这个文件在哪里呢

失败的安卓源码编译