# build_lite_note **Repository Path**: weharmony/build_lite_note ## Basic Information - **Project Name**: build_lite_note - **Description**: 注解编译构建子系统, 同步官方源码. - **Primary Language**: Python - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: http://weharmonyos.com - **GVP Project**: No ## Statistics - **Stars**: 10 - **Forks**: 6 - **Created**: 2021-07-22 - **Last Updated**: 2025-01-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: Python, hb, gn, ninja, make ## README 仲弓问仁。子曰:“出门如见大宾,使民如承大祭。己所不欲,勿施于人。在邦无怨,在家无怨。”仲弓曰:“雍虽不敏,请事斯语矣。” 《论语》:颜渊篇 [![](https://gitee.com/weharmonyos/resources/raw/master/common/io.png)](http://weharmonyos.com/) 百篇博客分析.本篇为: (构建工具篇) | 顺瓜摸藤调试构建过程 编译构建相关篇为: * [v50.03 鸿蒙内核源码分析(编译环境) | 编译鸿蒙防掉坑指南](https://my.oschina.net/weharmony/blog/5028613) * [v57.02 鸿蒙内核源码分析(编译过程) | 简单案例说透中间过程](https://my.oschina.net/weharmony/blog/5064209) * [v58.03 鸿蒙内核源码分析(环境脚本) | 编译鸿蒙原来很简单](https://my.oschina.net/weharmony/blog/5132725) * [v59.04 鸿蒙内核源码分析(构建工具) | 顺瓜摸藤调试构建过程](https://my.oschina.net/weharmony/blog/5135157) * [v60.04 鸿蒙内核源码分析(gn应用) | 如何构建鸿蒙系统](https://my.oschina.net/weharmony/blog/5137565) * [v61.03 鸿蒙内核源码分析(忍者ninja) | 忍者的特点就是一个字](https://my.oschina.net/weharmony/blog/5139034) ### 构建的必要性 * 前端开发有构建工具:`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 # 编译工具链配置,包括:编译器路径、编译选项、链接选项等 ``` ### 构建组成 鸿蒙构建系统由 `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' ``` 图为绕过hb python部分直接执行gn gen 的结果: ![](https://gitee.com/weharmonyos/resources/raw/master/59/gn_gen.png) * 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 }, ] } ``` ### 构建流程 编译构建流程图所示,主要分设置和编译两步: ![](http://weharmonyos.com/assets/img/%E7%BC%96%E8%AF%91%E6%9E%84%E5%BB%BA%E6%B5%81%E7%A8%8B.04be21a8.jpg) 本篇调试图中的 `hb set` | `hb build` 两个命令 ### hb set | 选择项目 源码见于: `./build/lite/hb/set/set.py` `hb set`执行的大致流程是这样的: * 你可以在任何目录下执行`hb set`, 它尝试读取当前目录下的 `ohos_config.json`配置文件,如果没有会让你输入代码的路径 ``` [OHOS INFO] Input code path: ``` 也就是源码根目录, 生成`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 ``` 图为断点调试现场 ![](https://gitee.com/weharmonyos/resources/raw/master/59/hb_set.png) * 最后生成的配置文件如下: ``` { "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 } ``` 有了这些路径就为后续 `hb build` 铺好了路. ### hb build | 编译项目 源码见于: `./build/lite/hb/build/*.py` 建议大家去调试下源码,非常有意思,能看清楚所有的细节.本篇将编译工具中重要代码都加上了注解. 也可以前往 [weharmony | 注解鸿蒙编译工具](https://gitee.com/weharmony/build_lite) 查看对其的代码注释工程. 总体步骤是分两步: * 调用 gn_build 使用 `gn gen`生成 *.ninja 文件 * 调用 ninja_build 使用 `ninja -w dupbuild=warn -C` 生成 *.o *.so *.bin 等最后的文件 **gn_build** 关于gn的资料可以前往 [GN参考手册](http://weharmonyos.com/gn/docs/)查看. 具体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 ``` **ninja_build** 关于ninja 的资料可以前往 [ninja 参考手册](http://weharmonyos.com/ninja/index.html)查看. 具体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 ``` ### 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)) ``` 图为断点调试现场 ![](https://gitee.com/weharmonyos/resources/raw/master/59/hb_build.png) ### 百篇博客分析.深挖内核地基 * 给鸿蒙内核源码加注释过程中,整理出以下文章。内容立足源码,常以生活场景打比方尽可能多的将内核知识点置入某种场景,具有画面感,容易理解记忆。说别人能听得懂的话很重要! 百篇博客绝不是百度教条式的在说一堆诘屈聱牙的概念,那没什么意思。更希望让内核变得栩栩如生,倍感亲切.确实有难度,自不量力,但已经出发,回头已是不可能的了。  * 与代码有bug需不断debug一样,文章和注解内容会存在不少错漏之处,请多包涵,但会反复修正,持续更新,v**.xx 代表文章序号和修改的次数,精雕细琢,言简意赅,力求打造精品内容。 按功能模块: |so|tools|load|process |:-:|:-:|:-:|:-:| [总目录](https://my.oschina.net/weharmony/blog/4626852) [调度故事](https://my.oschina.net/weharmony/blog/4634668) [内存主奴](https://my.oschina.net/weharmony/blog/4646802) [源码注释](https://my.oschina.net/weharmony/blog/4686747) [源码结构](https://my.oschina.net/weharmony/blog/4869137) [静态站点](https://my.oschina.net/weharmony/blog/5042657) [注释文档](https://my.oschina.net/weharmony/blog/5042657) |[双向链表](https://my.oschina.net/weharmony/blog/4572304) [位图管理](https://my.oschina.net/weharmony/blog/4888467) [用栈方式](https://my.oschina.net/weharmony/blog/4893388) [定时器](https://my.oschina.net/weharmony/blog/4951625) [原子操作](https://my.oschina.net/weharmony/blog/4955290) [时间管理](https://my.oschina.net/weharmony/blog/4956163) |[ELF格式](https://my.oschina.net/weharmony/blog/5030288) [ELF解析](https://my.oschina.net/weharmony/blog/5048746) [静态链接](https://my.oschina.net/weharmony/blog/5049918) [重定位](https://my.oschina.net/weharmony/blog/5055124) [进程映像](https://my.oschina.net/weharmony/blog/5060359) |[进程管理](https://my.oschina.net/weharmony/blog/4574429) [进程概念](https://my.oschina.net/weharmony/blog/4937521) [Fork](https://my.oschina.net/weharmony/blog/5010301) [特殊进程](https://my.oschina.net/weharmony/blog/5014444) [进程回收](https://my.oschina.net/weharmony/blog/5017716) [信号生产](https://my.oschina.net/weharmony/blog/5022149) [信号消费](https://my.oschina.net/weharmony/blog/5027224) [Shell编辑](https://my.oschina.net/weharmony/blog/5269307) [Shell解析](https://my.oschina.net/weharmony/blog/5282207) | |compile|ipc|mem|task [编译环境](https://my.oschina.net/weharmony/blog/5028613) [编译过程](https://my.oschina.net/weharmony/blog/5064209) [环境脚本](https://my.oschina.net/weharmony/blog/5132725) [构建工具](https://my.oschina.net/weharmony/blog/5135157) [gn应用](https://my.oschina.net/weharmony/blog/5137565) [忍者ninja](https://my.oschina.net/weharmony/blog/5139034) |[自旋锁](https://my.oschina.net/weharmony/blog/4944129) [互斥锁](https://my.oschina.net/weharmony/blog/4945465) [进程通讯](https://my.oschina.net/weharmony/blog/4947398) [信号量](https://my.oschina.net/weharmony/blog/4949720) [事件控制](https://my.oschina.net/weharmony/blog/4950956) [消息队列](https://my.oschina.net/weharmony/blog/4952961) |[内存分配](https://my.oschina.net/weharmony/blog/4646802) [内存管理](https://my.oschina.net/weharmony/blog/4652284) [内存汇编](https://my.oschina.net/weharmony/blog/4692156) [内存映射](https://my.oschina.net/weharmony/blog/4694841) [内存规则](https://my.oschina.net/weharmony/blog/4698384) [物理内存](https://my.oschina.net/weharmony/blog/4842408) |[时钟任务](https://my.oschina.net/weharmony/blog/4574493) [任务调度](https://my.oschina.net/weharmony/blog/4595539) [任务管理](https://my.oschina.net/weharmony/blog/4603919) [调度队列](https://my.oschina.net/weharmony/blog/4606916) [调度机制](https://my.oschina.net/weharmony/blog/4623040) [线程概念](https://my.oschina.net/weharmony/blog/4915543) [并发并行](https://my.oschina.net/weharmony/blog/4940329) [CPU](https://my.oschina.net/weharmony/blog/4952034) [系统调用](https://my.oschina.net/weharmony/blog/4967613) [任务切换](https://my.oschina.net/weharmony/blog/4988628) | |fs|hw [文件概念](https://my.oschina.net/weharmony/blog/5152858) [文件系统](https://my.oschina.net/weharmony/blog/5165752) [索引节点](https://my.oschina.net/weharmony/blog/5168716) [挂载目录](https://my.oschina.net/weharmony/blog/5172566) [根文件系统](https://my.oschina.net/weharmony/blog/5177087) [字符设备](https://my.oschina.net/weharmony/blog/5200946) [VFS](https://my.oschina.net/weharmony/blog/5211662) [文件句柄](https://my.oschina.net/weharmony/blog/5253251) [管道文件](https://my.oschina.net/weharmony/blog/5258434) |[汇编基础](https://my.oschina.net/weharmony/blog/4920361) [汇编传参](https://my.oschina.net/weharmony/blog/4927892) [工作模式](https://my.oschina.net/weharmony/blog/4965052) [寄存器](https://my.oschina.net/weharmony/blog/4969487) [异常接管](https://my.oschina.net/weharmony/blog/4973016) [汇编汇总](https://my.oschina.net/weharmony/blog/4977924) [中断切换](https://my.oschina.net/weharmony/blog/4990948) [中断概念](https://my.oschina.net/weharmony/blog/4992750) [中断管理](https://my.oschina.net/weharmony/blog/4995800) | ### 百万汉字注解.精读内核源码 四大码仓中文注解 . 定期同步官方代码 [![](https://gitee.com/weharmony/kernel_liteos_a_note/widgets/widget_card.svg?colors=393222,ebdfc1,fffae5,d8ca9f,393222,a28b40)](https://gitee.com/weharmony/kernel_liteos_a_note) 鸿蒙研究站( weharmonyos ) | 每天死磕一点点,原创不易,欢迎转载,请注明出处。若能支持点赞则更佳,感谢每一份支持。