目录
源码下载完后,真正的编译步骤只有以下几步:
cd android //切到android目录下,即下载的源码根目录
source build/envsetup.sh //也可以. build/envsetup.sh
lunch //选择编译版本类型
23 //针对不同类型选择序号,我这里选择23 user版
make clean //清除out目录,谨慎操作,会删除之前的所有编译,如果是第一次编译就无所谓
make -j8 //真正的源码编译,多线程编译:8为同时编译的线程数,一般Google推荐执行源码编译的线程数 = CPU核心数x 2 + 2,比如4核,就推荐10线程编译,执行make –10
mmm packages/apps/Helloword/ //源码编译完后可以执行单模块编译
源码编译跟源码下载一样是个很漫长的过程。但是编译前的准备不足或有些配置不完整,会导致编译中断或出错,需要重新编译,会浪费很多时间,以下就上面的编译命令作具体讲解。
编译前对编译环境的配置,是我们编译源码的必行之路。介于不同的源码定制厂商对环境配置可能会有一定的出入,因此,这里只是介绍几个基本通用的环境配置命令,供大家参考:
1.1 在 .bashrc文件中添加相关属性:
echo export USE_CCACE=1 >> ~/.bashrc
1.2 为了提高编译效率,我们需要设置编译器高速缓存,执行以下命令:
prebuilts/misc/linux-x86/ccache/ccache -M 50G
-M 50G 两个参数表示设置50G大小的空间作为编译缓存,这个数值可以根据自己的硬盘空间大小进行调整。
(以上两步可以不做)
1.3 导入编译Android源码所需的环境变量和其它参数,运行以下命令:
source build/envsetup.sh //source可以用.代替
1.4 运行lunch命令选择编译目标:
lunch
所有编译目标都采用 BUILD-BUILDTYPE形式,其中 BUILD 是表示特定功能组合的代号。
BUILDTYPE 是以下类型之一:
三者具体差异Google也在官方文档中给出了说明:https://source.android.com/source/building
模拟器一般选eng,调试功能全开。
调试真机的话选userdebug 。
发行最终版本用user 。
官方给出了一份自己出厂设备的代号和编译配置选项
刚开始接触源码时,没有真机,所以第一次选择的是“1”,用的模拟器运行的,在模拟器上折腾了一段时间后果断淘了一台二手的NEXUS 5 ,所以后来又重新选泽aosp_hammerhead-userdebug
编译,每次编译都需要很漫长的等待。
通过make指令进行代码编译,该指令通过-j
参数来设置参与编译的线程数量,以提高编译速度.比如这里我们设置8个线程同时编译:
make -j8
【执行make -j8, 8为同时编译的线程数,一般Google推荐执行源码编译的线程数 = CPU核心数x 2 + 2,比如4核,就推荐10线程编译,执行make –10。】
关于cpu个数,可以用下面命令查看:
cat /proc/cpuinfo | grep processor
可看到自己创建的虚拟机CPU核心共有 4 个,那么要实现最快的编译速度,可以使用介于 make -j4
到 make -j8
之间的命令。
(说明:以上CPU详情是参考网上截图,我用的公司电脑,CPU是单核,执行编译命令make -j4,但是执行到libwebviewchromium.so时执行不下去了,百度之后说是因为内存不足,需增加内存或虚拟内存,所以建议在编译之前增加2GSWAP,具体参考《android源码编译(3)-编译中常见问题》第二点)
然后就是漫长的等待过程……
编译完会生成out目录,out 文件夹内生成 img 文件
system.img:由out/target/product/PRODUCT_OUT/system目录生成
ramdisk.img:由out/target/product/PRODUCT_OUT/root目录生成
userdata.img:由out/target/product/PRODUCT_OUT/data目录生成
boot.img:包含kernel.img和ramdisk.img
recovery.img:我们可以通过boot.img和recovery_from_boot.p文件生成一个recovery.img文件
如果没有真机,只想看下源码或只想先在模拟器上试跑一下,可以通过执行
emulator打开模拟器,如果是真机,可以跳过这一步。
既然谈到了模拟器运行,这里我们顺便介绍模拟器运行所需要四个文件:
Linux Kernel
system.img
userdate.img
ramdisk.img
如果你在使用lunch命令时选择的是aosp_arm-eng,那么在执行不带参数的emualtor命令时,Linux Kernel默认使用的是/source/prebuilds/qemu-kernel/arm/kernel-qemu目录下的kernel-qemu文件;而android镜像文件则是默认使用source/out/target/product/generic目录下的system.img,userdata.img和ramdisk.img,也就是我们刚刚编译出来的镜像文件.
上面我在使用lunch命令时选择的是aosp_arm64-eng,因此linux默认使用的/source/prebuilds/qemu-kernel/arm64/kernel-qemu下的kernel-qemu,而其他文件则是使用的source/out/target/product/generic64目录下的system.img,userdata.img和ramdisk.img.
当然,emulator指令允许你通过参数制定使用不同的文件,具体用法可以通过emulator --help查看
除了通过make命令编译整个android源码外,Google也为我们提供了相应的命令来支持单独模块的编译.
编译环境初始化(即执行source build/envsetup.sh)之后,我们可以得到一些有用的指令,除了上边用到的lunch,还有以下:
简单解释一下:
--mm: 编译当前目录中的所有模块(如果要编译某个模块,需先切换到模块目录中,直接执行mm)。
--mmm: 编译指定目录中的所有模块。
区别:通常来说,每个目录即代表一个模块.比如这里我们要编译Launcher2模块,可以执行指令:
mmm packages/apps/Launcher2/
也可以切换到Launcher2目录中,然后执行:
xxx@ubuntu:~ /android/packages/apps/ Launcher2$ mm
稍等一会之后,如果提示:
### make completed success fully ###
即表示编译完成,此时在out/target/product/gereric/system/app
就可以看到编译的Launcher2.apk文件了。
我们也可以将自己的项目复制到packages/apps目录中,通过以上两种任意命令编译,生成的apk同样会放入out/target/product/gereric/system/app
中,记得项目根目录添加
Android.mk
文件,否则编译不过。关于
Android.mk
的介绍以后会整理。
2.打包
make bootimage //用这条命令可以生成boot.img,这个镜像文件中包含Linux Kernel,Ram disk,生成的boot.img只能通过fastboot进行烧写
make recoveryimage //生成 recovery.img
make systemimage //生成 system.img
make userdataimage //生成userdata.img
make ramdisk //生成ramdisk.img
make snod // 快速打包system.img从已经编译出的包快速重建系统镜像。
如果只是修改out/target/product/xxxx/system目录下内容,可以直接通过make snod快速打包system.img镜像文件。如:将任一apk放入out/target/product/xxxx/system/app目录下,或编译好指定模块后,想要将该模块对应的apk集成到系统镜像中,直接通过make snod
指令重新打包系统镜像,这样我们新生成的system.img中就包含了刚才编译的Launcher2模块.重启模拟器之后生效。刷机到手机也是一样。
自己动手编译Android 8.0源码
https://blog.csdn.net/dl6655/article/details/78869501/
二、Android系统源码编译及刷机实战
https://blog.csdn.net/u012417380/article/details/73196722
Android系统篇(一)——建立Android系统开发环境
https://blog.csdn.net/qq_26787115/article/details/79543340