computer_knowledge_notes/OS/Openthos/编译过程.md

227 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### source build/envsetup.sh
本文件的作用是初始化编译环境,并引入一些辅助命令。
- 定义hmm, 加载编译时使用的命令。
- 定义 printconfig, 显示当前构建的配置信息。
- 定义 add_lunch_combo, 用来给lunch命令添加编译选项。
本函数的处理过程是遍历数组LUNCH_MENU_CHOICES判断要添加的编译选项是否在数组里如在数组里则直接返回如不在数组里则将其添加到数组里。
- 添加了6条默认的选项aosp_*。
- 定义print_lunch_menu用于列出所有的编译选项。
- 定义lunch用于让用户指定编译选项。
- 定义_lunch用于为lunch命令提供参数自动补齐的功能。
- 这是一条complete命令指定由_lunch实现lunch命令里参数自动补齐的功能。
- 659~668, m, 在源码树的根目录执行make
- 687~723, mm, 构建当前目录下的模块
- 725770 mmm, 构建指定目录下的模块
- 823831croot切换到源码树的根的目录
- 1329~1332, jgrep, 在所有java文件上执行grep
- 1334~1337, cgrep, 在所有c/c++文件上执行grep
- 1339~1342, resgrep, 在所有res/*.xml文件上执行grep
- 1590~1632, godir, 转到包含某个文件的目录路径
- 在文件的末尾查找vendorsetup.sh脚本并加载它。openthos的编译选项就是在这里被加载的。
### lunch
lunch命令定义在build/envsetup.sh里用来让用户选择编译设备与编译类型。其执行步骤如下
1. 定义变量answer(用以代表用户的选择),如果命令里给了参数则直接使用给定的参数,否则列出所有的编译选项让用户选项。
2. 定义变量selection(用以代表变量answer所对应的字符串)如果用户没选择则使用默认选项aosp_arm-eng如果用户输入的是数字则使用该数字对应的字符串如果用户输入的是字符串则直接使用该字符串。
3. 定义变量product将selection里"-"的前面部分放在变量product里如编译openthos则其值为"openthos"。
4. 定义变量variant将selection里两个"-"之间的部分放在变量variant里如编译openthos则其值为"x86_64"。
5. 定义变量version将seleciton里"-"之后的部分放在version里如编译openthos则其值可能是"user"、"userdebug"或"eng"。eng适用于开发阶段userdebug适用于调试阶段user适用于最终发布阶段。
6. 定义如下3个环境变量
```
export TARGET_PRODUCT=$product
export TARGET_BUILD_VARIANT=$variant
export TARGET_BUILD_TYPE=release
```
7. set_stuff_for_environment函数设置一些环境变量。
8. printconfig函数打印一些主要的变量。
### make
- make命令定义在build/envsetup.sh里。
```
function make()
{
_wrap_build $(get_make_command) "$@"
}
```
- 依据`get_make_command`函数的定义,$(get_make_command)的值是"build/soong/soong_ui.bash --make-mode"。
- 在`_wrap_build`函数可见,第二行"$@"已经执行完所有的编译过程了,其它部分只不过是输出一些统计信息而已。
- build/soonn/soong_ui.bash。首先执行build/soong/cmd/microfactory/microfactory.bash定义了两个工具函数`getoutdir`用来查找out目录`build_go`用来编译所需的二进制(参数1是所要编译的二进制的名字参数2是包名)然后用build_go来编译soong_ui最后执行的是`out/soong_ui $@`完成构建的过程。
- 函数build_go的执行逻辑如果$mf_bin存在且$mf_version的值等于$mf_version_file里保存的值说明$mf_bin存在且是最新的此时它就是$mf_cmd否则说明$mf_bin不存在或它的版本不是最新的这时就需要构建新的$mf_cmd它的值为`go run $mf_src/microfactory.go`。`$mf_cmd ...`那行是真正干活的,-s用来指示microfactory的源码目录-b用来指示microfactory二进制的位置-pkg-path是从包前缀到文件路径的映射-trimpath用于从记录的源文件路径中删除前缀-o用于指定输出文件的名称。
#### 构建的过程
构建的起点在`build/core/main.mk`,可以看到整个文件的结构如下:
```
ifndef KATI
...
else # KATI
...
endif # KATI
```
由于没有定义KATI所以走的是ifndef流程。MAKECMDGOALS是make执行时后面的参数这意味着不管执行什么目标最终都执行的都是run_soong_ui这个目标。这样编译的控制权就交到了soong手上后面的事就跟make没有关系了。
soong_ui代码在`build/soong/cmd/soong_ui/main.go`真正干活的是main函数里的最后一句
```
build.Build(buildCtx, config, build.BuildAll)
```
build.Build在`ui/build/build.go`从中可以看到执行soong的流程
1. `runMakeProductConfig`在ui/build/make.go用来配置编译参数。在这里可以看到[第一段输出](# 第一段输出)
2. `runSoongBootstrap`和`runSoong`在ui/build/soong.go分别运行的是`./bootstrap.bash`和`soong`两个命令。在这里可以看到[第二段输出](# 第二段输出)和[第三段输出](# 第三段输出)
`./bootstrap.bash`的最后一句会执行`build/blueprint/bootstrap.bash $@`如不带参数则生成minibp如带参数则生成一个基于Blueprint的构建系统。
3. `runKati`在ui/build/kati.go运行的是ckati命令。把所有的Android.mk文件生成ninja文件。
4. `createCombinedBuildNinjaFile`在ui/build/build.go在out/combined-openthos_x86_64.ninja文件里用include关键字把前两步生成的ninja文件包含进来。
5. `runNinja`在ui/build/ninja.go运行ninja命令执行构建过程所使用的配置文件就是第四步生成的combined-openthos_x86_64.ninja。在这里看到[第四段输出](# 第四段输出)
#### 第一段输出
输出的是关于编译环境的若干变量。
#### 第二段输出
在`build/soong/build.ninja.in`,编译生成`out/soong/.bootstrap`下的文件。源文件在build/blueprint。
#### 第三段输出
搜集所有的`Android.bp`文件生成build.ninja。
#### 第四段输出
详细的编译过程
##### 第四段之生成oto_img
在bootable/newinstaller/Android.mk
```
# 1. 从175行可见OTO_IMAGE即oto_img
oto_img: $(OTO_IMAGE)
# 2. OTO_IMAGE详见143~158行
# OTO_IMAGE: openthos_x86_64_oto.img
# OTO_INITRD_RAMDISK:oto_initrd.img
# OTO_BILT_IMG: ramdisk.img install.img system.sfs kernel
# DATA_IMG: data.img
143$LOCAL_PaTH是/bootable/newinstaller
144:把$LOCAL_PATH/install/refind/efi目录压缩为$REFIND。$PRODUCT是out/target/product/openthos/$REFIND是$PRODUCT/efi.tar.bz2
145:把$PRODUCT_OUT/oto_initrd.img复制到$PRODUCT_OUT/initrd.img。$PRODUCT_OUT是out/target/product/openthos/
146~149:统计依赖文件的大小
150:把$REFIND的大小加到size上且再增加8k大小
151:把size调大了一点。size=size+62+(size/100)
152:创建($OTO_IMAGE).fat即openthos_x86_64_oto.img.fat然后用mkdosfs命令为其创建文件系统大小为size。
153:把$LOCAL_PATH/install/refind/efi目录复制到openthos_x86_64_oto.img.fat镜像的顶层目录
154:在openthos_x86_64_oto.img.fat里创建OpenThos目录
155:把$LOCAL_PATH/install/refind/boto_linux.conf里的"BOOT_MODE="替换为$BOARD_KERNEL_CMDLINE将输出重定向到out/target/product/openthos/boto_linux.conf
156:把$PRODUcT_OUT目录下的ramdisk.img install.img system.sfs initrd.img kernel efi.tar.bz2 boto_linux.conf复制到镜像openthos_x86_64_oto.img.fat的OpenThos目录下
157:创建openthos_x86_64_oto.img然后使用edit_mbr命令以bootable/newinstaller/editdisklbl/esp_layout.conf为layout配置文件以openthos_x86_64_oto.img为要编辑的镜像,以openthos_x86_64_oto.img.fat为配置文件里的esp创建启动镜像
158:删除openthos_x86_64_oto.img.fat和initrd.img
# 3. oto_initrd.img的生成详见76~83行
# 4. install.img的生成详见86~91行
```
ramdisk.img是在build/core/Makefile里生成的
```
580~596行
```
system.sfs
kernel是对源码目录kernel的编译编译规则可能在build/core/Makefile或kernel/Makefile。
### 对镜像的分析
#### 挂载openthos_x86_64.img
```
sudo mount -o loop,offset=1048576 openthos_x86_64.img /mnt
# offset是使用fdisk -l命令计算出来的起始扇区*每个扇区的大小
```
#### 解析initrd.img
通过对比可见initrd.img的内容来自于out/target/product/openthos/installer
```
file initrd.img # 发现它是gzip格式
cp initrd.img ~/initrd.img.gz && cd ~
gunzip initrd.img.gz # 生成initrd.img
file initrd.img # 发现它是cpio格式
mkdir initrd && cd initrd
cpio -i -F ../initrd.img # 把initrd.img的内容复制到initrd目录
```
#### 解析install.img
解压方法同initrd.img通过对比可见其内容主要来自bootable/newinstaller/install
#### 解析ramdisk.img
解压方法同initrd.img通过对比可见其内容主要来自out/target/product/openthos/root
#### 解析system.sfs
解压出system.img然后挂载。通过对比可见其内容主要来自out/target/product/openthos/system
```
unsquashfs system.sfs
```
### 编译错误记录
> DEPMOD 4.9.109-android-x86_64-01316-g45b3cc90-dirty
>
> /root/szx/kernel/Makefile:1350: recipe for target '_modinst_post' failed
> make[1]: *** [_modinst_post] Error 255
> make[1]: Leaving directory '/root/szx/out/target/product/openthos/obj/kernel'
> Makefile:152: recipe for target 'sub-make' failed
> make: *** [sub-make] Error 2
> make: Leaving directory '/root/szx/kernel'
> [ 99% 99776/99781] build out/target/product/openthos/install.img
> ninja: build stopped: subcommand failed.
> 02:44:29 ninja failed with: exit status 1
问题分析我的情况是少了kmod把它安装上即可。`sudo apt install kmod`。另,还应检查`syslinux genisoimage gettext bc dosfstools mtools kmod`是否都安装齐全。另:从这里是看不出来问题在哪的,要从往前翻,找到真正错误的地方。
### 参考资料
[理解安卓build系统](https://www.ibm.com/developerworks/cn/opensource/os-cn-android-build/)
[Android.bp及其工具链](http://note.qidong.name/2017/08/android-blueprint/)
[Android Soong build系统介绍](https://www.jianshu.com/p/80013a768a45)