Android6.0源码编译教程

本文约 1800 字,阅读需 4 分钟。

Android6.0源码编译教程

第一次成功编译了Android的源码,记录一下。

回忆

这是我第二次尝试去编译Android的源码,第一次是半年前,当时刚刚拿到去腾讯实习的Offer,虽然当时会一些Android开发的皮毛知识,但想到将来可能长期从事这个领域,就一时踌躇满志,打算先研究一下Android源码。 当时是按照网上最常见的方法,通过repo工具来下载代码,结果下了30G左右,似乎下载了所有版本,而且网络似乎有中断,都不知道下载的代码是否完整,再加上120G固态硬盘实在不够用,所以不了了之。 寒假回来,感觉自己最近一段时间过于沉迷游戏,毕设进度不及预期,博客也多荒废了。明年打算去公司继续实习,所以还是早回正轨吧!

下载源码

这次看到一篇博客,给了我一些新的启发,博主将Android6.0的源码打包,然后切割成10个700M左右的文件放在百度网盘,所以我只需要下载之后再合并这些文件就行了:

➜  下载 ls
Android6_r1_aa
Android6_r1_ab
Android6_r1_ac
Android6_r1_ad
Android6_r1_ae
Android6_r1_af
Android6_r1_ag
Android6_r1_ah
Android6_r1_ai
Android6_r1_aj

通过:

➜  下载 cat Android6_r1_*>Android6_r1.tgz

便可以合并这些文件,值得一提的是:由于文件下载过程中可能损坏(确实存在,有一个文件用浏览器老是下载失败,我便用手机客户端下载之后拷贝过来,就发现合并之后解压失败,检查之后发现这个文件的md5值已经变了),所以需要通过md5检验。通过md5sum命令查看每个文件的md5值,并与随同下载的hash.txt对比:

➜  下载 cat hash.txt
a4129f5d2d6a8293ee3ee3ed4343f0fd  Android6_r1_aa
e601f1239c0f60895cc6b9199b1cd7d1  Android6_r1_ab
af2d9e653a51072031ce40b62791c2de  Android6_r1_ac
482866559a4d6a8533411e512436363c  Android6_r1_ad
cef15f072f6d52243d9dea126c22f794  Android6_r1_ae
457979779748dae9f5f4f3c99db04826  Android6_r1_af
7ca217b1fd60a41c7ff9b7e294864fe3  Android6_r1_ag
5b468da830ef51fdd5f35d5d8ac72bd1  Android6_r1_ah
ba80f4acf5f61b1b82d3c1ba6ba702c1  Android6_r1_ai
4350d1bb74589ad03735279421dced92  Android6_r1_aj

cat Android6_r1_*>M.tgz


23858108e95095dc8d0292505a0d28e4  M.tgz
➜  下载 

构建环境

这一步比较看运气,之前用Ubuntu12就是各种冲突,这次我用的是LinuxMint18 Xfce,而AOSP的官方说明只说了Ubuntu各版本的依赖安装,由于LinuxMint是Ubuntu的近亲,所以我就直接按照最新版本(>=Ubuntu15)来安装依赖,所幸一次通过:

sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip

开始编译

make之后,日常报错,第一次错误很好解决:

You are attempting to build with the incorrect version
of java.
 
 Your version is: openjdk version "1.8.0_151" OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-0ubuntu0.16.04.2-b12) OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode).
 The required version is: "1.7.x"
  
  Please follow the machine setup instructions at
      https://source.android.com/source/initializing.html

由于最新版本已经不能下载openjdk7,所以需要重新设置一下源,下载之后重写一下当前终端的环境变量(一次使用无污染):

➜  Android_r1 export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64 
➜  Android_r1 export PATH=$JAVA_HOME/bin:$PATH 
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
➜  Android_r1 java -version
java version "1.7.0_95"
OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-3)
OpenJDK 64-Bit Server VM (build 24.95-b01, mixed mode)

最新版本的LinuxMint可能无法直接安装jdk1.7,需要手动设置源:

sudo add-apt-repository ppa:openjdk-r/ppa  
sudo apt-get update   
sudo apt-get install openjdk-7-jdk

注意不要用

sudo update-alternatives --config java
sudo update-alternatives --config javac

来指定版本,否则可能出现

Lock.ReentrantReadWriteLock.ReadLock(ReentrantReadWriteLock)
prebuilts/sdk/api/23.txt:53035: error 9: Removed public constructor java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock.ReentrantReadWriteLock.WriteLock(ReentrantReadWriteLock)
prebuilts/sdk/api/23.txt:53074: error 9: Removed public constructor java.util.jar.Attributes.Name.Attributes.Name(String)
prebuilts/sdk/api/23.txt:54404: error 9: Removed public constructor javax.crypto.spec.PSource.PSpecified.PSource.PSpecified(byte)

******************************
You have tried to change the API from what has been previously released in
an SDK.  Please fix the errors listed above.
******************************


build/core/tasks/apicheck.mk:46: recipe for target 'out/target/common/obj/PACKAGING/checkpublicapi-last-timestamp' failed
make: *** [out/target/common/obj/PACKAGING/checkpublicapi-last-timestamp] Error 38

##### make failed to build some targets (05:10 (mm:ss)) ####

第二个问题比较棘手:

clang: error: linker command failed with exit code 1 (use -v to see invocation)
build/core/host_shared_library_internal.mk:44: recipe for target 'out/host/linux-x86/obj32/lib/libnativehelper.so' failed
make: *** [out/host/linux-x86/obj32/lib/libnativehelper.so] Error 1

但StackOverflow上也能找到答案(具体参见链接),但是直接按照答案还是失败了,再参考其他博客后,我覆盖了ld文件,原来的保留为ld.old,并修改/art/build/Android.common_build.mk为:

## Host.
ART_HOST_CLANG := false
ifneq ($(WITHOUT_HOST_CLANG),true)
    ## By default, host builds use clang for better warnings.
    ART_HOST_CLANG := false
endif

(原答案是将判断语句中的true修改为false) 最终,这份10G左右的源码在我的老电脑(500G机械硬盘,4G内存,i5处理器)上编译了大概4个小时终于成功了。

启动模拟器

这个部分原博主说的不是很清楚,这里详细说一下。在编译完成后,所有的结果文件都在out文件夹,有26G:

➜  Android_r1 du . -h --max-depth=1
16M     ./build
29M     ./bionic
28M     ./art
108K    ./abi
880K    ./pdk
900K    ./platform_testing
26G     ./out
108M    ./hardware
5.7M    ./bootable
89M     ./device
28M     ./docs
2.6G    ./external
30M     ./system
493M    ./cts
196K    ./libnativehelper
83M     ./ndk
276M    ./developers
11M     ./dalvik
31M     ./sdk
6.5G    ./prebuilts
52M     ./libcore
307M    ./development
1.5G    ./frameworks
686M    ./tools
401M    ./packages
40G.

打开一个新终端,首先要设置运行环境,然后选择平台:

➜  Android_r1 source build/envsetup.sh 
build/envsetup.sh:573: command not found: complete
WARNING: Only bash is supported, use of other shell would lead to erroneous results
including device/asus/deb/vendorsetup.sh
including device/asus/flo/vendorsetup.sh
including device/asus/fugu/vendorsetup.sh
including device/generic/mini-emulator-arm64/vendorsetup.sh
including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
including device/generic/mini-emulator-mips/vendorsetup.sh
including device/generic/mini-emulator-x86_64/vendorsetup.sh
including device/generic/mini-emulator-x86/vendorsetup.sh
including device/htc/flounder/vendorsetup.sh
including device/lge/hammerhead/vendorsetup.sh
➜  Android_r1 lunch

You're building on Linux

Lunch menu... pick a combo:
1. aosp_arm-eng
2. aosp_arm64-eng
3. aosp_mips-eng
4. aosp_mips64-eng
5. aosp_x86-eng
6. aosp_x86_64-eng
7. aosp_deb-userdebug
8. aosp_flo-userdebug
9. full_fugu-userdebug
10. aosp_fugu-userdebug
11. mini_emulator_arm64-userdebug
12. m_e_arm-userdebug
13. mini_emulator_mips-userdebug
14. mini_emulator_x86_64-userdebug
15. mini_emulator_x86-userdebug
16. aosp_flounder-userdebug
17. aosp_hammerhead-userdebug
18. aosp_hammerhead_fp-userdebug
19. aosp_shamu-userdebug

Which would you like? [aosp_arm-eng] 

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=6.0
TARGET_PRODUCT=aosp_arm
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
TARGET_CPU_VARIANT=generic
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_OS=linux
HOST_OS_EXTRA=Linux-4.4.0-21-generic-x86_64-with-LinuxMint-18-sarah
HOST_BUILD_TYPE=release
BUILD_ID=MRA58K
OUT_DIR=out
============================================

➜  Android_r1 which emulator
/home/vimerzhao/SourceCode/Android_r1/prebuilts/android-emulator/linux-x86_64/emulator
➜  Android_r1 which android
/home/vimerzhao/SourceCode/Android_r1/prebuilts/devtools/tools/android
➜  Android_r1 echo $ANDROID_PRODUCT_OUT
/home/vimerzhao/SourceCode/Android_r1/out/target/product/generic

这时候输入emulator就可以看到效果了:

两点遗憾

第一点,觉得编译期间输出的log对于理解源码还是很有帮助的,可惜没保存下来。第二点,打算烧录到真机的时候才发现编译之前要配置相应的驱动,这次也只好到此为止。

参考

总阅读量次。