编译源码基本上都是在linux环境下编译,所以我们在window系统中使用虚拟机安装ubuntu系统来编译
1.虚拟机安装 Ubuntu
首先是下载Ubuntu系统镜像,我一开始下载的ubuntu官网上最新版Ubuntu 22.04 LTS,后来repo同步 android12源码的时候始终失败,但同步 android9源码会成功,后来换了Ubuntu18.04 LTS,终于repo同步成功。
简单说下载Ubuntu18.04 LTS版本,切记切记Ubuntu官网下载
拉到最下面就是:
不排除是我人品太差,你们可以试试这22.04版本。
安装Ubuntu前提一嘴:
1.如果你的电脑内存足够大,比如32G,那么在按照下面的安装步骤进行到给Ubuntu分配内存的时候,直接分配20G以上,会让你少走很多弯路。我的电脑总共16G,Ubuntu分配了8G。
2.给Ubuntu分配磁盘空间的时候至少分配200G,因为源码下载下来很大
3.安装Ubuntu过程中遇到安装界面被遮挡点不了“下一步”按钮,尝试按住win键然后鼠标拖动界面
然后下载虚拟机,VirtualBox 和VMware workstation 二选一:
VirtualBox安装Ubuntu
VMware安装Ubuntu
我用的VMware
2.下载AOSP源码
AOSP(Android Open Source Project)是Google开放的Android 开源项目,中文官网为:https://source.android.google.cn/
AOSP通俗来讲就是一个Android系统源码项目,通过它可以定制 Android 操作系统,国内手机厂商都是在此基础上开发的定制系统。因为墙的缘故,如果无法连接谷歌服务器获取AOSP源码,可以从 清华大学镜像站或者 中科大镜像。本篇文章以清华大学镜像站为例。
2.1下载 repo工具
Android源码包含数百个git库,光是下载这么多的git库就是一项繁重的任务,所以Google开发了repo,它是用于管理Android版本库的一个工具,使用了Python对git进行了一定的封装,简化了对多个Git版本库的管理。
安装 Git,在Ubuntu 终端输入如下命令:
sudo apt-get install git
设置git身份,添加自己的邮箱和姓名:
git config --global user.email "xxxx@qq.com"
git config --global user.name "xxxx"
创建bin,并加入到PATH中:
mkdir ~/bin
PATH=~/bin:$PATH
安装curl库:
sudo apt-get install curl
下载repo并设置权限:
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/bin/repo
chmod a+x ~/bin/repo
安装python,repo初始化时会用到:
sudo apt-get install python
2.2下载源码
下载源码大概有两种方式(参考清华源AOSP):1.使用每月更新的初始化包;2.传统初始化方法
网上aosp编译教程大多数选择的是传统初始化方法,这里我把2种都列出来
2.2.1 使用每月更新的初始化包
这个方式对磁盘空间要求较大,初始化包是个压缩包大概在190G左右,然后还得解压,所以磁盘要求起码400G起步,如果你在之前安装Ubuntu的时候分配的空间不足400G要么进行扩容,要么使用2.2.2传统初始化方法。
使用每月更新的初始化包
我们强烈建议您使用初始化包进行初始化。
下载 https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar,下载完成后记得根据 checksum.txt 的内容校验一下。
由于所有代码都是从隐藏的.repo
目录中 checkout 出来的,所以我们只保留了.repo
目录,下载后解压 再repo sync
一遍即可得到完整的目录。
首先我们先下载这个aosp-latest.tar,这个包接近200G因为它包含了所有版本信息!如果觉得太大,请看2.2.2传统方法。
可以在ubuntu使用终端命令下载,也可以在windows里使用迅雷等工具下载然后再通过共享文件夹复制到ubuntu里,然后解压 ,然后把代码checkout出来 checkout参考清华源AOSP,在ubuntu里下载也参考清华源AOSP
2.2.2 传统初始化方法
建立工作目录 :
mkdir aosp_12
cd aosp_12
repo的运行过程中会尝试访问官方的git源更新repo自己,如果想使用tuna的镜像源进行更新,可以将如下内容复制到你的~/.bashrc里
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'
找不到.bashrc文件?
打开Ubuntu桌面的文件 ,如图:
按快捷键crtl+H 显示隐藏文件,即可看到
初始化仓库:
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest
初始化并指定版本:
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-12.0.0_r8
这里我下载的是android12源码,android所有版本参考:https://source.android.google.cn/setup/start/build-numbers#source-code-tags-and-builds
同步源码:
repo sync
然后等待即可,几个小时左右吧。可能我人品太差,我一开始在ubuntu22.04上下载源码,下了几天尝试多次都不成功。后来使用ubuntu18.04一次成功。
成功会类似下图:
2.3下载内核源码
AOSP源码中并不包括内核源码,需要单独下载,内核源码有很多版本,比如common是通用的Linux内核,msm是用于使用高通MSM芯片的Android设备,goldfish是用于Android模拟器的内核源码,这里以goldfish为例。
和下载AOSP源码一样,我们需要先建立工作目录 :
mkdir kernel
cd kernel
使用清华的镜像:
git clone https://aosp.tuna.tsinghua.edu.cn/kernel/goldfish.git
完成后kernel目录中会生成一个goldfish文件夹,进入goldfish目录并使用git命令
cd goldfish
git branch -a
这时会列出有哪些内核的版本分支可以下载
这里选择下载goldfish 3.4版本
git checkout remotes/origin/android-goldfish-3.4
3.开始编译源码
3.1准备编译环境
安装 jdk8
sudo apt-get update
sudo apt-get install openjdk-8-jdk
安装依赖包
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
设置Ubuntu处理器数量
Ubuntu关机,在VirtualBox主页进入Ubuntu右侧设置–>系统–>处理器选项,设置处理器数量,设置最大处理器数量的一半或更高,也不要设置最大,容易卡主,我设置了一半。
3.2给Ubuntu增加虚拟内存
为什么要增加虚拟内存?编译Android12源码的时候提示如下:
意思是需要16G左右的内存(实测已经超过16G,如果你没有分配20G还是使用虚拟内存吧),而我们之前安装Ubuntu的时候只分配了8G,编译一定会失败!Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
已经分配20G内存的跳到段落3.3继续
所以需要添加虚拟内存(swap交换空间)
Linux 的交换分区(swap),或者叫内存置换空间(swap space),是磁盘上的一块区域,可以是一个分区,也可以是一个文件,或者是他们的组合。交换分区的作用是,当系统物理内存吃紧时,Linux 会将内存中不常访问的数据保存到 swap 上,这样系统就有更多的物理内存为各个进程服务,而当系统需要访问 swap 上存储的内容时,再将 swap 上的数据加载到内存中,也就是常说的 swap out 和 swap in。
首先查看是否已经存在交换空间,终端输入:
free -m
我们安装的Ubuntu默认有2G大小的swap空间,如图
使用以下命令查看swap详情:
swapon -s
可以看到我们Ubuntu上的默认的swap是存放在根目录的swapfile文件,我们去根目录找一下看看,进入根目录方法:
打开ubuntu桌面“文件”->点击其他位置->点击计算机 即可查看到
我们可以看到swapfile文件,2.1G没有错3.2.1 已存在swap交换空间
如果swap空间超过16G,则跳到3.3步骤;
如果swap空间没有16G,那么我们给它扩容,默认只有2G,那么我们给它扩容(其实就是停用删除这个小的,然后重新创建启用一个大的)
停用交换文件:
sudo swapoff /swapfile
删除文件:
sudo rm /swapfile
删除后继续创建↓
3.2.2 创建swap交换空间
新建swap空间,以16G为例,创建文件:
sudo fallocate -l 16G /swapfile
这里我们还是命名为“swapfile”,当然你也可以随意写
查看文件信息:
ls -lh /swapfile
设置文件权限:
sudo chmod 600 /swapfile
再次查看文件信息,权限已改变:
挂载:
sudo mkswap /swapfile
激活启用:
sudo swapon /swapfile
再次查看内存使用情况:
free -m
发现交换空间 16G,然后还有重要的一步把交换信息写入系统配置,不然Ubuntu重启后以上配置swap空间工作得重新做
使用vim编辑器打开配置文件:
sudo vim /etc/fstab
如果提示vim找不到命令,使用以下命令安装vim,然后再次打开配置文件
sudo apt-get install vim
打开配置文件如下:
发现已经存在/swapfile 这条信息,并且你后来创建的16G的文件使用的名字依然是“swapfile ”,那么我们直接退出编辑器,不用修改
如果你起的是别的名字,那么需要进行配置。
最后一行插入(vim打开后按i进入编辑模式,移动光标到最后回车换行):
/swapfile swap swap defaults 0 0
编辑好之后按ESC键退出编辑模式,然后依次输入:wq(英文冒号+wq)保存退出
重启Ubuntu 再次查看内存使用情况:
free -m
发现交换空间存在。
3.3 编译源码
3.3.1 初始化环境
cd进入AOSP的目录,依次输入如下2个命令:
source build/envsetup.sh
// 编译前删除build文件夹A
make clobber
3.3.2 选择编译目标
输入命令:
lunch
lunch命令用来让用户选择编译目标,只有在source build/envsetup.sh之后才会有效,不然会报命令not found
这里我又踩了一个坑,参照其他人的比较老的教程选择了aosp_x86-eng,这是可以运行在模拟器上。
Which would you like? [aosp_arm-eng]后面直接输入对应序号39就可以。
此序号39不是固定,不同版本源码列表不一样。
也可以使用命令lunch aosp_x86-eng直接指定编译的目标(不用每次都列出一个表然后输入39
然而我最终编译成功之后无法在模拟器上运行,因为android12源码改了!奶奶的,使用aosp_x86-eng编译并不能在模拟器上运行,无法启动的原因是没有生成相关*-qemu.img, 提示:Could not open '****/userdata-qemo.img':No such file or directory
寻找一番解决方案,使用以下方式编译:
lunch sdk_phone_x86_64
细心的朋友可能发现了“sdk_phone_x86_64”并没有出现在上面的lunch列表里,但实际上是存在的:
3.3.3 开始编译
如果你在Ubuntu安装时分配的内存就大于16G,那么直接执行下面的编译命令,如果你害怕编译失败浪费时间,那么直接按3.3.4把所有的解决方案操作一遍,再运行编译命令:
make -j6
这里的6是指并行任务数,我给虚拟机分配了6核,所以我用了参数6,理论上是可以设置到最大值12(6核12线程),以提高编译速度,开始编译后会提示需要16G左右的内存,如果编译失败,请减少-j的参数,我实测减少-j参数并没有用,唯一有用的就是增大内存.
如果一切顺利,编译成功会这样:
日啊,编译了7个多小时,我的电脑太垃圾了啊。终于成功了!前前后后花了10几天终于成功!
但是很可能会失败报错:
3.3.4 解决OOM内存不足的问题
明明已经创建了虚拟内存,为什么还会报OOM错误?
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
ninja failed with: exit status 1
我搜索了一些资料发现很多人都有这个问题,说是编译的时候这个虚拟内存根本就没有被利用到,我晕!
新建一个终端,输入命令:
top
上面那行KiB Mem是物理内存,下面那行KiB Swap就是我们的虚拟内存(交换空间),通过这个界面我们可以监测swap用上了没有。
我再次执行编译命令,然后报OOM错误,通过top信息查看到这个虚拟内存确实几乎没有被利用。
那么接下来进行一些设置,让虚拟内存能够被利用:
方法来自:(Ubuntu解决swap分区未被使用的问题)
终端输入命令:
sudo vim /etc/sysctl.conf
在最后面添加如下语句(按i进入编辑模式,光标移到最后,插入语句)
vm.min_free_kbytes=1500000
保存退出(按ESC退出编辑模式,输入:wq保存退出)
然后重启开机
原链接是这么写的:
更改swap配置,让系统RAM还有250000kbyte(可根据自己电脑的RAM自定义,系统的默认值很小,导致已经卡死了才会启动swap,我是8G内存所以设置250000)
原链接是4个0,可用内存不足250M时启用swap,我直接加了个0,我分配给Ubuntu的内存为8G,这样不足1.5G的时候就启用swap,我觉得这样更保险。如果你给Ubuntu分配的内存为4G,我建议你不要设置1.5G,这样可能会影响到系统正常运行,因为虚拟内存效率没有物理内存高的,所以你系统可能很频繁的启用swap可能会卡,设置1G试一下。
重启后再次编译,有效果!
top信息可以看到swap空间利用起来了,你以为就这么结束了?
后面又奔溃了,还是OOM错误,不过又多了一行错误信息:
ninja: build stopped: subcommand failed.
找到一个解决办法:https://forum.xda-developers.com/t/guide-how-to-build-android-11-with-low-ram.4298483
找到 aosp_12/build/soong/java/droidstubs.go 文件,双击打开,搜索“cmd.BuiltTool("metalava")”定位到代码处,然后新加语句:
Flag("-J-Xmx6114m").
保存退出
然后再次编译!一直等一直等,成功了!
3.3.5 模拟器运行
模拟器运行可能会出现问题:
问题1:ERROR: x86_64 emulation currently requires hardware acceleration
模拟器需要硬件加速,我使用的虚拟机是VMware workstation
解决参考:https://blog.csdn.net/mvp_Dawn/article/details/107678057
问题2:打开硬件加速后,Ubuntu无法启动提示:
此平台不支持虚拟化的 Intel VT-x/EPT。 不使用虚拟化的 Intel VT-x/EPT,是否继续?
VMware Workstation 在此主机上不支持嵌套虚拟化。 模块“HV”启动失败。 未能启启动虚拟机
我按照这个解决了:https://blog.csdn.net/m0_62571257/article/details/124102636
其他一些问题记录:
make clobber
它会删除所有设置所生成的所有的output与中间文件。
等价于指令
rm -rf out/
如果遇到make clobber一直卡住的,可以试试rm这个命令
感谢:
http://liuwangshu.cn/framework/aosp/1-install-ubuntu.html
http://liuwangshu.cn/framework/aosp/2-download-aosp.html
https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/
https://forum.xda-developers.com/t/guide-how-to-build-android-11-with-low-ram.4298483/
https://blog.csdn.net/SSchawn/article/details/116138896