本篇关键词:、、、
下载 >> 离线文档.鸿蒙内核源码分析(百篇博客分析.挖透鸿蒙内核).pdf
编译运行相关篇为:
- v84.02 鸿蒙内核源码分析(编译过程) | 简单案例说透中间过程
- v85.03 鸿蒙内核源码分析(编译构建) | 编译鸿蒙防掉坑指南
- v86.04 鸿蒙内核源码分析(GN语法) | 如何构建鸿蒙系统
- v87.03 鸿蒙内核源码分析(忍者无敌) | 忍者的特点就是一个字
- v88.04 鸿蒙内核源码分析(ELF格式) | 应用程序入口并非main
- v89.03 鸿蒙内核源码分析(ELF解析) | 敢忘了她姐俩你就不是银
- v90.04 鸿蒙内核源码分析(静态链接) | 一个小项目看中间过程
- v91.04 鸿蒙内核源码分析(重定位) | 与国际接轨的对外发言人
- v92.01 鸿蒙内核源码分析(动态链接) | 正在制作中 ...
- v93.05 鸿蒙内核源码分析(进程映像) | 程序是如何被加载运行的
- v94.01 鸿蒙内核源码分析(应用启动) | 正在制作中 ...
- v95.06 鸿蒙内核源码分析(系统调用) | 开发者永远的口头禅
- v96.01 鸿蒙内核源码分析(VDSO) | 正在制作中 ...
构建的必要性
- 前端开发有构建工具:
Grunt
、Gulp
、Webpack
- 后台开发有构建工具:
Maven
、Ant
、Gradle
构建工具重要性不言而喻,它描述了整个工程的如何编译、连接,打包等规则,其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建那些库文件以及如何创建这些库文件、如何最后输出我们想要的文件。
鸿蒙轻内核(L1/liteos)的编译构建工具是hb
,hb
是ohos-build
的简称, 而ohos
又是openharmony os
的简称。
hb | ohos-build
hb通过以下命令安装,是用 python写的一个构建工具。
python3 -m pip install --user ohos-build
其源码在 ./build/lite 目录下,含义如下:
build/lite
├── components # 组件描述文件
├── figures # readme中的图片
├── hb # hb pip安装包源码
│ ├── build # hb build 命令实现
│ ├── clean # hb clean 命令实现
│ ├── common # 通用类, 提供 Device,Config,Product,utils 类
│ ├── cts # hb cts 命令实现
│ ├── deps # hb deps 命令实现
│ ├── env # hb env 命令实现
│ ├── set # hb set 命令实现
├── make_rootfs # 文件系统镜像制作脚本
├── config # 编译配置项
│ ├── component # 组件相关的模板定义
│ ├── kernel # 内核相关的编译配置
│ └── subsystem # 子系统编译配置
├── platform # ld脚本
├── testfwk # 测试编译框架
└── toolchain # 编译工具链配置,包括:编译器路径、编译选项、链接选项等
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
构建组成
鸿蒙构建系统由 python
, gn
, ninja
, makefile
几个部分组成,每个部分都有自己的使命,干自己最擅长的活。
python : 胶水语言,最擅长的是对参数,环境变量,文件操作,它任务是做好编译前的准备工作和为gn收集命令参数。不用python直接用gn行不行? 也行,但很麻烦。比如:直接使用下面的命令行也可以生成 .ninja文件,最后的效果是一样的。但相比只使用
hb build
哪个更香,hb build
也会生成下面这一坨坨, 但怎么来是python的强项。/home/tools/gn gen /home/openharmony/code-v1.1.1-LTS/out/hispark_aries/ipcamera_hispark_aries \ --root=/home/openharmony/code-v1.1.1-LTS \ --dotfile=/home/openharmony/code-v1.1.1-LTS/build/lite/.gn \ --script-executable=python3 \ '--args=ohos_build_type="debug" ohos_build_compiler_specified="clang" ohos_build_compiler_dir="/home/tools/llvm" product_path="/home/openharmony/code-v1.1.1-LTS/vendor/hisilicon/hispark_aries" device_path="/home/openharmony/code-v1.1.1-LTS/device/hisilicon/hispark_aries/sdk_liteos" ohos_kernel_type="liteos_a" enable_ohos_appexecfwk_feature_ability = false ohos_full_compile=true'
1
2
3
4
5图为绕过hb python部分直接执行gn gen 的结果:
gn : 类似构建界的高级语言,gn和ninja的关系有点像C和汇编语言的关系,与它对标的是cmake,它的作用是生成.ninja文件,不用gn直接用ninja行不行? 也行,但更麻烦。就跟全用汇编写鸿蒙系统一样,理论上可行,可谁会这么去干呢。
ninja:类似构建界的汇编语言,与它对标的是make,由它完成对编译器clang,链接器ld的使用。
makefile:鸿蒙有些模块用的还是make编译, 听说后面会统一使用ninja,是不是以后就看不到make文件了,目前是还有大量的make存在。
如何调试 hb
推荐使用vscode来调试,在调试面板点击 create a launch.json file
创建调试文件,复制以下内容就可以调试hb了。
{
"version": "0.2.0",
"configurations": [
{// hb set
"name": "hb set",
"type": "python",
"request": "launch",
"program": "./build/lite/hb/__main__.py",
"console": "integratedTerminal",
"args": ["set"],
"stopOnEntry": true
},
{//hb build
"name": "hb build debug",
"type": "python",
"request": "launch",
"program": "./build/lite/hb/__main__.py",
"console": "integratedTerminal",
"args": ["build"],
"stopOnEntry": true
},
{//hb clean
"name": "hb clean",
"type": "python",
"request": "launch",
"program": "./build/lite/hb/__main__.py",
"console": "integratedTerminal",
"args": ["clean"],
"stopOnEntry": true
},
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
构建流程
编译构建流程图所示,主要分设置和编译两步:
本篇调试图中的 hb set
| hb build
两个命令
hb set | 选择项目
源码见于: ./build/lite/hb/set/set.py
hb set
执行的大致流程是这样的:
你可以在任何目录下执行
hb set
, 它尝试读取当前目录下的ohos_config.json
配置文件,如果没有会让你输入代码的路径[OHOS INFO] Input code path:
1也就是源码根目录, 生成
ohos_config.json
配置文件,配置内容项是固定的,由Config
类管理。可以在以下位置打上断点调试
set
命令,跟踪整个过程。def exec_command(args): if args.root_path is not None: return set_root_path(root_path=args.root_path) if args.product: return set_product() return set_root_path() == 0 and set_product() == 0
1
2
3
4
5
6
7
8图为断点调试现场
最后生成的配置文件如下:
{ "root_path": "/home/openharmony/code-v1.1.1-LTS", "board": "hispark_aries", "kernel": "liteos_a", "product": "ipcamera_hispark_aries", "product_path": "/home/openharmony/code-v1.1.1-LTS/vendor/hisilicon/hispark_aries", "device_path": "/home/openharmony/code-v1.1.1-LTS/device/hisilicon/hispark_aries/sdk_liteos", "patch_cache": null }
1
2
3
4
5
6
7
8
9有了这些路径就为后续
hb build
铺好了路。
hb build | 编译项目
源码见于: ./build/lite/hb/build/*.py
建议大家去调试下源码,非常有意思,能看清楚所有的细节。本篇将编译工具中重要代码都加上了注解。
也可以前往 weharmony | 注解鸿蒙编译工具 查看对其的代码注释工程。
总体步骤是分两步:
- 调用 gn_build 使用
gn gen
生成 *.ninja 文件 - 调用 ninja_build 使用
ninja -w dupbuild=warn -C
生成 *.o *.so *.bin 等最后的文件
gn_build
关于gn的资料可以前往 GN参考手册查看。 具体gn是如何生成.ninja文件的,后续有篇幅详细介绍其语法及在鸿蒙中的使用。
#执行gn编译
def gn_build(self, cmd_args):
# Clean out path
remove_path(self.config.out_path) #先删除out目录
makedirs(self.config.out_path) #创建out目录
# Gn cmd init and execute ,生成 build.ninja, args.gn
gn_path = self.config.gn_path
gn_args = cmd_args.get('gn', [])
gn_cmd = [gn_path,#gn的安装路径 ~/gn
'gen',
self.config.out_path, #/home/openharmony/out/hispark_aries/ipcamera_hispark_aries
'--root={}'.format(self.config.root_path), #项目的根例如:/home/openharmony
'--dotfile={}/.gn'.format(self.config.build_path),#/home/openharmony/build/lite/.gn -> root = "//build/lite"
f'--script-executable={sys.executable}',#python3
'--args={}'.format(" ".join(self._args_list))] + gn_args
# ohos_build_type="debug"
# ohos_build_compiler_specified="clang"
# ohos_build_compiler_dir="/root/llvm"
# product_path="/home/openharmony/vendor/hisilicon/hispark_aries"
# device_path="/home/openharmony/device/hisilicon/hispark_aries/sdk_liteos"
# ohos_kernel_type="liteos_a"
# enable_ohos_appexecfwk_feature_ability = false
# ohos_full_compile=true'
# 这些参数也将在exec_command后保存在 args.gn文件中
exec_command(gn_cmd, log_path=self.config.log_path)#执行 gn gen .. 命令,在./out/hispark_aries/ipcamera_hispark_aries目录下生成如下文件
# obj 子编译项生成的 ninja文件目录,例如:obj/base/global/resmgr_lite/frameworks/resmgr_lite/global_resmgr.ninja
# args.gn 各种参数, ohos_build_type="debug" ...
# build.ninja 子编译项 例如: build aa: phony dev_tools/bin/aa
# build.ninja.d 由那些模块产生的子编译项 例如:../../../base/global/resmgr_lite/frameworks/resmgr_lite/BUILD.gn
# toolchain.ninja 工具链 放置了各种编译/链接规则 rule cxx rule alink
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ninja_build
关于ninja 的资料可以前往 ninja 参考手册查看。 具体ninja是如何运行的,后续有篇幅详细介绍其语法及在鸿蒙中的使用。
# ninja 编译过程
def ninja_build(self, cmd_args):
ninja_path = self.config.ninja_path
ninja_args = cmd_args.get('ninja', [])
ninja_cmd = [ninja_path,
'-w',
'dupbuild=warn',
'-C',
self.config.out_path] + ninja_args
# ninja -w dupbuild=warn -C /home/openharmony/out/hispark_aries/ipcamera_hispark_aries
# 将读取gn生成的文件,完成编译的第二步,最终编译成 .o .bin 文件
exec_command(ninja_cmd, log_path=self.config.log_path, log_filter=True)
#生成以下部分文件
#NOTICE_FILE OHOS_Image.bin bin build.ninja config etc libs obj server.map test_info userfs
#OHOS_Image OHOS_Image.map bm_tool.map build.ninja.d data foundation.map liteos.bin rootfs.tar suites toggleButtonTest.map userfs_jffs2.img
#OHOS_Image.asm args.gn build.log bundle_daemon_tool.map dev_tools gen media_server.map rootfs_jffs2.img test toolchain.ninja vendor
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
exec_command | utils.py
gn_build
和 ninja_build
最后都会调用 exec_command
来执行命令,exec_command
是个通用方法,见于
build/lite/hb/common/utils.py
,调试时建议在这里打断点,顺瓜摸藤,跟踪相关函数的实现细节。
def exec_command(cmd, log_path='out/build.log', **kwargs):
useful_info_pattern = re.compile(r'\[\d+/\d+\].+')
is_log_filter = kwargs.pop('log_filter', False)
with open(log_path, 'at', encoding='utf-8') as log_file:
process = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding='utf-8',
**kwargs)
for line in iter(process.stdout.readline, ''):
if is_log_filter:
info = re.findall(useful_info_pattern, line)
if len(info):
hb_info(info[0])
else:
hb_info(line)
log_file.write(line)
process.wait()
ret_code = process.returncode
if ret_code != 0:
with open(log_path, 'at', encoding='utf-8') as log_file:
for line in iter(process.stderr.readline, ''):
if 'ninja: warning' in line:
log_file.write(line)
continue
hb_error(line)
log_file.write(line)
if is_log_filter:
get_failed_log(log_path)
hb_error('you can check build log in {}'.format(log_path))
if isinstance(cmd, list):
cmd = ' '.join(cmd)
raise Exception("{} failed, return code is {}".format(cmd, ret_code))
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
图为断点调试现场
百文说内核 | 抓住主脉络
- 百文相当于摸出内核的肌肉和器官系统,让人开始丰满有立体感,因是直接从注释源码起步,在加注释过程中,每每有心得处就整理,慢慢形成了以下文章。内容立足源码,常以生活场景打比方尽可能多的将内核知识点置入某种场景,具有画面感,容易理解记忆。说别人能听得懂的话很重要! 百篇博客绝不是百度教条式的在说一堆诘屈聱牙的概念,那没什么意思。更希望让内核变得栩栩如生,倍感亲切。
- 与代码需不断
debug
一样,文章内容会存在不少错漏之处,请多包涵,但会反复修正,持续更新,v**.xx
代表文章序号和修改的次数,精雕细琢,言简意赅,力求打造精品内容。 - 百文在 < 鸿蒙研究站 | 开源中国 | 博客园 | 51cto | csdn | 知乎 | 掘金 > 站点发布,百篇博客系列目录如下。
按功能模块:
百万注源码 | 处处扣细节
百万汉字注解内核目的是要看清楚其毛细血管,细胞结构,等于在拿放大镜看内核。内核并不神秘,带着问题去源码中找答案是很容易上瘾的,你会发现很多文章对一些问题的解读是错误的,或者说不深刻难以自圆其说,你会慢慢形成自己新的解读,而新的解读又会碰到新的问题,如此层层递进,滚滚向前,拿着放大镜根本不愿意放手。
关注不迷路 | 代码即人生
- 互联网从业十五年,计算机硕士,技术副总裁
- 关注我,持续更新四十年,即聊技术也聊人生
- 交有趣靠谱的人;做难而正确的事
- 不做作,不炒作,只唯真
- 不唯上,不唯书,只唯实
据说喜欢 点赞 + 分享 的,后来都成了大神。😃