鸿蒙内核源码分析(构建工具篇) | 顺瓜摸藤调试鸿蒙构建过程

构建的必要性

  • 前端开发有构建工具:Grunt、Gulp、Webpack
  • 后台开发有构建工具: Maven、Ant、Gradle

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

鸿蒙轻内核(L1/liteos)的编译构建工具是hb,hb是ohos-build的简称, 而ohos又是openharmony os的简称.

hb | ohos-build

hb通过以下命令安装,是用 python写的一个构建工具.

css 复制代码
python3 -m pip install --user ohos-build

其源码在 ./build/lite 目录下,含义如下:

bash 复制代码
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的强项.
ini 复制代码
    /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了.

json 复制代码
{
    "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配置文件,如果没有会让你输入代码的路径
css 复制代码
    [OHOS INFO] Input code path: 

也就是源码根目录, 生成ohos_config.json配置文件,配置内容项是固定的,由Config类管理.

  • 可以在以下位置打上断点调试 set命令,跟踪整个过程.
csharp 复制代码
    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

图为断点调试现场

  • 最后生成的配置文件如下:
json 复制代码
      {
      "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 铺好了路.

DD一下: 欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。

erlang 复制代码
`欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点学习。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......

hb build | 编译项目

源码见于: ./build/lite/hb/build/*.py 建议大家去调试下源码,非常有意思,能看清楚所有的细节.本篇将编译工具中重要代码都加上了注解.

总体步骤是分两步:

  • 调用 gn_build 使用 gn gen生成 *.ninja 文件
  • 调用 ninja_build 使用 ninja -w dupbuild=warn -C 生成 *.o *.so *.bin 等最后的文件

gn_build 具体gn是如何生成.ninja文件的,后续有篇幅详细介绍其语法及在鸿蒙中的使用.

python 复制代码
    #执行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是如何运行的,后续有篇幅详细介绍其语法及在鸿蒙中的使用.

arduino 复制代码
    # 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,调试时建议在这里打断点,顺瓜摸藤,跟踪相关函数的实现细节.

python 复制代码
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))

图为断点调试现场

相关推荐
贾伟康12 分钟前
【化学实验室|07】HarmonyOS ArkTS 知识全局搜索实战:实现跨知识点、公式与阅读内容的本地检索
harmonyos·arkts·arkui·本地搜索·化学知识
马剑威(威哥爱编程)28 分钟前
【共创稿事节】HarmonyOS 7 Agent 开发实战 08:结构化输出解析
华为·harmonyos
donk13141 小时前
React Native for OpenHarmony 实战:三方库 react-native-segmented-control-tab 的鸿蒙化适配指南
javascript·react native·react.js·华为·harmonyos
360智汇云2 小时前
鸿蒙开发中如何实现画中画
华为·harmonyos
donk13144 小时前
React Native for OpenHarmony 实战:三方库 react-native-toast-message 的鸿蒙化适配指南
react native·react.js·音视频·harmonyos
Flutter_OH4 小时前
Flutter OHOS Dart 堆栈符号化
harmonyos
Flutter_OH4 小时前
Flutter OHOS Flutter 多设备自适应 DPI 指导文档
harmonyos
SuperHeroWu74 小时前
【HarmonyOS 7】 应用 Agent 接入云 A2A 与端 A2A 的实践详解
ai·harmonyos·小艺
用户29469405448165 小时前
个人开发者上架鸿蒙 AI 应用,最后倒在安全评估实名制这一格
harmonyos·deepseek
Keya6 小时前
HarmonyOS 开发实战:用 util.Aspect 玩转 AOP 切面编程
harmonyos