搭建编译环境:
在python2环境进行操作
1、安装openjdk8
sudo apt-get install openjdk-8-jdk
sudo apt-get install openjdk-8-jre
配置java版本
sudo update-alternatives --config java
sudo update-alternatives --config javac
2、安装依赖包
sudo apt 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 libgl1-mesa-dev libxml2-utils xsltproc unzip ccache
下载源码:
AOSP的代码管理是基于git的管理方式,但是是由几百个git仓库构成的,这几百个git仓库统一管理就必要要有一个统一的工具,google的工程师用python写了个脚本叫repo,使用它来进行管理android的中每个git仓库对应的版本。
安装git和repo并配置
sudo apt-get install git repo
git config --global user.name "your name"
git config --global user.email "XXX@XXX.com"
配置repo
vim ~/.bashrc
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'
配置其它
vim ~/.bashrc
#添加以下内容
export USE_CCACHE=1
export CCACHE_COMPRESS=1
export LC_ALL=C
下载源码
mkdir aosp
cd aosp
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest
#或者下载特定分支
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-4.0.1_r1
#分支网址:https://source.android.com/setup/start/build-numbers.html
repo sync #开始下载
推荐使用清华大学镜像:
将 https://android.googlesource.com/
全部使用 https://aosp.tuna.tsinghua.edu.cn/代替
开始编译:
cd aosp
. build/envsetup.sh #初始化编译环境
lunch #设置编译目标
make #开始编译 可选参数 -j 指定编辑线程数目
emulator #编译成功后,运行模拟器
#使用emulator时,虚拟机停在黑屏界面,点击无任何响应.此时,可能是kerner内核问题,解决方法如下:
#执行如下命令:
./out/host/linux-x86/bin/emulator -partition-size 1024 -kernel ./prebuilts/qemu-kernel/arm/kernel-qemu-armv7
#使用emulator出现comand not found,需要编译sdk
source ./build/envsetup.sh
lunch sdk
#或者
make sdk
#出现
#emulator: ERROR: x86_64 emulation currently requires hardware acceleration!
#Please ensure KVM is properly installed and usable.
#CPU acceleration status: This user doesn't have permissions to use KVM (/dev/kvm)
sudo apt-get install qemu-kvm cpu-checker
sudo addgroup kvm
sudo usermod -a -G kvm 你的用户名
sudo chgrp kvm /dev/kvm
sudo vim /etc/udev/rules.d/60-qemu-kvm.rules
#添加
KERNEL=="kvm", GROUP="kvm", MODE="0660"
#通过使用kernel-qemu-armv7内核 解决模拟器等待黑屏问题.而-partition-size 1024 则是解决警告: #system partion siez adjusted to match image file (163 MB >66 MB)
#如果你一开始编译的版本是aosp_arm-eng,使用上述命令仍然不能解决等待黑屏问题时,不妨编译#aosp_arm64-eng试试.
编译成功后,我们使用vendorsetup.sh脚本里面的pack函数将编译出来的镜像文件打包成rom,红色部分表示生成的路径。
出现错误:
mkfs.fat: warning - lowercase labels might not work properly with DOS or Windows
mkfs.fat 4.1 (2017-01-24)
.....
AssertionError: Can only handle FAT with 1 reserved sector
.....
ninja: build stopped: subcommand failed.
14:59:40 ninja failed with: exit status 1
解决方法:暂无
出现错误:
subcommand failed.
20:38:09 ninja failed with: exit status 1
build/core/main.mk:24: recipe for target 'run_soong_ui' failed
make: *** [run_soong_ui] Error 1
#### make failed to build some targets (28:58 (mm:ss)) ####
解决方法:
sudo apt-get install aptitude
sudo aptitude install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib
sudo aptitude install -y git flex bison gperf build-essential libncurses5-dev:i386
sudo aptitude install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386
sudo aptitude install dpkg-dev libsdl1.2-dev libesd0-dev
sudo aptitude install git-core gnupg flex bison gperf build-essential
sudo aptitude install zip curl zlib1g-dev gcc-multilib g++-multilib
sudo aptitude install libc6-dev-i386
sudo aptitude install lib32ncurses5-dev x11proto-core-dev libx11-dev
sudo aptitude install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
sudo aptitude install lib32z-dev ccache
关于编译介绍
- 在aosp根目录下,
out
目录是编译之后产生的, 具体介绍如下:
out/target/product/[generic]/system
: 其中,[]
表示的目录是根据你lunch
选项生成的, 例如generic_arm64
表示生成的是arm
架构的64问系统.out/target/product/generic/system/apk
: Android系统自带的apk文件out/target/product/generic/system/bin
: 一些可执行文件(比如C编译的执行)out/target/product/generic/system/lib
: 动态链接库;out/targer/product/generic/system/lib/hw
: 硬件抽象层文件
模块编译
https://bbs.youkuaiyun.com/topics/370150557
除了通过make命令编译可以整个android源码外,Google也为我们提供了相应的命令来支持单独模块的编译.
编译环境初始化(即执行source build/envsetup.sh
)之后,我们可以得到一些有用的指令,除了上边用到的lunch,还有以下:
Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
- lunch: lunch <product_name>-<build_variant>
Selects <product_name> as the product to build, and <build_variant> as the variant to
build, and stores those selections in the environment to be read by subsequent
invocations of 'm' etc.
- tapas: tapas [<App1> <App2> ...] [arm|x86|mips|arm64|x86_64|mips64] [eng|userdebug|user]
- croot: Changes directory to the top of the tree.
- m: Makes from the top of the tree.
- mm: Builds all of the modules in the current directory, but not their dependencies.
- mmm: Builds all of the modules in the supplied directories, but not their dependencies.
To limit the modules being built use the syntax: mmm dir/:target1,target2.
- mma: Builds all of the modules in the current directory, and their dependencies.
- mmma: Builds all of the modules in the supplied directories, and their dependencies.
- provision: Flash device with all required partitions. Options will be passed on to fastboot.
- cgrep: Greps on all local C/C++ files.
- ggrep: Greps on all local Gradle files.
- jgrep: Greps on all local Java files.
- resgrep: Greps on all local res/*.xml files.
- mangrep: Greps on all local AndroidManifest.xml files.
- mgrep: Greps on all local Makefiles files.
- sepgrep: Greps on all local sepolicy files.
- sgrep: Greps on all local source files.
- godir: Go to the directory containing a file.
其中mmm指令就是用来编译指定目录.通常来说,每个目录只包含一个模块.比如这里我们要编译Launcher2模块,执行指令:
mmm packages/apps/Launcher2/
稍等一会之后,如果提示:### make completed success fully ###
即表示编译完成,此时在out/target/product/gereric/system/app
就可以看到编译的Launcher2.apk文件了.
重新打包系统镜像
编译好指定模块后,如果我们想要将该模块对应的apk集成到系统镜像中,需要借助make snod
指令重新打包系统镜像,这样我们新生成的system.img中就包含了刚才编译的Launcher2模块了.重启模拟器之后生效.
单独安装模块
我们在不断的修改某些模块,总不能每次编译完成后都要重新打包system.img,然后重启手机吧?有没有什么简单的方法呢?
在编译完后,借助adb install命令直接将生成的apk文件安装到设备上即可,相比使用make snod,会节省很多事件.
2.编译命令及解释
编译指令 解释
m 在源码树的根目录执行编译
mm 编译当前路径下所有模块,但不包含依赖
mmm [module_path] 编译指定路径下所有模块,但不包含依赖
mma 编译当前路径下所有模块,且包含依赖
mmma [module_path] 编译指定路径下所有模块,且包含依赖
make [module_name] 无参数,则表示编译整个Android代码
下面列举部分模块的编译指令:
模块 make命令 mmm命令
init make init mmm system/core/init
zygote make app_process mmm frameworks/base/cmds/app_process
system_server make services mmm frameworks/base/services
java framework make framework mmm frameworks/base
framework资源 make framework-res mmm frameworks/base/core/res
jni framework make libandroid_runtime mmm frameworks/base/core/jni
binder make libbinder mmm frameworks/native/libs/binder
补充
我们简单的来介绍out/target/product/generic/system
目录下的常用目录:
Android系统自带的apk文件都在out/target/product/generic/system/apk
目录下;
一些可执行文件(比如C编译的执行),放在out/target/product/generic/system/bin
目录下;
动态链接库放在out/target/product/generic/system/lib
目录下;
硬件抽象层文件都放在out/targer/product/generic/system/lib/hw
目录下.
SDK编译
如果你需要自己编译SDK使用,很简单,只需要执行命令make sdk
即可.
编译framework
# 先在framework/base目录下执行
mmm core/res/ # 生成framework-res.apk
# 然后再返回aosp目录,单独编译framework
mmm frameworks/base
编译好模块后,还要重新打包一下system.img
文件(重打包命令如下),这样我们把system.img运行在模拟器上时,就可以看到我们的程序了。
make snod
将源码导入android studio
#编译idegen这个项目,生成idegen.jar文件。
mmm development/tools/idegen/
#生成:android.iws, android.ipr, android.iml这个三个文件。
sudo ./development/tools/idegen/idegen.sh
#android.iws 包含工作区的个人设置,比如打开过的文件,版本控制工具的配置,本地修改历史,运行和#debug的配置等。
#android.ipr 一般保存了工程相关的设置,比如modules和modules libraries的路径,编译器配置,入口#点等。
#android.iml 用来描述modules。它包括modules路径、 依赖关系,顺序设置等。一个项目可以包含多个 #*.iml 文件。
打开Android Studio --> File --> open --> 选中生成的android.ipr文件,确定后就会导入整个源码。
为了加快读取速度,我们定义一些不需要读取的文件夹,比如 build、.repo、device、out 等等。
vim android.iml
#
发现大标签只有三种
<sourceFolder />
<excludeFolder />
<orderEntry />
关于<sourceFolder>标签:
去除不需要debug的<sourceFolder/>标签内容,通常我们只需要frameworks和packages两个目录,所以保留这两个目录有关的标签就行,其他全部删掉,这样索引的速度就会加快了。
关于<excludeFolder>标签:
exclude顾名思义就是不包含的意思。我们有很多目录直接就不想让Studio去管它,不管是索引还是什么等等,所以只需要将这些目录配置到<excludeFolder>中就好了。
** 我这里只保留了framworks和packages模块,将其他模块全部排除了,因此在android.iml中添加了以下配置: 剩下的都删了**
#
<?xml version="1.0" encoding="UTF-8"?>
<module version="4" relativePaths="true" type="JAVA_MODULE">
<component name="ModuleRootManager" />
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<!--sourceFolder标签表示需要索引的代码目录-->
<sourceFolder url="file://$MODULE_DIR$/frameworks/base/core/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
<!--excludeFolder标签表示这个目录下所有内容都不索引-->
<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$/frameworks/base/tests" />
<excludeFolder url="file://$MODULE_DIR$/frameworks/base/tools" />
<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$/pdk" />
<excludeFolder url="file://$MODULE_DIR$/platform_testing" />
<excludeFolder url="file://$MODULE_DIR$/prebuilt" />
<excludeFolder url="file://$MODULE_DIR$/sdk" />
<excludeFolder url="file://$MODULE_DIR$/tools" />
<excludeFolder url="file://$MODULE_DIR$/vendor" />
<excludeFolder url="file://$MODULE_DIR$/toolchain" />
<excludeFolder url="file://$MODULE_DIR$/system" />
<excludeFolder url="file://$MODULE_DIR$/prebuilts" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="inheritedJdk" />
<orderEntryProperties />
</component>
</module>
接下来,修改JDK + SDK,适配编译使用的jdk和sdk版本