admin 管理员组

文章数量: 887021

前言

近期因工作原因,需要频繁编译、调试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 "afinalstone@foxmail"
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/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/git-repo/clone.bundle

  • 解决方案1:可以输入以下指令修改repo仓库更新的地址为国内地址,再尝试repo init
REPO_URL='https://mirrors.tuna.tsinghua.edu/git/git-repo'
  • 解决方案2:还可以将如下内容复制到~/.bashrc里,这样每次系统启动都会自动修改repo仓库更新的地址为国内地址,再尝试repo init
sudo vim ~/.bashrc
export REPO_URL='https://mirrors.tuna.tsinghua.edu/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/git/git-repo')
if not REPO_URL:
 #REPO_URL = 'https://gerrit.googlesource/git-repo' //注释掉这一行,新增下面一行配置
 REPO_URL = 'https://mirrors.tuna.tsinghua.edu/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/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/platform/manifest

五、同步源码

1、repo指定Android版本

repo init -u https://aosp.tuna.tsinghua.edu/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/ache  (指定一个缓存目录,也可以不指定,默认目录为你当前用户目录下的ache)
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
    if T="$(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."
      return 1
    fi
)

九、各个模块具体编译指令

9.1 完整系统编译

1)进入frameworks的上一级目录
2)source build/envsetup.sh
3)lunch 选择编译的类型
4)使用make命令开始进行系统编译

9.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的刷机操作

9.3 framework/base/services模块编译

修改了framework/base/services目录下面的类代码之后,需要重新编译产生/system/framework/services.jar文件替换原有的文件。

9.3.1 Android12之前的版本

1)进入frameworks的上一级目录
2)source build/envsetup.sh
3)lunch 选择编译的类型
4)在当前目录输入make services 或者进入frameworks/base/services目录输入mma命令进行services模块编译
5)编译完毕,services.jar文件的生成目录为:/out/target/product/msm***/system/framework
6)adb root、adb remount获取硬盘读写权限
7)使用adb push services.jar /system/framework/ 替换掉系统中旧的services.jar

9.3.2 Android12版本

1)进入frameworks的上一级目录
2)source build/envsetup.sh
3)lunch 选择编译的类型
4)在当前目录输入make services 或者进入frameworks/base/services目录,如果直接mma会提示错误,可以删除tests目录,然后再输入mma指令进行services模块编译
5)编译完毕,services.jar文件的生成目录为:/out/target/product/msm***/system/framework
6)adb root、adb remount获取硬盘读写权限
7)使用adb push services.jar /system/framework/ 替换掉系统中旧的services.jar

9.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获取硬盘读写权限
8)使用adb push services.jar /system/framework/ 替换掉系统中旧的framework-res.apk

9.5 frameworks/base模块编译

修改了framework/base目录下面的类代码之后,需要重新编译产生/system/framework/framework.jar文件替换原有的文件。

9.5.1 Android12之前的版本

1)进入frameworks的上一级目录
2)source build/envsetup.sh
3)lunch 选择编译的类型
4)使用make framework命令或者进入framework/base/目录使用mma命令开始进行base模块的编译
5)编译完毕,framework.jar文件的生成目录为:/out/target/product/msm***/system/framework
6)adb root、adb remount获取硬盘读写权限
7)使用adb push framework.jar /system/framework/ 替换掉系统中旧的framework.jar

9.5.2 Android12版本

1)进入frameworks的上一级目录
2)source build/envsetup.sh
3)lunch 选择编译的类型
4)输入make framework-minus-apex -j16
5)使用adb push framework.jar /system/framework/ 替换掉系统中旧的framework.jar

9.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

本文标签: 系统 源码 镜像 Android