鸿蒙内核源码分析(忍者ninja篇) | 都忍者了能不快吗

ninja | 忍者

ninja是一个叫 Evan Martin的谷歌工程师开源的一个自定义的构建系统,最早是用于 chrome的构建,Martin给它取名 ninja(忍者)的原因是因为它strikes quickly(快速出击).这是忍者的特点,可惜Martin不了解中国文化,不然叫小李飞刀更合适些.究竟有多块呢? 用Martin自己的话说是当一个文件被修改后,ninja从发现到编译速度是make的十倍.有没有十倍不是本篇讨论的重点,人家做出来了,就算是牛皮也该人家吹.本篇是要对鸿蒙如何使用ninja做一个比较详细的阐述.

ninja是一个重视速度的构建系统,与其对标的是Make,它们都依赖于文件的时间戳进行检测重编.

  • 它的设计目的是让更高级别的构建系统生成其输入端文件,其并不希望你手动去编.ninja文件,可以生成.ninja的工具有gn,cmake,premake,甚至你自己都可以写个 ninja 生成工具.
  • ninja非常高效,可理解为构建系统中的汇编语言。
  • ninja文件没有分支、循环的流程控制,是被指定了一堆规则的文件,所以要比Makefile简单很多
  • 目前已知的GoogleChromeAndroid的一部分,LLVM, V8, 方舟编译器, 鸿蒙 等大型系统都使用到了ninja构建.

基本概念

sql 复制代码
概念	中译	解释
edge	边      即build语句,指定目标(输出)、规则与输入,是编译过程拓扑图中的一条边(edge)。
target	目标	编译过程需要产生的目标,由build语句指定。
output	输出	build语句的前半段,是target的另一种称呼。
input	输入	build语句的后半段,用来产生output的文件或目标,另一种称呼是依赖。
rule	规则	通过指定command与一些内置变量,决定如何从输入产生输出。
pool	池      一组rule或edge,通过指定其depth,可以控制并行上限。
scope	作用域	变量的作用范围,有rule与build语句的块级,也有文件级别。rule也有scope。
--------------------------------------------------------------------------------------------
关键字	  作用
build	  定义一个edge。
rule	  定义一个rule。
pool	  定义一个pool。
default	  指定默认的一个或多个target。
include	  添加一个ninja文件到当前scope。
subninja  添加一个ninja文件,其scope与当前文件不同。
phony     一个内置的特殊规则,指定非文件的target。

简单的ninja

首先 ninja 一定是简单的,呆板的.凡是能被工具生成的东西,一定是在不断的重复某种简单,众多的简单按一定的规则有效叠加起来就能解决复杂的问题,请仔细想想是不是这个道理.ninja简单到没什么语法,只是几个概念和规则.

看个示例:

ini 复制代码
cflags = -Wall -Werror  #全局变量
rule cc
  command = gcc $cflags -c $in -o $out

build foo.o: cc foo.c

build special.o: cc special.c
  cflags = -Wall #局部变量,范围只在编译special.c上有效

解读

  • cflags:定义一个用户变量,用于给规则传参.
  • rule:定义一个叫cc的规则.
    • command:将生成bash命令,接收外部三个参数
  • 第一个build,将foo.ccc规则编译成foo.o
    • 最终编译选项:gcc -Wall -Werror -c foo.c -o foo.o
  • 第二个build,将special.ccc规则编译成special.o
    • 最终编译选项:gcc -Wall -c foo.c -o foo.o
  • in,outninja的两个内置变量.

phony规则

跟称呼弗拉基米尔·弗拉基米罗维奇·普京普总一样, 有些文件路径会很长,ninja提供取别名的功能,这仅仅是为了方便.

bash 复制代码
build ability: phony ./libability.so
build ability_notes: phony obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/ability_notes.stamp
build ability_test: phony obj/foundation/aafwk/aafwk_lite/services/abilitymgr_lite/unittest/ability_test.stamp
build ability_test_pageAbilityTest_group_lv0: phony obj/foundation/aafwk/aafwk_lite/services/abilitymgr_lite/unittest/test_lv0/page_ability_test/ability_test_pageAbilityTest_group_lv0.stamp

有了上面的铺垫,读懂鸿蒙的ninja部分应该没多大障碍了.

鸿蒙 | ninja

在[v60.xx 鸿蒙内核源码分析(gn应用篇) | gn语法及在鸿蒙的使用 ]篇的末尾已说明通过 gn gen生成了以下文件和目录

ruby 复制代码
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS/out/hispark_aries/ipcamera_hispark_aries$ ls
args.gn  build.ninja  build.ninja.d  NOTICE_FILE  obj  test_info  toolchain.ninja
  • args.gn :一些参数
  • build.ninja : ninja的主文件
  • build.ninja.d :记录生成所有.ninja 所依赖的BUILD.gn文件路劲列表,一个BUILD.gn就生成一个.ninja文件
  • obj :各组件模块构建/编译文件输出地.
  • toolchain :放置ninja规则,将被 subninja 进 build.ninja

build.ninja

build.ninja内容如下:

bash 复制代码
ninja_required_version = 1.7.2

rule gn
  command = ../../../../tools/gn --root=../../.. -q --dotfile=../../../build/lite/.gn --script-executable=python3 gen .
  description = Regenerating ninja files

build build.ninja: gn
  generator = 1
  depfile = build.ninja.d

subninja toolchain.ninja

build ability: phony ./libability.so
build ability_notes: phony obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/ability_notes.stamp
build ability_test: phony obj/foundation/aafwk/aafwk_lite/services/abilitymgr_lite/unittest/ability_test.stamp
build ability_test_pageAbilityTest_group_lv0: phony obj/foundation/aafwk/aafwk_lite/services/abilitymgr_lite/unittest/test_lv0/page_ability_test/ability_test_pageAbilityTest_group_lv0.stamp
#此处省略诸多 phony ..

build all: phony $
    ./libcameraApp.so $
    obj/applications/sample/camera/cameraApp/cameraApp_hap.stamp $
    ./libgallery.so $
    ...

default all

解读

  • 前面部分是定义一个 gn规则,用于干嘛呢? 重新生成一遍 *ninja文件
  • subninja相当于 #include文件
  • default all,指定默认的一个或多个target

toolchain | 定义规则

toolchain.ninja 定义了编译c,c++,汇编器,链接,静态/动态链接库,时间戳,拷贝等规则. 内容如下:

ini 复制代码
rule cxx
  command = /root/llvm/bin/clang++ ${defines} ${include_dirs} ${cflags_cc} -c ${in} -o ${out}
  description = clang++ ${out}
  depfile = ${out}.d
  deps = gcc
rule alink
  command = /root/llvm/bin/llvm-ar -cr ${out} @"${out}.rsp"
  description = AR ${out}
  rspfile = ${out}.rsp
  rspfile_content = ${in}
rule link
  command = /root/llvm/bin/clang ${ldflags} ${in} ${libs}   -o ${output_dir}/bin/${target_output_name}${output_extension}
  description = LLVM LINK ${output_dir}/bin/${target_output_name}${output_extension}
  rspfile = ${output_dir}/bin/${target_output_name}${output_extension}.rsp
  rspfile_content = ${in}
rule solink
  command = /root/llvm/bin/clang -shared ${ldflags} ${in} ${libs} -o ${output_dir}/${target_output_name}${output_extension}
  description = SOLINK ${output_dir}/${target_output_name}${output_extension}
  rspfile = ${output_dir}/${target_output_name}${output_extension}.rsp
  rspfile_content = ${in}
rule stamp
  command = /usr/bin/touch ${out}
  description = STAMP ${out}
rule asm
  command = /root/llvm/bin/clang ${include_dirs} ${asmflags} -c ${in} -o ${out}
  description = ASM ${out}
  depfile = ${out}.d
  deps = gcc
rule cc
  command = /root/llvm/bin/clang ${defines} ${include_dirs} ${cflags} ${cflags_c} -c ${in} -o ${out}
  description = clang ${out}
rule copy
  command = cp -afd ${in} ${out}
  description = COPY ${in} ${out}
  • 注意这些规则中的描述description字段,其后面的内容会打到控制台上,每一条输出都是一次 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.鸿蒙版性能优化指南
.......

组件编译

本篇以编译ability组件为例说明 ninja对组件的编译情况.每个组件都有自己的.ninja,描述组件的编译细节.而整个鸿蒙系统就是由众多的类似.ninja构建编译完成的.

复制代码
├── foundation
│   ├── aafwk
│   │   └── aafwk_lite
│   │       ├── frameworks
│   │       │   ├── ability_lite
│   │       │   │   └── ability.ninja

ability.ninja内容如下:

bash 复制代码
defines = -DOHOS_APPEXECFWK_BMS_BUNDLEMANAGER \
          -D_XOPEN_SOURCE=700 -DOHOS_DEBUG \
          -D_FORTIFY_SOURCE=2 \
          -D__LITEOS__ -D__LITEOS_A__
include_dirs = -I../../../foundation/aafwk/aafwk_lite/frameworks/abilitymgr_lite/include \
               -I../../../foundation/aafwk/aafwk_lite/frameworks/want_lite/include \
               -I../../../foundation/aafwk/aafwk_lite/interfaces/innerkits/abilitymgr_lite \
               -I../../../foundation/aafwk/aafwk_lite/interfaces/kits/want_lite \
               -I../../../foundation/aafwk/aafwk_lite/interfaces/kits/ability_lite \
               -I../../../foundation/appexecfwk/appexecfwk_lite/utils/bundle_lite \
               -I../../../foundation/appexecfwk/appexecfwk_lite/interfaces/kits/bundle_lite \
               -I../../../foundation/appexecfwk/appexecfwk_lite/frameworks/bundle_lite/include \
               -I../../../foundation/graphic/ui/frameworks -I../../../foundation/graphic/surface/interfaces/kits \
               -I../../../foundation/distributedschedule/samgr_lite/interfaces/kits/registry \
               -I../../../foundation/distributedschedule/samgr_lite/interfaces/kits/samgr \
               -I../../../foundation/communication/ipc_lite/frameworks/liteipc/include \
               -I../../../kernel/liteos_a/kernel/include \
               -I../../../kernel/liteos_a/kernel/common \
               -I../../../third_party/bounds_checking_function/include \
               -I../../../third_party/freetype/include \
               -I../../../utils/native/lite/kv_store/innerkits \
               -I../../../utils/native/lite/include \
               -I../../../foundation/aafwk/aafwk_lite/frameworks/ability_lite/include \
               -I../../../foundation/aafwk/aafwk_lite/frameworks/ability_lite \
               -I/root/llvm/include/c++/v1 \
               -I../../../prebuilts/lite/sysroot/usr/include/arm-liteos \
               -I../../../base/hiviewdfx/hilog_lite/interfaces/native/innerkits/hilog \
               -I../../../base/hiviewdfx/hilog_lite/interfaces/native/innerkits \
               -I../../../third_party/bounds_checking_function/include \
               -I../../../third_party/bounds_checking_function/include \
               -I../../../foundation/communication/ipc_lite/interfaces/kits \
               -I../../../utils/native/lite/include
cflags = -Wall -Wno-format -Wno-format-extra-args -fPIC \
          --target=arm-liteos \
          --sysroot=/home/openharmony/prebuilts/lite/sysroot \
          -Oz -flto -mfloat-abi=softfp -mcpu=cortex-a7 -nostdlib -fno-common -fno-builtin -fno-strict-aliasing -Wall -fsigned-char -mno-unaligned-access -fno-omit-frame-pointer -fstack-protector-all -fPIC
cflags_cc = -Wall -Wno-format -Wno-format-extra-args -fPIC \
            --target=arm-liteos \
            --sysroot=/home/openharmony/prebuilts/lite/sysroot \
            -Oz -flto -mfloat-abi=softfp -mcpu=cortex-a7 -nostdlib -fno-common -fno-builtin -fno-strict-aliasing -Wall -mno-unaligned-access -fno-omit-frame-pointer -fstack-protector-all -fexceptions -std=c++11 -fPIC
target_output_name = libability

build obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability.o: cxx ../../../foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/ability.cpp
build obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_context.o: cxx ../../../foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/ability_context.cpp
build obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_env.o: cxx ../../../foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/ability_env.cpp
build obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_env_impl.o: cxx ../../../foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/ability_env_impl.cpp
build obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_event_handler.o: cxx ../../../foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/ability_event_handler.cpp
build obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_loader.o: cxx ../../../foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/ability_loader.cpp
build obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_main.o: cxx ../../../foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/ability_main.cpp
build obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_scheduler.o: cxx ../../../foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/ability_scheduler.cpp
build obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_thread.o: cxx ../../../foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/ability_thread.cpp

build ./libability.so: solink \
  obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability.o \
  obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_context.o \
  obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_env.o \
  obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_env_impl.o \
  obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_event_handler.o \
  obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_loader.o \
  obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_main.o \
  obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_scheduler.o \
  obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite/src/libability.ability_thread.o \
  ./libabilitymanager.so ./libbundle.so ./libhilog_shared.so ./libliteipc_adapter.so \
  ./libsec_shared.so ./libutils_kv_store.so || obj/utils/native/lite/kv_store/kv_store.stamp
  ldflags = -lstdc++ \
  --target=arm-liteos \
  --sysroot=/home/openharmony/prebuilts/lite/sysroot \
  -L/root/llvm/lib/arm-liteos/c++ \
  -L/home/openharmony/prebuilts/lite/sysroot/usr/lib/arm-liteos \
  -L/root/llvm/lib/clang/9.0.0/lib/arm-liteos \
  -lclang_rt.builtins -lc -lc++ -lc++abi \
  --sysroot=/home/openharmony/prebuilts/lite/sysroot \
  -mcpu=cortex-a7 -lc \
  -L/home/openharmony/out/hispark_aries/ipcamera_hispark_aries \
  -Wl,-rpath-link=/home/openharmony/out/hispark_aries/ipcamera_hispark_aries -Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack
  libs =
  frameworks =
  output_extension = .so
  output_dir = .

解读

  • defines,include_dirs,cflags_cc都是用户自定义变量,为了给 rule cxx准备参数,对.cpp的编译使用了这个规则
ini 复制代码
    rule cxx
      command = /root/llvm/bin/clang++ ${defines} ${include_dirs} ${cflags_cc} -c ${in} -o ${out}
      description = clang++ ${out}
      depfile = ${out}.d
      deps = gcc
  • in,out是两个内置变量,无须定义,值由build提供,如此就编译成了一个个的 .o文件.
  • 在最后在当前目录下使用了solink规则,生成一个动态链接库libability.so.
ini 复制代码
   rule solink
     command = /root/llvm/bin/clang -shared ${ldflags} ${in} ${libs} -o ${output_dir}/${target_output_name}${output_extension}
     description = SOLINK ${output_dir}/${target_output_name}${output_extension}
     rspfile = ${output_dir}/${target_output_name}${output_extension}.rsp
     rspfile_content = ${in}

ability | 最终生成文件

ruby 复制代码
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS/out/hispark_aries/ipcamera_hispark_aries/obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite$ tree
.
├── aafwk_abilitykit_lite.stamp
├── ability.ninja
├── ability_notes.stamp
└── src
    ├── libability.ability_context.o
    ├── libability.ability_env_impl.o
    ├── libability.ability_env.o
    ├── libability.ability_event_handler.o
    ├── libability.ability_loader.o
    ├── libability.ability_main.o
    ├── libability.ability.o
    ├── libability.ability_scheduler.o
    └── libability.ability_thread.o

1 directory, 12 files
turing@ubuntu:/home/openharmony/code-v1.1.1-LTS/out/hispark_aries/ipcamera_hispark_aries/obj/foundation/aafwk/aafwk_lite/frameworks/ability_lite$ stat ability_notes.stamp 
  File: ability_notes.stamp
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: 805h/2053d	Inode: 1217028     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/  turing)   Gid: (    0/    root)
Access: 2021-07-21 00:38:52.237373740 -0700
Modify: 2021-07-21 00:34:30.207312566 -0700
Change: 2021-07-21 00:34:30.207312566 -0700
相关推荐
Miguo94well7 小时前
Flutter框架跨平台鸿蒙开发——地理知识速记APP的开发流程
flutter·华为·harmonyos·鸿蒙
讯方洋哥9 小时前
HarmonyOS App开发——鸿蒙音乐播放机应用App开发
华为·harmonyos
小雨青年10 小时前
【鸿蒙原生开发会议随记 Pro】 会议随记 Pro v1.1 发布 详解 HarmonyOS NEXT 原生国际化(i18n)架构与最佳实践
华为·harmonyos
木斯佳11 小时前
HarmonyOS 6实战(源码教学篇)— Speech Kit TextReader:【仿某云音乐接入语音朗读控件】
华为·harmonyos
南村群童欺我老无力.11 小时前
Flutter 框架跨平台鸿蒙开发 - 校园生活一站式:打造智慧校园服务平台
flutter·华为·harmonyos
南村群童欺我老无力.13 小时前
Flutter 框架跨平台鸿蒙开发 - 城市文创打卡:探索城市文化创意之旅
android·flutter·华为·harmonyos
yingdonglan14 小时前
Flutter 框架跨平台鸿蒙开发 ——AnimatedBuilder性能优化详解
flutter·性能优化·harmonyos
菜鸟小芯15 小时前
【开源鸿蒙跨平台开发先锋训练营】DAY8~DAY13 底部选项卡&首页功能实现
flutter·harmonyos
大雷神15 小时前
HarmonyOS智慧农业管理应用开发教程--高高种地-- 第19篇:语音合成 - TTS语音播报
华为·语音识别·harmonyos
b20772115 小时前
Flutter for OpenHarmony 身体健康状况记录App实战 - 提醒设置实现
python·flutter·macos·cocoa·harmonyos