百篇博客系列篇.本篇为:

v59.xx 鸿蒙内核源码分析(构建工具篇) | 顺瓜摸藤调试鸿蒙构建过程 | 51.c.h.o

编译构建相关篇为:

构建的必要性

  • 前端开发有构建工具:GruntGulpWebpack
  • 后台开发有构建工具: MavenAntGradle

构建工具重要性不言而喻,它描述了整个工程的如何编译、连接,打包等规则,其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建那些库文件以及如何创建这些库文件、如何最后输出我们想要的文件。

鸿蒙轻内核(L1/liteos)的编译构建工具是hb,hbohos-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 的结果:

  • 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
},
]
}

构建流程

编译构建流程图所示,主要分设置和编译两步:

本篇调试图中的 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

    图为断点调试现场

  • 最后生成的配置文件如下:

      {
    "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 | 注解鸿蒙编译工具 查看对其的代码注释工程.

总体步骤是分两步:

  • 调用 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

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

exec_command | utils.py

gn_buildninja_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))

图为断点调试现场

鸿蒙内核源码分析.总目录

v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 百篇博客分析 | 51.c.h .o

百万汉字注解.百篇博客分析

百万汉字注解 >> 精读鸿蒙源码,中文注解分析, 深挖地基工程,大脑永久记忆,四大码仓每日同步更新< gitee| github| csdn| coding >

百篇博客分析 >> 故事说内核,问答式导读,生活式比喻,表格化说明,图形化展示,主流站点定期更新中< 51cto| csdn| harmony| osc >

关注不迷路.代码即人生

QQ群:790015635 | 入群密码: 666

原创不易,欢迎转载,但请注明出处.

鸿蒙内核源码分析(构建工具篇) | 顺瓜摸藤调试鸿蒙构建过程 | 百篇博客分析OpenHarmony源码 | v59.01的更多相关文章

  1. 鸿蒙内核源码分析(忍者ninja篇) | 都忍者了能不快吗 | 百篇博客分析OpenHarmony源码 | v61.02

    百篇博客系列篇.本篇为: v61.xx 鸿蒙内核源码分析(忍者ninja篇) | 都忍者了能不快吗 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...

  2. 鸿蒙内核源码分析(GN应用篇) | GN语法及在鸿蒙的使用 | 百篇博客分析OpenHarmony源码 | v60.01

    百篇博客系列篇.本篇为: v60.xx 鸿蒙内核源码分析(gn应用篇) | gn语法及在鸿蒙的使用 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...

  3. 鸿蒙内核源码分析(编译脚本篇) | 如何防编译环境中的牛皮癣 | 百篇博客分析OpenHarmony源码 | v58.01

    百篇博客系列篇.本篇为: v58.xx 鸿蒙内核源码分析(环境脚本篇) | 编译鸿蒙原来如此简单 | 51.c.h.o 本篇用两个脚本完成鸿蒙(L1)的编译环境安装/源码下载/编译过程,让编译,调试鸿 ...

  4. 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视GCC编译全过程 | 百篇博客分析OpenHarmony源码| v57.01

    百篇博客系列篇.本篇为: v57.xx 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视编译全过程 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...

  5. 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙看这篇或许真的够了 | 百篇博客分析OpenHarmony源码 | v50.06

    百篇博客系列篇.本篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙防掉坑指南 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙防掉 ...

  6. 鸿蒙源码分析系列(总目录) | 百万汉字注解 百篇博客分析 | 深入挖透OpenHarmony源码 | v8.23

    百篇博客系列篇.本篇为: v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 百篇博客分析 | 51.c.h .o 百篇博客.往期回顾 在给OpenHarmony内核源码加注过程中,整理出以下 ...

  7. 鸿蒙内核源码分析(源码注释篇) | 鸿蒙必定成功,也必然成功 | 百篇博客分析OpenHarmony源码 | v13.02

    百篇博客系列篇.本篇为: v13.xx 鸿蒙内核源码分析(源码注释篇) | 鸿蒙必定成功,也必然成功 | 51.c.h .o 几点说明 kernel_liteos_a_note | 中文注解鸿蒙内核 ...

  8. v72.01 鸿蒙内核源码分析(Shell解析) | 应用窥伺内核的窗口 | 百篇博客分析OpenHarmony源码

    子曰:"苟正其身矣,于从政乎何有?不能正其身,如正人何?" <论语>:子路篇 百篇博客系列篇.本篇为: v72.xx 鸿蒙内核源码分析(Shell解析篇) | 应用窥视 ...

  9. v75.01 鸿蒙内核源码分析(远程登录篇) | 内核如何接待远方的客人 | 百篇博客分析OpenHarmony源码

    子曰:"不学礼,无以立 ; 不学诗,无以言 " <论语>:季氏篇 百篇博客分析.本篇为: (远程登录篇) | 内核如何接待远方的客人 设备驱动相关篇为: v67.03 ...

随机推荐

  1. wpf 中的矩形的歪斜

    <Grid> <Rectangle x:Name="rect12" Width="100" Opacity="1" Hei ...

  2. jquery validate 验证插件 解决多个相同的Name 只验证第一个的方案

    方案一:如果 项目里不是只是个别页面 有多个name 验证, 那么利用 prototype 来写,把这段代码加在你所要使用多个name的页面  的js初始化里 即可 if ($.validator) ...

  3. Mybatis映射器(二)

    上一篇文章返回是resultType,但其无法定义多的属性,比如typeHandler,级联等.为了支持复杂映射,可以用resultMap属性,先定义resultmap属性: <mapper n ...

  4. Go依赖包管理--间接依赖

    目录 1.indirect含义 1.2 直接依赖未启用 Go module 1.2 直接依赖 go.mod 文件不完整 2.总结 1.indirect含义 在使用 Go module 过程中,随着引入 ...

  5. go测试--进阶

    目录 前言 控制编译的参数 -args -json -o 控制测试的参数 -bench regexp -benchtime s -cpu 1,2,4 -count n -failfast -list ...

  6. VS C++ C# 混合编程

    创建C++ DLL 注意,32bit和64bit之间不兼容 创建普通dll工程 设置Properties -> Configuration Properties -> General -& ...

  7. 分布式协调组件Zookeeper之 选举机制与ZAB协议

    Zookeeper简介: Zookeeper是什么: Zookeeper 是⼀个分布式协调服务的开源框架. 主要⽤来解决分布式集群中应⽤系统的⼀致性问题, 例如怎样避免同时操作同⼀数据造成脏读的问题. ...

  8. elsa core—3.elsa 服务

    在本快速入门中,我们将介绍一个用于设置Elsa Server的最小ASP.NET Core应用程序.我们还将安装一些更常用的activities(活动),如Timer.Cron和sendmail,以能 ...

  9. redux的使用

    1.redux的使用 核心概念 action 动作的对象 包含2个属性 type:标识属性, 值为字符串, 唯一, 必要属性 data:数据属性, 值类型任意, 可选属性 例子:{ type: 'AD ...

  10. Session原理、生命周期及购物车功能的实现

    在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).因此,在需要保存用户数据(保存该浏览器(会话)的相关信息)时 ...