前言
近期因工作原因,需要频繁编译、调试Android源码 ,特别是修改framework层的源码,经过不懈努力,终于可以正常调试了。
这里进行一些总结和分享。
参考文章:清华镜像之Android 镜像使用帮助、Android系统源码编译
一、环境准备
1、ubuntu24.04(250G+6核+16GRAM)
2、VirtualBox6.1.34
至于VirtualBox如何安装ubuntu24.04,请参考我的另一篇文章:使用VirtualBox安装Ubuntu系统
二、安装repo
1、简介
Repo 是我们以 Git 为基础构建的代码库管理工具。Repo 可以在必要时整合多个 Git 代码库,将相关内容上传到我们的修订版本控制系统,并自动执行 Android 开发工作流程的部分环节。Repo 并非用来取代 Git,只是为了让您在 Android 环境中更轻松地使用 Git,Repo的常见应用场景:
- 大型软件开发项目:多仓,多分支,多流程
- 多仓管理:多责任田,多评审网站等
- 搭配Gerrit使用
由于Android系统源码是非常庞大的,而且每个模块都是用git来进行管理 ,整个Android源码是由很多个git项目构成,Google对Android代码的更新也是更新到相应模块的git项目上。那对于需要编译Android的开发者来说,要分别clone 每个git项目而且还要放到固定的位置确实是件惨绝人寰的事,所以Google就开发了一个基于Python编写的帮助开发者管理多个项目的工具,这个工具就叫repo,repo就是封装了git命令的python脚本。
2、 安装python3
由于Python 2 的支持已于 2020 年 1 月 1 日停止,现在的Repo也必须使用Python 3。
apt-get install python3
alias python=python3
3、安装Git & 配置Git信息
sudo apt-get install git
git config --global user.name "afinalstone"
git config --global user.email "[email protected]"
git config --list
4、安装curl
sudo apt-get install curl
5、 安装repo
由于国内网络的原因,这里我使用的是清华源来下载源码和repo工具,在下载好repo工具之后,添加对应权限,然后将repo添加到环境变量中。
mkdir ~/bin
sudo chmod 777 ~/bin
PATH=~/bin:$PATH
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH
三、常见异常
1)file=sys.stderr)异常
解决方案:请注意python的版本是python3而不是python2
2)mkdir: cannot create directory ‘xxx’: Permission denied
解决方案:赋予文件读写权限
sudo chmod 777 xxx
3)/usr/bin/env: ‘python’: No such file or directory
解决方案:查找python3的位置,为其创建链接
whereis python3
sudo ln -s /usr/bin/python3 /usr/bin/python
4)Cannot get https://gerrit.googlesource.com/git-repo/clone.bundle
- 解决方案1:可以输入以下指令修改repo仓库更新的地址为国内地址,再尝试repo init
REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'
- 解决方案2:还可以将如下内容复制到~/.bashrc里,这样每次系统启动都会自动修改repo仓库更新的地址为国内地址,再尝试repo init
sudo vim ~/.bashrc
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'
- 解决方案3:直接修改~/bin/repo文件内容中REPO_URL 的赋值
#REPO_URL = os.environ.get('REPO_URL', None) //注释掉这一行,新增下面一行配置
REPO_URL = os.environ.get('REPO_URL', 'https://mirrors.tuna.tsinghua.edu.cn/git/git-repo')
if not REPO_URL:
#REPO_URL = 'https://gerrit.googlesource.com/git-repo' //注释掉这一行,新增下面一行配置
REPO_URL = 'https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'
REPO_REV = os.environ.get('REPO_REV')
if not REPO_REV:
REPO_REV = 'stable'
# URL to file bug reports for repo tool issues.
BUG_URL = 'https://bugs.chromium.org/p/gerrit/issues/entry?template=Repo+tool+issue'
四、使用Repo初始化仓库
1、创建Android系统源码存放目录
mkdir /home/ubuntu/android (根据实际情况来新建目录)
cd /home/ubuntu/android
2、初始化仓库
sudo snap install git-repo
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest
五、同步源码
1、repo指定Android版本
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-9.0.0_r8
2、repo指定Android版本
repo sync (等待源代码下载完成,长时间等待,若失败请检查网络等情况)
四、搭建编译环境
1、安装openJDK8
sudo apt-get update
sudo apt-get install openjdk-8-jdk
2、安装依赖
sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386
sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib
sudo apt-get install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386
sudo apt-get install dpkg-dev libsdl1.2-dev libesd0-dev
sudo apt-get install git-core gnupg flex bison gperf build-essential
sudo apt-get install zip curl zlib1g-dev gcc-multilib g++-multilib
sudo apt-get install libc6-dev-i386
sudo apt-get install lib32ncurses5-dev x11proto-core-dev libx11-dev
sudo apt-get install lib32z-dev ccache
sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
3、 设置启用ccache (加快重新编译源码时的速度。可选)
export USE_CCACHE=1 (在你home主目录的.bashrc中加入)
export CCACHE_DIR=/home/ubuntu/.ccache (指定一个缓存目录,也可以不指定,默认目录为你当前用户目录下的.ccache)
aosp/prebuilts/misc/linux-x86/ccache/ccache -M 50G (这个命令在Android源码中,缓存大小按照自己的硬盘来适当调整)
source ~/.bashrc (source命令使修改立即生效)
4、下载手机驱动
1) 打开Android系统源代码标记和 build列表页面,查看源代码标记和 build版本,主要是为了后面下载对应版本的驱动。
2)从上图可知android-9.0.0_r8系统源码对应的是buildId为PPR2.180905.006.A1,打开Android系统版本驱动列表页面,搜索关键字PPR2.180905.006.A1,找到android-9.0.0_r8对应的驱动。
3)将下载的文件解压放在源码根目录,授权执行sh文件,运行后,会提示你查看证书,按Enter键一行行的查看,出现输入提示时,输入 I ACCEPT,解压到了vendor 目录下
./extract-google_devices-sailfish.sh
./extract-qcom-sailfish.sh
4)对于以上步骤有什么疑惑的可以参考官方文档:谷歌官网文档搭建编译环境
六、编译系统
1、设置环境
使用 envsetup.sh 脚本初始化环境。请注意,将 source 替换成 .(一个点)可以省去一些字符,这种简写形式在文档中更为常用。
source build/envsetup.sh
2、选择目标
使用 lunch 选择要编译的目标。确切的配置可作为参数进行传递。
例如,以下命令表示针对模拟器进行完整编译,并且所有调试功能均处于启用状态。
lunch aosp_arm-eng
直接运行 lunch (没有参数),会列出所有支持的类型,输入对应的序号来进行选择。
所有编译目标都采用 BUILD-BUILDTYPE 形式,其中 BUILD 是表示特定功能组合的代号。BUILDTYPE 是以下类型之一:
useruserdebugeng仅安装标签为 user 的模块安装标签为 user、debug 的模块安装标签为 user、debug、eng 的模块设定属性 ro.secure=1,打开安全检查功能设定属性 ro.secure=1,打开安全检查功能设定属性 ro.secure=0,关闭安全检查功能设定属性 ro.debuggable=0,关闭应用调试功能设定属性 ro.debuggable=1,启用应用调试功能设定属性 ro.debuggable=1,启用应用调试功能设定属性 ro.kernel.android.checkjni=1,启用 JNI 调用检查默认关闭 adb 功能默认打开 adb 功能默认打开 adb 功能关闭root权限开启root权限开启root权限打开 Proguard 混淆器打开 Proguard 混淆器关闭 Proguard 混淆器打开 DEXPREOPT 预先编译优化打开 DEXPREOPT 预先编译优化关闭 DEXPREOPT 预先编译优化3、源码编译您可以使用 make 编译任何代码。GNU make 可以借助 -j【N】 参数处理并行任务,通常使用的任务数 【N】 介于编译时所用计算机上硬件线程数的 1-2 倍之间。例如,在一台双核 E5520 计算机(2 个 CPU,每个 CPU 4 个内核,每个内核 2 个线程)上,要实现最快的编译速度,可以使用介于 make -j16 到 make -j32 之间的命令。
make -j16
如果编译完一个版本后想重新编译一个,可以使用 make clobber清除之前编译生成的文件。我们编译产生的文件都在 out文件夹下。
4、 启动模拟器
编译成功后,将镜像烧入模拟器硬件设备,就可以启动模拟器进入Android系统了
七、如何查看源码的版本
1、 从代码中查看当前版本,找到如下文件
build\core\version_defaults.mk
2、找到关键字 PLATFORM_VERSION
INTERNAL_BUILD_ID_MAKEFILE := $(wildcard $(BUILD_SYSTEM)/build_id.mk)
ifdef INTERNAL_BUILD_ID_MAKEFILE
include $(INTERNAL_BUILD_ID_MAKEFILE)
endif
DEFAULT_PLATFORM_VERSION := PPR1
MIN_PLATFORM_VERSION := PPR1
MAX_PLATFORM_VERSION := PPR1
ALLOWED_VERSIONS := $(call allowed-platform-versions,\
$(MIN_PLATFORM_VERSION),\
$(MAX_PLATFORM_VERSION),\
$(DEFAULT_PLATFORM_VERSION))
ifndef TARGET_PLATFORM_VERSION
TARGET_PLATFORM_VERSION := $(DEFAULT_PLATFORM_VERSION)
endif
ifeq (,$(filter $(ALLOWED_VERSIONS), $(TARGET_PLATFORM_VERSION)))
$(warning Invalid TARGET_PLATFORM_VERSION '$(TARGET_PLATFORM_VERSION)', must be one of)
$(error $(ALLOWED_VERSIONS))
endif
PLATFORM_VERSION.PPR1 := 9
八、系统编译/模块编译
m / mm / mmm / mmma 命令
// 编译整个安卓系统
function m()(
_trigger_build "all-modules""$@")// 编译当前目录下的模块,当前目录下需要有 Android.mk, 否则就往上找最近的 Android.mk 文件
function mm()(
_trigger_build "modules-in-a-dir-no-deps""$@")// 编译指定目录下的模块
function mmm()(
_trigger_build "modules-in-dirs-no-deps""$@")// 当前目录有修改时,可以用这个命令重新编译
function mma()(
_trigger_build "modules-in-a-dir""$@")// 指定目录有修改时,可以用这个命令重新编译
function mmma()(
_trigger_build "modules-in-dirs""$@")
function _trigger_build()(
local -r bc="$1"; shift
ifT="$(gettop)"; then
_wrap_build "$T/build/soong/soong_ui.bash"--build-mode --${bc}--dir="$(pwd)""$@"else>&2 echo "Couldn't locate the top of the tree. Try setting TOP."return1
fi
)
1、完整系统编译
1)进入frameworks的上一级目录
2)source build/envsetup.sh
3)lunch 选择编译的类型
4)使用make命令开始进行系统编译
2、kernel模块编译:
1)/kernel/msm-3.18/drivers/misc/qcom/leapmotor/drv_gpio/
2)进入frameworks的上一级目录
3)source build/envsetup.sh
4)lunch 选择编译的类型
5)输入make bootimage -j16命令开始进行kernel模块的编译
6)根据最终输出信息确认rawprogram-boot.xml文件的路径
7)使用QF进行boot的刷机操作
3、framework/base/services模块编译
修改了framework/base/services目录下面的类代码之后,需要重新编译产生/system/framework/services.jar文件替换原有的文件。
1)进入frameworks的上一级目录
2)source build/envsetup.sh
3)lunch 选择编译的类型
4)在当前目录输入mmm frameworks/base/services/ 或者进入frameworks/base/services目录输入mma命令进行services模块编译
5)编译完毕,services.jar文件的生成目录为:/out/target/product/msm***/system/framework
6)adb root、adb remount获取硬盘读写权限(高版本系统还需要adb disable-verity禁用分区检测)
7)使用adb push services.jar /system/framework/ 替换掉系统中旧的services.jar
4、framework/base/core/res/res模块编译
修改了framework/base/core/res/res目录下面的资源之后,需要重新编译产生/system/framework/framework-res.apk文件替换原有的文件。
1)进入frameworks的上一级目录
2)source build/envsetup.sh
3)lunch 选择编译的类型
4)进入framework/base/core/res目录
5)使用mma命令开始进行res模块的编译
6)编译完毕,framework-res.apk文件的生成目录为:/out/target/product/msm***/system/framework
7)adb root、adb remount获取硬盘读写权限(高版本系统还需要adb disable-verity禁用分区检测)
8)使用adb push services.jar /system/framework/ 替换掉系统中旧的framework-res.apk
5、frameworks/base模块编译
1)进入frameworks的上一级目录
2)source build/envsetup.sh
3)lunch 选择编译的类型
4)进入framework/base/目录
5)使用mma命令开始进行base模块的编译
6)编译完毕,framework.jar文件的生成目录为:/out/target/product/msm***/system/framework
7)adb root、adb remount获取硬盘读写权限(高版本系统还需要adb disable-verity禁用分区检测)
8)使用adb push framework.jar /system/framework/ 替换掉系统中旧的framework.jar
6、SystemUI模块编译:
修改了framework/base/packages/SystemUI目录下面的代码和资源之后,需要重新编译产生/system/priv-app/SystemUI/SystemUI.apk文件替换原有的文件。
1)进入frameworks的上一级目录
2) source build/envsetup.sh
3)lunch 选择编译的类型
4)输入mmm frameworks/base/packages/SystemUI命令开始进行SystemUI模块的编译(也可以直接在framework的上一级目录执行make SystemUI来进行SystemUI模块的编译)
5)编译完毕,根据最终输出信息确认SystemUI.apk件的路径
6)out/target/product/msm***/system/priv-app/SystemUI/SystemUI.apk
7)使用adb push SystemUI.apk /system/priv-app/SystemUI/ 替换掉系统中旧的SystemUI.apk
版权归原作者 AFinalStone 所有, 如有侵权,请联系我们删除。