更新2.2.1

This commit is contained in:
feiocng 2023-03-06 11:47:18 +08:00
parent 54ef6491fa
commit e130a00706

View File

@ -10,20 +10,21 @@
## 2.2 环境准备 ## 2.2 环境准备
安卓系统在低于版本10之前是支持macOS系统上编译AOSP代码的。在新版本系统的演进过程中安卓官方已经放弃在macOS系统平台上做AOSP开发的支持官方开发指导环境采用了Linux上比较有名的Ubuntu发行版本。 安卓系统在版本10之前是支持macOS系统上编译AOSP代码的。在新版本系统的演进过程中安卓官方已经放弃在macOS系统平台上做AOSP开发的支持官方开发指导环境采用了Linux上比较流行的Ubuntu发行版本。
在实际的开发过程中可以使用Windows系统下的WSL2或Docker来构建一个Ubuntu系统运行环境同样可以完成AOSP编译与开发工作。 在实际的开发过程中可以使用Windows系统下的WSL2或Docker来构建一个Ubuntu系统运行环境同样可以完成AOSP编译与开发工作。
这一节将会介绍在Windows系统与Linux系统上如何完成环境准备工作。 这一节将会介绍在Windows系统与Linux系统上如何完成环境准备工作。
### 2.2.1 Windows ### 2.2.1 Windows
由于在Windows中缺少了各种底层支持,所以一般情况我们不会直接在Windows环境中编译而是选择在Windows中创建一个Linux的虚拟环境然后在虚拟环境中安装编译所需要用到的底层依赖。而Windows的虚拟机环境我们有多种选择例如Docker、WSL2、Vmware 由于在Windows中缺少了各种底层编译器与开发库的支持,一般情况下,开发人员不会直接在Windows环境中编译而是选择在Windows中创建一个Linux的虚拟环境然后在虚拟环境中安装编译所需要用到的底层依赖。在Windows系统上部署Ubuntu虚拟环境有多种可选方案例如Docker、WSLWindows Subsystem for Linux、Vmware虚拟机QEMU、HyperV虚拟机平台等等
三种虚拟环境我都尝试过编译其中Docker在Windows的体验并不怎么好特别是在我们编译需要较大体积硬盘的情况下完整编译后下次开机耗时明显变高。如果不擅长折腾的话不太建议在Windows下采用Docker来编译源码。 几种方案经过编译对比测试发现Docker在Windows系统上的体验并不怎么好主要体现在编译这类大型项目时需要较大的磁盘存储空间选择外挂磁盘映射时编译时IO性能较弱而选择创建虚拟磁盘时对宿主机的开机耗时明显变高。这里不太建议在Windows下采用Docker来编译源码。
WSL2是Windows下内置的Linux子系统是一个非常轻量化的Linux系统如果你是属于那种又想在Windows中编译但是又不想打开虚拟机那选择WSL2就没错了。使用起来的感觉就好似直接使用命令行一样。并且编译性能相比Vmware要更加高效。在我的笔记本环境中WSL2完整编译的耗时为130分钟Vmware的耗时是170分钟这是因为它是完全直连计算机硬件无需虚拟化硬件的。所以性能是有较为显著的提升。 WSL是Windows下内置的Linux子系统最新的版本号为2通常将其称为WSL2。它是一个非常轻量化的Linux系统让那些想在Windows中编译与运行Linux程序的开发人员爱不释手。安装好WSL2后只要在终端中输入一个`wsl`命令就可以启动环境。使用起来的感觉就好似直接使用命令行一样。并且编译性能相比`Vmware`这类虚拟机要更加高效。在我的笔记本环境中WSL2完整编译的耗时为130分钟`Vmware`虚拟机的耗时是170分钟这是因为WSL2采用直通计算机硬件IO性能有着较为显著的提升。
如果你是Windows10的环境那么你需要先查询当前系统版本必须是18917或更高的版本才支持WSL2。在cmd命令行中输入`winver`查看当前版本 如果你的系统上Windows10那么你需要先查询当前系统版本必须是18917或更高的版本才支持WSL2。在cmd命令行中输入`winver`命令查看当前系统版本号。
![image-20230102183339463](.\images\image-20230102183339463.png) ![image-20230102183339463](.\images\image-20230102183339463.png)
@ -31,50 +32,51 @@
![img](.\images\69ba546fd55c4fea8ef9b5d55a9bd354.png) ![img](.\images\69ba546fd55c4fea8ef9b5d55a9bd354.png)
或者是采用命令的方式开启虚拟机平台和Linux子系统使用管理员权限启动PowerShell 或者是采用命令的方式开启虚拟机平台和Linux子系统使用管理员权限启动` `
![image-20230102183708998](.\images\image-20230102183708998.png) ![image-20230102183708998](.\images\image-20230102183708998.png)
执行下面的命令开启功能 执行下面的命令开启功能
~~~ ```
//启用虚拟机平台 //启用虚拟机平台
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
//启用Linux子系统 //启用Linux子系统
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
~~~ ```
启动完成后重启计算机,然后我们就可以开始安装一个ubuntu了。直接打开Microsoft Store应用商店搜索ubuntu然后选择自己需要的版本即可例如我安装的是22.04版本,如下图。 启动完成这些特性计算机,然后我们就可以开始安装一个`Ubuntu`系统了。打开Microsoft Store应用商店搜索`Ubuntu`系统然后选择自己需要的版本即可例如我安装的是22.04版本,如下图。
![image-20230102184626538](.\images\image-20230102184626538.png) ![image-20230102184626538](.\images\image-20230102184626538.png)
成功获取ubuntu后从应用中启动ubuntu即开始正式安装。安装完成后我们点细节需要处理子系统需要迁移由于应用商店默认会给我们安装在C盘中而我们编译系统会占用相当大的空间所以必须将子系统迁移到其他硬盘中。首先打开命令行工具查询当前的子系统名称。 成功获取`Ubuntu`系统后从应用中启动系统即开始正式安装。安装过程只需要设置好用户名与密码即可。完成后会进行一个shell环境供用户输入。
需要注意的是应用商店默认会将WSL安装在C盘中而我们编译系统会占用相当大的空间如果你的系统盘空间不够需要做一个迁移操作将子系统迁移到其他硬盘中。操作方法是桌面任意位置右键选择终端在打开的终端环境中自毁长城下面的命令查询当前的子系统名称。
~~~ ```
wsl -l -v wsl -l -v
NAME STATE VERSION NAME STATE VERSION
* ubuntu22 Running 2 * ubuntu22 Running 2
~~~ ```
然后我们将这个子系统导出,并且注销掉,然后再重新导入放在其他磁盘的子系统 然后,执行`wsl --export`命令,将子系统导出到其它较大空间的分区中;接着,执行`wsl --unregister`将其注销,最后,执行`wsl --import `再重新导入放在其他分区或磁盘上的子系统。如下所示
~~~ ```
//导出子系统 //导出子系统
wsl --export ubuntu22 E:\wsl2\ubuntu22.tar wsl --export ubuntu22 E:\wsl2\ubuntu22.tar
//注销之前的虚拟机 //注销之前的虚拟机
wsl --unregister ubuntu22 wsl --unregister ubuntu22
//重新导入虚拟机,并且指定新的虚拟机存放位置 //重新导入虚拟机,并且指定新的虚拟机存放位置
wsl --import ubuntu22 E:\wsl2\ubuntu22_wsl E:\wsl2\ubuntu22.tar wsl --import ubuntu22 E:\wsl2\ubuntu22_wsl E:\wsl2\ubuntu22.tar
~~~ ```
这时我们在直接在命令行执行`wsl`即可进入子系统 现在,再次执行`wsl`命令即可进入子系统的shell环境
使用WSL2主要是在于轻量级和更优的高性能一般都是命令模式的linux即使我们在WSL2中安装了图形界面也会存在一些依赖缺陷所以使用WSL2开发时一般是在Windows使用插件来远程代码管理进行开发。例如使用vscode就直接用wsl插件可以快速的远程访问代码或者是安装ssh服务后使用remote ssh插件进行代码修改 使用WSL2主要是在于轻量级和更优的高性能一般都是命令模式的Linux图形界面的程序可以通过安装一些依赖来解决但这不是WSL2的强项。使用WSL2搭建开发环境时使用远程开发模式不失为一种优雅的技术方案典型的有使用`vscode`配合wsl插件可以快速的远程访问WSL2环境上的代码与程序另外WSL2安装ssh服务后`vscode`配合使用remote ssh插件也可以进行开发环境的搭建
如果我们需要完整的Linux虚拟机使用VMware会更加的省事。步骤也非常简单流程如下。 如果需要完整的Linux系统环境使用`VMware`虚拟机会更加的合适。步骤也非常简单,流程如下。
1、下载并安装VMware虚拟机然后下载ubuntu22.04镜像 1、下载并安装`VMware`虚拟机然后下载Ubuntu22.04系统ISO镜像文件
2、VWware创建虚拟机选择指定镜像 2、VWware创建虚拟机选择指定镜像
@ -84,7 +86,7 @@ wsl --import ubuntu22 E:\wsl2\ubuntu22_wsl E:\wsl2\ubuntu22.tar
![image-20230102194243774](.\images\image-20230102194243774.png) ![image-20230102194243774](.\images\image-20230102194243774.png)
4、选择虚拟机保存位置这里不要保存在c记得磁盘要有至少300G的空间 4、选择虚拟机保存位置这里不要保存在C记得磁盘要有至少300G的空间
![image-20230102194331141](.\images\image-20230102194331141.png) ![image-20230102194331141](.\images\image-20230102194331141.png)
@ -100,7 +102,7 @@ wsl --import ubuntu22 E:\wsl2\ubuntu22_wsl E:\wsl2\ubuntu22.tar
![image-20230102194952517](.\images\image-20230102194952517.png) ![image-20230102194952517](.\images\image-20230102194952517.png)
虚拟机开机后将默认进入Ubuntu安装界面按照提示进行选择语言区域等待安装完成即可。 虚拟机开机后将默认进入Ubuntu安装界面按照提示进行选择语言区域等待安装完成即可。
### 2.2.2 Linux ### 2.2.2 Linux
@ -114,7 +116,7 @@ wsl --import ubuntu22 E:\wsl2\ubuntu22_wsl E:\wsl2\ubuntu22.tar
然后用命令更新一下软件,并安装一下基本的工具 然后用命令更新一下软件,并安装一下基本的工具
~~~ ```
// 更新软件列表 // 更新软件列表
sudo apt update -y && sudo apt upgrade -y sudo apt update -y && sudo apt upgrade -y
@ -131,7 +133,7 @@ echo -e '\n[install]\ntrusted-host=pypi.douban.com\n[global]\nindex-url=http://p
cat ~/.pip/pip.conf cat ~/.pip/pip.conf
pip install pytest pip install pytest
~~~ ```
@ -159,7 +161,7 @@ pip install pytest
上面知道了我们需要的目标分支接下来要拉取代码。repo是一个以git为基础包装的代码版本管理工具内部是由python脚本构成的对git命令进行包装主要为了方便管理大型的项目使用repo可以非常方便的拉取对应的分支节点。下面我们开始拉取代码。 上面知道了我们需要的目标分支接下来要拉取代码。repo是一个以git为基础包装的代码版本管理工具内部是由python脚本构成的对git命令进行包装主要为了方便管理大型的项目使用repo可以非常方便的拉取对应的分支节点。下面我们开始拉取代码。
~~~ ```
// 安装git // 安装git
sudo apt-get install git sudo apt-get install git
@ -192,11 +194,11 @@ repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-12.0
// 同步代码 // 同步代码
repo sync -c -j8 repo sync -c -j8
~~~ ```
同步代码`repo sync -c -j8`的命令其中`-c`表示只同步当前分支代码,可以提高同步速度,而`-j`是设置同步使用的线程数这里我使用了8条线程但并不是线程越多速度越快而是根据cpu的核心使用最合理的线程数才能达到最佳的并发效果。 同步代码`repo sync -c -j8`的命令其中`-c`表示只同步当前分支代码,可以提高同步速度,而`-j`是设置同步使用的线程数这里我使用了8条线程但并不是线程越多速度越快而是根据cpu的核心使用最合理的线程数才能达到最佳的并发效果。
~~~ ```
// 查看可用cpu数量我的环境显示为16 // 查看可用cpu数量我的环境显示为16
nproc --all nproc --all
@ -205,25 +207,25 @@ repo sync -c -j16
//也可以直接省略成一句 //也可以直接省略成一句
repo sync -c -j$(nproc --all) repo sync -c -j$(nproc --all)
~~~ ```
代码同步完成后,会提示`Success`,如果失败了,就重新拉取即可,多拉取几次后,基本都能同步成功。接下来我们开始安装编译的底层依赖。 代码同步完成后,会提示`Success`,如果失败了,就重新拉取即可,多拉取几次后,基本都能同步成功。接下来我们开始安装编译的底层依赖。
~~~ ```
// AOSP编译的相关依赖安装 // AOSP编译的相关依赖安装
sudo apt-get install -y git-core gnupg flex bison build-essential \ sudo apt-get install -y git-core gnupg flex bison build-essential \
zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev \ zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev \
x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip \ x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip \
fontconfig libncurses5 procps rsync libsqlite3-0 fontconfig libncurses5 procps rsync libsqlite3-0
~~~ ```
依赖安装完成后,我们再进行一个细节调整,由于我们经常需要备份代码,将整个源码进行打包备份,但是编译出来的输出目录`out`的体积非常庞大,所以我备份时会选择移走`out`目录,或者干脆删除掉,这样非常的麻烦,所以我会选择直接修改编译输出的目录。通过设置环境变量`OUT_DIR`就可以调整编译结果的输出目录了。 依赖安装完成后,我们再进行一个细节调整,由于我们经常需要备份代码,将整个源码进行打包备份,但是编译出来的输出目录`out`的体积非常庞大,所以我备份时会选择移走`out`目录,或者干脆删除掉,这样非常的麻烦,所以我会选择直接修改编译输出的目录。通过设置环境变量`OUT_DIR`就可以调整编译结果的输出目录了。
~~~ ```
vim ./build/envsetup.sh vim ./build/envsetup.sh
// 在底部加上环境变量设置为和源码同一级的目录,我当前源码路径为~/android_src/aosp12 // 在底部加上环境变量设置为和源码同一级的目录,我当前源码路径为~/android_src/aosp12
export OUT_DIR=~/android_src/aosp12_out export OUT_DIR=~/android_src/aosp12_out
~~~ ```
在开始编译前,我们还需要准备对应设备的驱动,根据我们前面选择的版本号`SP1A.210812.016.A1`,在官网地址:`https://developers.google.com/android/drivers`中找到对应的版本号,并且可以看到`Pixel 3`的手机对应的代号是`blueline` 在开始编译前,我们还需要准备对应设备的驱动,根据我们前面选择的版本号`SP1A.210812.016.A1`,在官网地址:`https://developers.google.com/android/drivers`中找到对应的版本号,并且可以看到`Pixel 3`的手机对应的代号是`blueline`
@ -235,7 +237,7 @@ export OUT_DIR=~/android_src/aosp12_out
点击`Link`下载然后将下载的文件拷贝到Android源码根目录下。然后解压并导出相关驱动文件。 点击`Link`下载然后将下载的文件拷贝到Android源码根目录下。然后解压并导出相关驱动文件。
~~~ ```
// 解压驱动文件 // 解压驱动文件
tar -xvf qcom-blueline-sp1a.210812.016.a1-33e668b9.tgz tar -xvf qcom-blueline-sp1a.210812.016.a1-33e668b9.tgz
tar -xvf google_devices-blueline-sp1a.210812.016.a1-d10754e0.tgz tar -xvf google_devices-blueline-sp1a.210812.016.a1-d10754e0.tgz
@ -244,11 +246,11 @@ tar -xvf google_devices-blueline-sp1a.210812.016.a1-d10754e0.tgz
// 依次运行两个文件运行后会提示许可说明按回车键然后按q跳过最后手动输入I ACCEPT后回车即可 // 依次运行两个文件运行后会提示许可说明按回车键然后按q跳过最后手动输入I ACCEPT后回车即可
./extract-google_devices-blueline.sh ./extract-google_devices-blueline.sh
./extract-qcom-blueline.sh ./extract-qcom-blueline.sh
~~~ ```
导入设备驱动完成后,准备工作基本完成,可以开始编译源码了。 导入设备驱动完成后,准备工作基本完成,可以开始编译源码了。
~~~ ```
// 初始化环境,执行后会导入多个命令,辅助我们进行编译。 // 初始化环境,执行后会导入多个命令,辅助我们进行编译。
// 这里也可以使用. build/envsetup.sh 是同样的效果 // 这里也可以使用. build/envsetup.sh 是同样的效果
source ./build/envsetup.sh source ./build/envsetup.sh
@ -275,7 +277,7 @@ Which would you like? [aosp_arm-eng]
// 和上面一样。直接使用当前cpu的核心数作为编译的并发线程 // 和上面一样。直接使用当前cpu的核心数作为编译的并发线程
make -j$(nproc --all) make -j$(nproc --all)
~~~ ```
在上面选择版本中可以看到`aosp_arm-eng``aosp_arm64-eng`的选项,这两个是模拟器使用的版本。而模拟器使用的版本是可以不需要导入设备驱动文件的。如果在`lunch`的菜单中没有看到你要编译的版本,并且直接`lunch aosp_blueline-userdebug `也提示错误,可能是没有成功导入驱动文件,或者下载的驱动文件不对。 在上面选择版本中可以看到`aosp_arm-eng``aosp_arm64-eng`的选项,这两个是模拟器使用的版本。而模拟器使用的版本是可以不需要导入设备驱动文件的。如果在`lunch`的菜单中没有看到你要编译的版本,并且直接`lunch aosp_blueline-userdebug `也提示错误,可能是没有成功导入驱动文件,或者下载的驱动文件不对。
@ -289,7 +291,7 @@ make -j$(nproc --all)
第一次完整编译非常的漫长我的电脑耗时2个小时成功编译。编译成功后我们检查一下输出的文件。 第一次完整编译非常的漫长我的电脑耗时2个小时成功编译。编译成功后我们检查一下输出的文件。
~~~ ```
// 查看输出目录的所有镜像文件 // 查看输出目录的所有镜像文件
ls /root/android_src/aosp12_out/target/product/blueline | grep img ls /root/android_src/aosp12_out/target/product/blueline | grep img
@ -313,7 +315,7 @@ system_other.img
userdata.img userdata.img
vbmeta.img vbmeta.img
vendor.img vendor.img
~~~ ```
确定有编译出`vendor.img、system.img、boot.img`等等镜像文件,就说明编译成功了。 确定有编译出`vendor.img、system.img、boot.img`等等镜像文件,就说明编译成功了。
@ -321,7 +323,7 @@ vendor.img
前文在编译的过程中介绍到,我们使用`source ./build/envsetup.sh`初始化环境的时候,导入了多个命令来帮助我们进行编译。我们可以通过命令`hmm`查看提供的命令帮助。 前文在编译的过程中介绍到,我们使用`source ./build/envsetup.sh`初始化环境的时候,导入了多个命令来帮助我们进行编译。我们可以通过命令`hmm`查看提供的命令帮助。
~~~ ```
hmm hmm
Run "m help" for help with the build system itself. Run "m help" for help with the build system itself.
@ -344,7 +346,7 @@ Invoke ". build/envsetup.sh" from your shell to add the following functions to y
To limit the modules being built use the syntax: mmm To limit the modules being built use the syntax: mmm
// 省略 // 省略
...... ......
~~~ ```
`croot` 命令可以跳转根目录,或者是根目录下的任意子目录 `croot` 命令可以跳转根目录,或者是根目录下的任意子目录
@ -358,7 +360,7 @@ Invoke ". build/envsetup.sh" from your shell to add the following functions to y
我们可以通过`m help`查看可以单独编译哪些选项 我们可以通过`m help`查看可以单独编译哪些选项
~~~ ```
m help m help
Common goals are: Common goals are:
@ -392,7 +394,7 @@ Common goals are:
Stands for "VendorDlkm, NO Dependencies" Stands for "VendorDlkm, NO Dependencies"
odnod Quickly rebuild the odm_dlkm image from built packages odnod Quickly rebuild the odm_dlkm image from built packages
Stands for "OdmDlkm, NO Dependencies" Stands for "OdmDlkm, NO Dependencies"
~~~ ```
通过帮助命令的提示,我们可以看到`m snod`就是单独编译`System`,命令`m vnod`就是单独编译`Vendor`。大多数时候我们修改的内容都是在`System`中。我们可以根据自己的变动情况,模块编译即可。 通过帮助命令的提示,我们可以看到`m snod`就是单独编译`System`,命令`m vnod`就是单独编译`Vendor`。大多数时候我们修改的内容都是在`System`中。我们可以根据自己的变动情况,模块编译即可。
@ -406,7 +408,7 @@ Common goals are:
接下来我们按照官网的说明拉取代码并编译。 接下来我们按照官网的说明拉取代码并编译。
~~~ ```
// 内核编译的相关依赖安装 // 内核编译的相关依赖安装
sudo apt install p7zip-full wget curl git tree -y sudo apt install p7zip-full wget curl git tree -y
sudo apt-get install dialog file python3 python3-pip python2 libelf-dev gpg gpg-agent tree flex bison libssl-dev zip unzip curl wget tree build-essential bc software-properties-common libstdc++6 libpulse0 libglu1-mesa locales lcov --no-install-recommends -y sudo apt-get install dialog file python3 python3-pip python2 libelf-dev gpg gpg-agent tree flex bison libssl-dev zip unzip curl wget tree build-essential bc software-properties-common libstdc++6 libpulse0 libglu1-mesa locales lcov --no-install-recommends -y
@ -426,11 +428,11 @@ build/build.sh
// 编译完成后查看编译结果最后输出显示Image.lz4文件就表示内核编译是成功的。 // 编译完成后查看编译结果最后输出显示Image.lz4文件就表示内核编译是成功的。
ls /root/android_src/android-kernel/out/android-msm-pixel-4.9/dist |grep Image ls /root/android_src/android-kernel/out/android-msm-pixel-4.9/dist |grep Image
~~~ ```
编译成功后我们还需要指定Android源码编译时使用这个内核文件。只需要设置环境变量指定路径即可。方式如下。 编译成功后我们还需要指定Android源码编译时使用这个内核文件。只需要设置环境变量指定路径即可。方式如下。
~~~ ```
// 为了以后方便,环境路径相关的,我们都写在这个初始化导入环境命令的地方 // 为了以后方便,环境路径相关的,我们都写在这个初始化导入环境命令的地方
vim ./build/envsetup.sh vim ./build/envsetup.sh
@ -445,7 +447,7 @@ lunch aosp_blueline-userdebug
// 单独编译内核镜像 // 单独编译内核镜像
make bootimage make bootimage
~~~ ```
### 2.6 刷机 ### 2.6 刷机
@ -457,7 +459,7 @@ make bootimage
首先我们要进入刷机模式,然后环境变量设置编译结果的路径,然后使用命令完整刷机即可。详细流程如下 首先我们要进入刷机模式,然后环境变量设置编译结果的路径,然后使用命令完整刷机即可。详细流程如下
~~~ ```
// 进入刷机模式 // 进入刷机模式
adb reboot bootloader adb reboot bootloader
@ -472,11 +474,11 @@ fastboot devices
// 完整刷机 // 完整刷机
fastboot flashall -w fastboot flashall -w
~~~ ```
等待刷机结束即可刷机结束后会自动进入Android系统。如果我们只想刷单个分区镜像也是可以的。流程如下 等待刷机结束即可刷机结束后会自动进入Android系统。如果我们只想刷单个分区镜像也是可以的。流程如下
~~~ ```
// 进入刷机模式 // 进入刷机模式
adb reboot bootloader adb reboot bootloader
@ -510,30 +512,30 @@ fastboot flash vendor ./vendor.img
// 重启 // 重启
fastboot reboot fastboot reboot
~~~ ```
### 2.6.2 卡刷 ### 2.6.2 卡刷
我们前面编译出来的是线刷包,如果我们需要卡刷包,就需要使用下面的方式进行编译 我们前面编译出来的是线刷包,如果我们需要卡刷包,就需要使用下面的方式进行编译
~~~ ```
// 下面是简单的编译卡刷包 // 下面是简单的编译卡刷包
cd aosp12 cd aosp12
source ./build/envsetup.sh source ./build/envsetup.sh
lunch aosp_blueline-userdebug lunch aosp_blueline-userdebug
make otapackage make otapackage
~~~ ```
编译完成后,我们可以在前面线刷包的路径下看到卡刷包文件,我这里的文件名是`aosp_blueline-ota-eng.king.zip`。除了上面的方式,我们还可以完整编译卡刷包,编译方式如下 编译完成后,我们可以在前面线刷包的路径下看到卡刷包文件,我这里的文件名是`aosp_blueline-ota-eng.king.zip`。除了上面的方式,我们还可以完整编译卡刷包,编译方式如下
~~~ ```
//下面是完整编译卡刷包 //下面是完整编译卡刷包
cd aosp12 cd aosp12
source ./build/envsetup.sh source ./build/envsetup.sh
lunch aosp_blueline-userdebug lunch aosp_blueline-userdebug
mkdir dist_output mkdir dist_output
make dist DIST_DIR=dist_output make dist DIST_DIR=dist_output
~~~ ```
编译完成后,可以在目录`dist_output`中看到完整卡刷包结果。 编译完成后,可以在目录`dist_output`中看到完整卡刷包结果。
@ -543,10 +545,10 @@ make dist DIST_DIR=dist_output
首先进入fastbootd 首先进入fastbootd
~~~ ```
adb reboot bootloader adb reboot bootloader
fastboot reboot fastboot fastboot reboot fastboot
~~~ ```
这时的界面如下图,使用音量键减,切换到`Enter recovery`,然后按电源键进入`recovery`模式 这时的界面如下图,使用音量键减,切换到`Enter recovery`,然后按电源键进入`recovery`模式
@ -564,7 +566,7 @@ fastboot reboot fastboot
Android系统是一个非常庞大的项目所以我们需要采用合适的编辑器或者是`ide`来修改代码,如果你的改动不多,那么我们简单的使用`VsCode`导入工作区即可开始修改代码。但是`VsCode`的智能提示和跳转较为简陋,所以如果想要更加友好的开发体验,我们可以选择将源码导入`Android Studio`中编辑java部分代码导入`Clion`中编辑`native`部分代码。下面简单介绍如何将源码导入Android Studio。 Android系统是一个非常庞大的项目所以我们需要采用合适的编辑器或者是`ide`来修改代码,如果你的改动不多,那么我们简单的使用`VsCode`导入工作区即可开始修改代码。但是`VsCode`的智能提示和跳转较为简陋,所以如果想要更加友好的开发体验,我们可以选择将源码导入`Android Studio`中编辑java部分代码导入`Clion`中编辑`native`部分代码。下面简单介绍如何将源码导入Android Studio。
~~~ ```
cd ~/aosp12 cd ~/aosp12
source build/envsetup.sh source build/envsetup.sh
lunch aosp_blueline-userdebug lunch aosp_blueline-userdebug
@ -602,11 +604,11 @@ vim ./android.iml
<excludeFolder url="file://$MODULE_DIR$/system"/> <excludeFolder url="file://$MODULE_DIR$/system"/>
<excludeFolder url="file://$MODULE_DIR$/tools"/> <excludeFolder url="file://$MODULE_DIR$/tools"/>
<excludeFolder url="file://$MODULE_DIR$/kernel"/> <excludeFolder url="file://$MODULE_DIR$/kernel"/>
~~~ ```
修改好配置后最后使用Android studio打开`android.ipr`文件即可。接下来简单介绍将代码导入Clion。 修改好配置后最后使用Android studio打开`android.ipr`文件即可。接下来简单介绍将代码导入Clion。
~~~ ```
// 设置环境变量,在编译时生成CMakeLists.txt文件 // 设置环境变量,在编译时生成CMakeLists.txt文件
export SOONG_GEN_CMAKEFILES=1 export SOONG_GEN_CMAKEFILES=1
export SOONG_GEN_CMAKEFILES_DEBUG=1 export SOONG_GEN_CMAKEFILES_DEBUG=1
@ -661,7 +663,7 @@ add_subdirectory(system/core/logd/logd-arm64-android)
add_subdirectory(system/core/logd/liblogd-arm64-android) add_subdirectory(system/core/logd/liblogd-arm64-android)
add_subdirectory(system/core/lmkd/liblmkd_utils-arm64-android) add_subdirectory(system/core/lmkd/liblmkd_utils-arm64-android)
add_subdirectory(system/core/lmkd/lmkd-arm64-android) add_subdirectory(system/core/lmkd/lmkd-arm64-android)
~~~ ```
配置好cmake文件后使用clion打开项目选择刚刚配置好的`CMakeLists.txt`文件的目录`out/development/ide/clion/`。导入成功后,我们需要修改工程的根目录,`Tools->Cmake->Change Project Root`,然后选择源码根目录即可。 配置好cmake文件后使用clion打开项目选择刚刚配置好的`CMakeLists.txt`文件的目录`out/development/ide/clion/`。导入成功后,我们需要修改工程的根目录,`Tools->Cmake->Change Project Root`,然后选择源码根目录即可。
@ -671,7 +673,7 @@ add_subdirectory(system/core/lmkd/lmkd-arm64-android)
首先我们需要对repo进行一定的了解在前文中有简单的介绍到repo是python脚本实现的是对git命令的封装用来管理大型项目关联多个子项目的。现在我们重新回顾一下下载android代码的过程。前文中我们使用repo进行初始化指定分支在完成初始化后会在当前目录生成一个.repo的目录首先我们查看目录中的manifest.xml文件内容如下。 首先我们需要对repo进行一定的了解在前文中有简单的介绍到repo是python脚本实现的是对git命令的封装用来管理大型项目关联多个子项目的。现在我们重新回顾一下下载android代码的过程。前文中我们使用repo进行初始化指定分支在完成初始化后会在当前目录生成一个.repo的目录首先我们查看目录中的manifest.xml文件内容如下。
~~~ ```
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
DO NOT EDIT THIS FILE! It is generated by repo and changes will be discarded. DO NOT EDIT THIS FILE! It is generated by repo and changes will be discarded.
@ -686,11 +688,11 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
<manifest> <manifest>
<include name="default.xml" /> <include name="default.xml" />
</manifest> </manifest>
~~~ ```
可以看到只是导入了default.xml文件。接着我们查看这个配置文件。 可以看到只是导入了default.xml文件。接着我们查看这个配置文件。
~~~ ```
<manifest> <manifest>
<remote name="aosp" <remote name="aosp"
fetch=".." fetch=".."
@ -726,7 +728,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
<project path="bionic" name="platform/bionic" groups="pdk" /> <project path="bionic" name="platform/bionic" groups="pdk" />
..... .....
</manifest> </manifest>
~~~ ```
可以看到这个文件实际上是一份git仓库清单`repo init`初始化的过程就是下载git仓库清单文件以及下载repo工具的仓库也就是git-repo项目使用国内网络进行初始化时的速度非常慢的主要原因就在于git-repo项目较大且必须通过外网访问所以很多人使用国内源进行`repo init`前还需要通过设置环境变量`REPO_URL`修改git-repo的拉取地址。而`repo sync`步骤就是就是将清单文件中对应的子模块全部拉取下来。而default.xml中的元素主要为以下几种。 可以看到这个文件实际上是一份git仓库清单`repo init`初始化的过程就是下载git仓库清单文件以及下载repo工具的仓库也就是git-repo项目使用国内网络进行初始化时的速度非常慢的主要原因就在于git-repo项目较大且必须通过外网访问所以很多人使用国内源进行`repo init`前还需要通过设置环境变量`REPO_URL`修改git-repo的拉取地址。而`repo sync`步骤就是就是将清单文件中对应的子模块全部拉取下来。而default.xml中的元素主要为以下几种。
@ -750,7 +752,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
清楚了使用repo同步代码的原理以及git清单中元素的作用后我们就可以开始搭建自己的Android源码远程仓库了。由于项目较大所以我们可以在本地搭建一个gitlab服务然后将项目上传至gitlab中进行管理如下是搭建gitlab服务的步骤。 清楚了使用repo同步代码的原理以及git清单中元素的作用后我们就可以开始搭建自己的Android源码远程仓库了。由于项目较大所以我们可以在本地搭建一个gitlab服务然后将项目上传至gitlab中进行管理如下是搭建gitlab服务的步骤。
~~~ ```
// 安装gitlab服务的依赖 // 安装gitlab服务的依赖
sudo apt-get update sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates sudo apt-get install -y curl openssh-server ca-certificates
@ -774,17 +776,17 @@ sudo gitlab-ctl reconfigure
// 启动gitlab // 启动gitlab
sudo gitlab-ctl start sudo gitlab-ctl start
~~~ ```
接下来直接在浏览器中输入局域网ip来访问gitlab页面比如我的是`http://192.168.2.189/`。然后注册一个账号。在登录的时候出现了下面这个错误 接下来直接在浏览器中输入局域网ip来访问gitlab页面比如我的是`http://192.168.2.189/`。然后注册一个账号。在登录的时候出现了下面这个错误
~~~ ```
Your account has been blocked. Please contact your GitLab administrator if you think this is an error. Your account has been blocked. Please contact your GitLab administrator if you think this is an error.
~~~ ```
这是因为注册的账号需要审批激活后才能使用。我们回到终端上通过下面的命令激活账号 这是因为注册的账号需要审批激活后才能使用。我们回到终端上通过下面的命令激活账号
~~~ ```
// 进入gitlab的控制台 // 进入gitlab的控制台
gitlab-rails console gitlab-rails console
@ -797,7 +799,7 @@ user.state = "active"
// 保存修改并退出 // 保存修改并退出
user.save user.save
exit exit
~~~ ```
到这里gitlab服务准备就绪登录账号后就可以创建aosp的子模块仓库了。 到这里gitlab服务准备就绪登录账号后就可以创建aosp的子模块仓库了。
@ -819,16 +821,16 @@ exit
然后就可以使用curl命令通过token访问gitlab的api创建一个空白的仓库 然后就可以使用curl命令通过token访问gitlab的api创建一个空白的仓库
~~~ ```
// 创建一个名称为manifests的空白仓库namespace_id是根目录的分组id // 创建一个名称为manifests的空白仓库namespace_id是根目录的分组id
curl --header "PRIVATE-TOKEN: 27zctxyWZP9Txksenkxb" \ curl --header "PRIVATE-TOKEN: 27zctxyWZP9Txksenkxb" \
--data "name=manifest&namespace_id=6" \ --data "name=manifest&namespace_id=6" \
--request POST "http://192.168.2.189/api/v4/projects" --request POST "http://192.168.2.189/api/v4/projects"
~~~ ```
接下来修改配置并且将清单项目上传到gitlab中 接下来修改配置并且将清单项目上传到gitlab中
~~~ ```
// 创建项目目录 // 创建项目目录
mkdir manifest && cd manifest mkdir manifest && cd manifest
@ -860,11 +862,11 @@ git init
git remote add origin git@192.168.2.189:android12_r3/manifest.git git remote add origin git@192.168.2.189:android12_r3/manifest.git
git add . && git commit -m "init" git add . && git commit -m "init"
git push git push
~~~ ```
准备好清单文件后接下来就需要准备所有子模块仓库了。首先我们得知道一共有哪些子模块需要上传而这个通过default.xml中的project元素很容易得到。我们可以编写一个python脚本来匹配出所有project中的path属性然后创建group和仓库。下面贴上一份网上找到读取default.xml自动创建所有仓库。 准备好清单文件后接下来就需要准备所有子模块仓库了。首先我们得知道一共有哪些子模块需要上传而这个通过default.xml中的project元素很容易得到。我们可以编写一个python脚本来匹配出所有project中的path属性然后创建group和仓库。下面贴上一份网上找到读取default.xml自动创建所有仓库。
~~~python ```python
#!/usr/bin/python3 #!/usr/bin/python3
import gitlab import gitlab
@ -990,11 +992,11 @@ if __name__ == '__main__':
create_group_and_project() create_group_and_project()
# test_create_project_with_dot_name() # test_create_project_with_dot_name()
~~~ ```
子模块仓库建立完成最后我们还需要将代码上传到对应的仓库中。同样参考网上找的上传代码修改一部分细节这里一定要注意default.xml中project元素的属性path的是本地路径而name才是指的git仓库的路径代码如下 子模块仓库建立完成最后我们还需要将代码上传到对应的仓库中。同样参考网上找的上传代码修改一部分细节这里一定要注意default.xml中project元素的属性path的是本地路径而name才是指的git仓库的路径代码如下
~~~python ```python
#!/usr/bin/python3 #!/usr/bin/python3
import os import os
@ -1099,11 +1101,11 @@ if __name__ == '__main__':
parse_repo_manifest() parse_repo_manifest()
wrapper_push_source_code_write_log() wrapper_push_source_code_write_log()
~~~ ```
上传过程较慢等待所有仓库上传完成最后将git-repo工具子模块上传到我们的仓库。首先在gitlab中创建一个分组android-tools。然后在分组中手动创建一个仓库git-repo。然后从github下载一份git-repo的工具源码传到我们的gitlab。过程如下。 上传过程较慢等待所有仓库上传完成最后将git-repo工具子模块上传到我们的仓库。首先在gitlab中创建一个分组android-tools。然后在分组中手动创建一个仓库git-repo。然后从github下载一份git-repo的工具源码传到我们的gitlab。过程如下。
~~~ ```
// 从github下载git-repo源码并上传到gitlab仓库 // 从github下载git-repo源码并上传到gitlab仓库
git clone https://github.com/GerritCodeReview/git-repo.git && cd git-repo git clone https://github.com/GerritCodeReview/git-repo.git && cd git-repo
rm .git -rf rm .git -rf
@ -1116,11 +1118,11 @@ git push -u origin master
// 将这里的repo拿来使用 // 将这里的repo拿来使用
cp ./repo ~/bin/ cp ./repo ~/bin/
PATH=~/bin:$PATH PATH=~/bin:$PATH
~~~ ```
终于一切准备就绪,那么开始拉取我们自己的代码吧。 终于一切准备就绪,那么开始拉取我们自己的代码吧。
~~~ ```
// 创建存放源码的目录 // 创建存放源码的目录
mkdir myandroid12 && cd myandroid12 mkdir myandroid12 && cd myandroid12
@ -1139,11 +1141,11 @@ repo init -u git@192.168.2.189:android12_r3/manifest.git --repo-url=git@192.168.
//同步代码 //同步代码
repo sync -j8 repo sync -j8
~~~ ```
在同步的过程中,出现了两个问题。首先第一个是出现如下错误 在同步的过程中,出现了两个问题。首先第一个是出现如下错误
~~~ ```
remote: remote:
remote: ======================================================================== remote: ========================================================================
remote: remote:
@ -1156,11 +1158,11 @@ fatal: 无法读取远程仓库。
请确认您有正确的访问权限并且仓库存在。 请确认您有正确的访问权限并且仓库存在。
platform/build/bazel: platform/build/bazel:
~~~ ```
检测代码后发现bazel仓库在路径build中不存在这个仓库被建立在了platform下。导致这个问题的原因是由于前面的创建git的脚本中发现build被指定为project所以创建为仓库而bazel必须是在一个group下路径才会成立。而build的仓库已经存在创建这个group失败后就默认使用了更上一层的group。而解决办法也非常简单直接将default中的几个build路径下的几个project重新命名不要放在build的group下即可。下面是解决后的default.xml配置。 检测代码后发现bazel仓库在路径build中不存在这个仓库被建立在了platform下。导致这个问题的原因是由于前面的创建git的脚本中发现build被指定为project所以创建为仓库而bazel必须是在一个group下路径才会成立。而build的仓库已经存在创建这个group失败后就默认使用了更上一层的group。而解决办法也非常简单直接将default中的几个build路径下的几个project重新命名不要放在build的group下即可。下面是解决后的default.xml配置。
~~~ ```
<project path="build/make" name="platform/build" groups="pdk" > <project path="build/make" name="platform/build" groups="pdk" >
<copyfile src="core/root.mk" dest="Makefile" /> <copyfile src="core/root.mk" dest="Makefile" />
<linkfile src="CleanSpec.mk" dest="build/CleanSpec.mk" /> <linkfile src="CleanSpec.mk" dest="build/CleanSpec.mk" />
@ -1181,26 +1183,26 @@ platform/build/bazel:
<linkfile src="root.bp" dest="Android.bp" /> <linkfile src="root.bp" dest="Android.bp" />
<linkfile src="bootstrap.bash" dest="bootstrap.bash" /> <linkfile src="bootstrap.bash" dest="bootstrap.bash" />
</project> </project>
~~~ ```
另外一个问题也非常类似。错误如下。 另外一个问题也非常类似。错误如下。
~~~ ```
请确认您有正确的访问权限并且仓库存在。 请确认您有正确的访问权限并且仓库存在。
device/mediatek/wembley-sepolicy: sleeping 4.0 seconds before retrying device/mediatek/wembley-sepolicy: sleeping 4.0 seconds before retrying
~~~ ```
经过检查后发现这是由于这个仓库在default.xml中的配置如下 经过检查后发现这是由于这个仓库在default.xml中的配置如下
~~~ ```
<project name="device/mediatek/wembley-sepolicy" path="device/mediatek/wembley-sepolicy" groups="device"/> <project name="device/mediatek/wembley-sepolicy" path="device/mediatek/wembley-sepolicy" groups="device"/>
~~~ ```
然后看了创建仓库和批量提交代码的逻辑就明白了是的name和path的顺序反了导致正则表达式未能成功匹配到这个仓库所以我们调整一下name和path的顺序即可。 然后看了创建仓库和批量提交代码的逻辑就明白了是的name和path的顺序反了导致正则表达式未能成功匹配到这个仓库所以我们调整一下name和path的顺序即可。
成功拉取完成后,如果在编译时碰到找不到文件的问题,这是由于有些子模块仓库下的子目录中有`.gitignore`文件将一些应该提交的文件给过滤掉了。就回到我们同步代码的目录中找到指定的git仓库使用下面的方式重新提交一下。然后回到我们同步下来的代码处重新拉取更新的代码。 成功拉取完成后,如果在编译时碰到找不到文件的问题,这是由于有些子模块仓库下的子目录中有`.gitignore`文件将一些应该提交的文件给过滤掉了。就回到我们同步代码的目录中找到指定的git仓库使用下面的方式重新提交一下。然后回到我们同步下来的代码处重新拉取更新的代码。
~~~ ```
// 进入缺少文件的子模块仓库目录 // 进入缺少文件的子模块仓库目录
cd ~/external/angle/ cd ~/external/angle/
git add . -f git add . -f
@ -1208,7 +1210,7 @@ git commit -m "init"
git push -u origin master git push -u origin master
cd ~/android_src/myandroid12/ cd ~/android_src/myandroid12/
repo sync -j8 repo sync -j8
~~~ ```
到这里就完成了gitlab源码管理android源码开发了。最后如何使用git提交和查看历史记录我就不在这里叙述了。 到这里就完成了gitlab源码管理android源码开发了。最后如何使用git提交和查看历史记录我就不在这里叙述了。