Mac 编译 android framework 6.0源码

工作到现在为止刚好一年半,一直做着公司Android产品的半开发半维护的工作,内心一直向往一份关于android framework开发方面的工作,前面几个月研读了一些设计模式和Sandroid framework源码的书,接下来的目标就是搭建调试framework的环境,听说mac不错,于是买了个mba 128g的笔记本,现在有点后悔,如果时间能重新选择,一定买mbp,本来打算编译2.3点源码的,但是看了官方的android版本于编译系统的对应关系,还是决定按要求来吧,选择了android6.0.1版本,而且自己有个nexus5,正好可以刷。

Android版本 Mac OS (Intel/x86)
Android 6.0 (Marshmallow) - Android最新版本 Mac OS v10.10 (Yosemite) or later with Xcode 4.5.2 and Command Line Tools
Android 5.x (Lollipop) Mac OS v10.8 (Mountain Lion) with Xcode 4.5.2 and Command Line Tools
Android 4.1.x-4.3.x (Jelly Bean) - Android 4.4.x (KitKat) Mac OS v10.6 (Snow Leopard) or Mac OS X v10.7 (Lion) and Xcode 4.2 (Apple’s Developer Tools)
Android 1.5 (Cupcake) - Android 4.0.x (Ice Cream Sandwich) Mac OS v10.5 (Leopard) or Mac OS X v10.6 (Snow Leopard) and the Mac OS X v10.5 SDK

##1、本文相关配置

硬件:

1、MacBook Air i5双核处理器 硬盘128g 内存8g

2、一块2T的移动硬盘

3、nexus5

软件:

1、各个版本的jdk,jdk6、jdk7、jdk8,(本文选择android版本为6.0.1因此默认用jdk7)网盘地址 密码:tz95

2、repo 下载地址

3、清华镜像站的初始化包 下载地址

4、选择编译的android版本为android-6.0.1_r60(r60分支只支持刷入nexus5)

5、xcode8(最新版为xcode9,但是编译过程提示xcode和aosp中externl库函数冲突,google发现别人也有这个问题,换xcode8后解决了)

6、MacOSX10.11.sdk(xcode8默认的MacOSX10.12.sdk编译时会提示有些函数废弃了编译不了,因此需要下载10.11.sdk,并拷贝到10.12.sdk同一目录下)网盘地址密码:kv23

7、MacPorts(用于方便安装make、git、gpg等相关工具)下载地址

8、nexus5 r60分支版本的驱动

google官网驱动下载地址

nexus5 r60分支版本MOB30Y的驱动网盘地址密码:2a33,不同版本对应不同驱动,这个要注意

##2、下载源码

国内有长城,google下不来,可以从清华大学开源软件镜像站下,看介绍源码会有30g以上,但是自己的笔记本却只有128g,而且现在就剩40g了,查资料发现可以在移动硬盘弄,于是乎买了个2t的移动硬盘。

##3、下载repo工具 1.这个命令会下载一个repo的文件到当前命令的目录下

curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o repo

*第一个知识点:repo

2.在home目录下创建bin目录

mkdir ~/bin

3.把上面下载的repo拷贝到~/bin目录下

4.赋予权限

chmod a+x ~/bin/repo

5.用文本编辑的方式打开repo,并且修改为REPO_URL为:

REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'

##4、安装MacPorts

MacPorts下载地址

接着使用下面等MacPorts命令安装make、git等工具

sudo port install gmake libsdl git-core gnupg

##5、创建一个区分大小写的镜像文件

hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 100g ~/android.dmg.sparsefile.sparseimage

这个镜像主要是用来存放源代码的,由于我用的是移动硬盘来编译源码,因此把这个镜像文件移动到移动硬盘里,因为自己笔记本容量小,因此把镜像文件拷到移动硬盘后再进行使用镜像,这步很重要,这个100g是镜像的上限,新创建时并没有100g,只有200多m,而且可以动态改变大小,只要用下面的命令

hdiutil resize -size 150g ~/android.dmg.sparsefile.sparseimage

我编译了模拟器以及真机的镜像,最后镜像大小为127g,当然如果编译时空间不够,可以把.repo删除了

在~/根目录下看看有没有.bash_profile文件,没有就创建一个,这个文件主要是用来进行一些环境变量的配置,下面是我自己的.bash_profile文件

# 用来挂载镜像的函数
function mountAndroid { hdiutil attach /Volumes/mhdd/android.dmg.sparsefile.sparseimage -mountpoint /Volumes/android; }

# 推出镜像,跟在桌面推出效果一样
function umountAndroid() { hdiutil detach /Volumes/android; }

# 安装MacPorts的变量配置
PATH=/opt/local/bin:$PATH
PATH=/opt/local/sbin:$PATH

#解除1024限制 
ulimit -S -n 1024

# -------------java的环境变量start---------------------
# Mac默认 JDK 6  
export JAVA_6_HOME=`/usr/libexec/java_home -v 1.6`  
# 设置 JDK 7  
export JAVA_7_HOME=`/usr/libexec/java_home -v 1.7`  
# 设置 JDK 8  
export JAVA_8_HOME=`/usr/libexec/java_home -v 1.8`  
  
#默认JDK 7  
export JAVA_HOME=$JAVA_7_HOME  
  
#alias命令动态切换JDK版本,直接在命令行输入jdk6或其他版本就可切换了  
alias jdk6="export JAVA_HOME=$JAVA_6_HOME"  
alias jdk7="export JAVA_HOME=$JAVA_7_HOME"  
alias jdk8="export JAVA_HOME=$JAVA_8_HOME"  
# -------------java的环境变量end---------------------

​ #——————-repo环境变量——————- export PATH=$PATH:$HOME/bin

#-----------------android sdk环境变量--------------
#主要是执行adb命令,fastboot命令等用到,这是我本地的路径,根据需要自己修改
ANDROID_HOME=/Users/xuanliang/coding/android/android-sdk-macosx
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/platform-tools

*第二个知识点:bash_profile文件是什么

用命令行mountAndroid挂载好镜像文件后,就可以像硬盘一样使用镜像文件了,在镜像中建立aosp文件夹,接着从清华镜像站下载好40多g的原始包,把它解压到镜像文件aosp文件夹里,是一个.repo的文件。(一开始自己是先从笔记本硬盘把压缩文件拷到镜像里再解压,发现很慢,想起来是因为镜像在移动硬盘上的原因,于是采用直接从笔记本用命令把文件解压到镜像文件里,就快多了),命令行进入到aosp目录,执行初始化repo到命令:

repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-6.0.1_r60

r60代表是nexus5的MOB30Y版本,_r60这个参数很重要,因为对应着机型版本以及驱动版本,版本不对烧写真机时容易出问题,可以根据需要取其他分支。然后执行下面的命令进行同步。

repo sync

同步完成后aosp目录会生成6.0.1_r60分支的所有代码,可以通过.repo目录里的manifest文件看看所下分支是否正确。(执行repo sync命令时遇到了一个坑,查了半天发现是当时解压用的软件解压的,解压的不完全,解压出的文件有问题,后来把文件都删除了,重新用命令行解压后再进行repo sync同步就好了,得了个教训以后对于大文件解压还是得用命令行)

然后就是进行编译了

$ source build/envsetup.sh

lunch

make -j4

编译成功会在products里生成hammerhead文件夹,烧写入真机时要进入这个文件夹执行fastboot等命令,如果上面lunch选择1则会generic文件夹,里面是模拟器用到的镜像相关文件

因为要烧写入真机,因此先执行驱动的三个脚本文件生成相关文件,如果只需要模拟器则跳过这步 首先把驱动脚本拷进aosp目录,然后依次执行三个驱动脚本

./extract-broadcom-hammerhead.sh
./extract-lge-hammerhead.sh
./extract-qcom-hammerhead.sh

执行过程中会有一些条款,阅读完后会提示输入“同意”指令,输入完会在相关目录生成驱动文件。

最后手机连上电脑,执行adb命令

adb reboot bootloader

这个命令会让手机重启并进入刷机模式,如果adb命令找不到,先看看是否环境变量配置正确,adb工具以及fastboot工具在android的sdk里,参考步骤5里的配置

#cd 到源码编译输出的目录执行fastboot命令
fastboot -w flashall

最后刷机成功。

接着是生成android studio能导入的文件,使用如下命令

make idegen && development/tools/idegen/idegen.sh

会在源码目录生成两个文件,如下图,

可以对android.imp进行编辑去掉一些模块,这样android studio导入就会快点。

 <excludeFolder url="file://$MODULE_DIR$/.repo" />
  <excludeFolder url="file://$MODULE_DIR$/abi" />
  <excludeFolder url="file://$MODULE_DIR$/art" />
  <excludeFolder url="file://$MODULE_DIR$/bionic" />
  <excludeFolder url="file://$MODULE_DIR$/bootable" />
  <excludeFolder url="file://$MODULE_DIR$/build" />
  <excludeFolder url="file://$MODULE_DIR$/cts" />
  <excludeFolder url="file://$MODULE_DIR$/dalvik" />
  <excludeFolder url="file://$MODULE_DIR$/developers" />
  <excludeFolder url="file://$MODULE_DIR$/development" />
  <excludeFolder url="file://$MODULE_DIR$/device" />
  <excludeFolder url="file://$MODULE_DIR$/docs" />
  <excludeFolder url="file://$MODULE_DIR$/external" />
  <excludeFolder url="file://$MODULE_DIR$/external/bluetooth" />
  <excludeFolder url="file://$MODULE_DIR$/external/chromium" />
  <excludeFolder url="file://$MODULE_DIR$/external/emma" />
  <excludeFolder url="file://$MODULE_DIR$/external/icu4c" />
  <excludeFolder url="file://$MODULE_DIR$/external/jdiff" />
  <excludeFolder url="file://$MODULE_DIR$/external/webkit" />
  <excludeFolder url="file://$MODULE_DIR$/frameworks/base/docs" />
  <excludeFolder url="file://$MODULE_DIR$/hardware" />
  <excludeFolder url="file://$MODULE_DIR$/libcore" />
  <excludeFolder url="file://$MODULE_DIR$/libnativehelper" />
  <excludeFolder url="file://$MODULE_DIR$/ndk" />
  <excludeFolder url="file://$MODULE_DIR$/out" />
  <excludeFolder url="file://$MODULE_DIR$/out/eclipse" />
  <excludeFolder url="file://$MODULE_DIR$/out/host" />
  <excludeFolder url="file://$MODULE_DIR$/out/target/common/docs" />
  <excludeFolder url="file://$MODULE_DIR$/out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates" />
  <excludeFolder url="file://$MODULE_DIR$/out/target/product" />
  <excludeFolder url="file://$MODULE_DIR$/packages" />
  <excludeFolder url="file://$MODULE_DIR$/pdk" />
  <excludeFolder url="file://$MODULE_DIR$/prebuilt" />
  <excludeFolder url="file://$MODULE_DIR$/prebuilts" />
  <excludeFolder url="file://$MODULE_DIR$/sdk" />
  <excludeFolder url="file://$MODULE_DIR$/system" />
  <excludeFolder url="file://$MODULE_DIR$/tools" />

接着还要在android stuidio中进行一些源码关联sdk的配置,

然后就可以通过真机调试framework源代码了。手机连上电脑,关联debugger可以看到手机上的所有进程。选择system_process绑定, 然后在activitymanagerservice中找个位置打上断点,随便打开一个app,发现可以跳进断点了。

编译过程完成,后面就是进一步对android framework的学习了,漫漫长路踏出第一步。