回顾
在文章中已经分析openharmony的小型系统(liteos-a)编译过程,最主要的就是调用gn/ninja/makefs三个命令最终生成可烧录的镜像文件
在文章详细介绍了liteos-a系统编译时gn命令的原理,本文中针对liteos-a编译时ninja的使用做一些详细说明
通过前面文章中可以看到调用的ninja命令如下

ninja工具
ninja工具源码及文档路径为https://github.com/ninja-build/ninja
网上也有很多中文版的资料,如Ninja - chromium核心构建工具
国内github网站访问慢的问题解决方法可以参考https://www.jianshu.com/p/4ec122a48733
类似gn工具需要在根目录下有一个.gn以及BUILD.gn文件,ninja工具运行需要根目录下有一个build.ninja文件,也即ninja编译规则的入口,此文件所在路径可以通过选项-C dir
来指定,例如liteos-a中使用的就是gn的out路径/home/itsenlin/code/ohos_3.0/out/hispark_taurus/ipcamera_hispark_taurus
build.ninja文件分析
此文件是ninja编译工具的入口,类似于make的makefile;相对于makefile,ninja文件规则、依赖更简单,编译速度也会更快
打开此文件可以看到主要包含以下几块内容
- 版本信息
- 一个生成build.ninja文件的规则
gn
以及build语句
- 包含toolchain.ninja
- 定义一堆build的别名(使用phony规则)
- 定义别名为all的build语句
- 设置默认build
ninja_required_version = 1.7.2
rule gn
command = ../../../prebuilts/build-tools/linux-x86/bin/gn --root=../../.. -q --dotfile=../../../build/lite/.gn --script-executable=/usr/local/bin/python3.9 gen .
description = Regenerating ninja files
build build.ninja: gn
generator = 1
depfile = build.ninja.d
subninja toolchain.ninja
build CalcSubTest: phony ./bin/CalcSubTest.bin
build I18nTest: phony test/unittest/global/bin/I18nTest.bin
......
build all: phony $
obj/applications/sample/camera/ai/ai.stamp $
obj/applications/sample/camera/ai/asr/asr.stamp $
obj/applications/sample/camera/ai/asr/keyword_spotting/kws.stamp $
......
default all
这样在执行ninja命令时,就会默认build这个all
,然后根据前面这个依赖关系进而编译整个系统
但是有一个问题,查看这个文件内容,并没有看到各模块目录下ninja的信息,这个是怎么关联进来的呢?
toolchain.ninja
查看这个文件内容,这里面不仅仅有编译工具链相关的定义,还有对编译所需要的各模块的.ninja
文件的关联也在这里,以及build.gn中定义的一些规则也转换成rule放在这个文件中了,如下
rule cxx
command = /home/itsenlin/code/ohos_3.0/prebuilts/clang/ohos/linux-x86_64/llvm/bin/clang++ ${defines} ${include_dirs} ${cflags_cc} -c ${in} -o ${out}
description = clang++ ${out}
depfile = ${out}.d
deps = gcc
......
build obj/applications/sample/camera/ai/cv/image_classification/demo_image_for_test.stamp: stamp data/image_classification_demo.jpg
build obj/applications/sample/camera/ai/cv/image_classification/ic.stamp: stamp dev_tools/bin/ic_app
subninja obj/applications/sample/camera/ai/cv/image_classification/ic_app.ninja
subninja obj/applications/sample/camera/cameraApp/cameraApp.ninja
rule __applications_sample_camera_cameraApp_cameraApp_hap___build_lite_toolchain_linux_x86_64_ohos_clang__rule
command = /usr/local/bin/python3.9 ../../../build/lite/hap_pack.py --packing-tool-path /home/itsenlin/code/ohos_3.0/developtools/packing_tool/jar/hmos_app_packing_tool.jar --mode hap --json-path /home/itsenlin/code/ohos_3.0/applications/sample/camera/cameraApp/cameraApp/src/main/config.json --resources-path /home/itsenlin/code/ohos_3.0/applications/sample/camera/cameraApp/cameraApp/src/main/resources --ability-so-path /home/itsenlin/code/ohos_3.0/out/hispark_taurus/ipcamera_hispark_taurus/libcameraApp.so --force true --signtool-path /home/itsenlin/code/ohos_3.0/prebuilts/signcenter/hapsigntool/hapsigntoolv2.jar --privatekey OpenHarmony\$ Application\$ Release --sign-algo SHA256withECDSA --unsignhap-path /home/itsenlin/code/ohos_3.0/out/hispark_taurus/ipcamera_hispark_taurus/system/internal/unsigned_cameraApp.hap --signhap-path /home/itsenlin/code/ohos_3.0/out/hispark_taurus/ipcamera_hispark_taurus/system/internal/cameraApp.hap --sign-server rnd-signserver.huawei.com --jks-path /home/itsenlin/code/ohos_3.0/prebuilts/signcenter/key/OpenHarmony.p12 --cert-path /home/itsenlin/code/ohos_3.0/prebuilts/signcenter/certificates/OpenHarmonyApplication.pem --sign-by-server False --cert-profile /home/itsenlin/code/ohos_3.0/applications/sample/camera/cameraApp/cert/camera_HarmonyAppProvision_Release.p7b
description = ACTION //applications/sample/camera/cameraApp:cameraApp_hap(//build/lite/toolchain:linux_x86_64_ohos_clang)
restat = 1
build obj/applications/sample/camera/cameraApp/cameraApp_hap_build_log.txt: __applications_sample_camera_cameraApp_cameraApp_hap___build_lite_toolchain_linux_x86_64_ohos_clang__rule | ../../../build/lite/hap_pack.py ./libcameraApp.so obj/build/lite/prebuilts.stamp
......
这样就关联上了编译所需要的所有的ninja文件,然后 ninja就会对每个依赖项进行编译,最终生成.o
、.a
、.so
、.bin
等文件
题外话
当前openharmony编译系统中不仅仅使用了gn+ninja,还使用了make+makefile。
举个例子,linux kernel的编译就是通过make编译的;而liteos kernel两者都有用,编译的文件也不一样,后面再详细分析吧
是怎么实现使用两种编译工具同时编译的呢?看生成的ninja文件(或者gn中的定义)不难看出是通过执行bash脚本来实现的,以liteos-a的make为例:
gn中有下面这个定义
build_ext_component("make") {
exec_path = rebase_path(".", root_build_dir)
outdir = rebase_path("$target_out_dir/${target_name}_out")
sysroot_path = rebase_path(ohos_current_sysroot)
arch_cflags = string_join(" ", target_arch_cflags)
command = "./build.sh \"$board_name\" \"$ohos_build_compiler\" \"$root_build_dir\" \"$ohos_build_type\" \"$tee_enable\""
command += " \"$device_company\" \"$product_path\" \"$outdir\" \"$ohos_version\" \"$sysroot_path\" \"$arch_cflags\""
command += " \"$device_path\" \"$compile_prefix\" \"$liteos_config_file\""
if (liteos_skip_make) {
print("build_ext_component \"$target_name\" skipped:", command)
command = "true"
}
}
转换成ninja规则如下
rule __kernel_liteos_a_make___build_lite_toolchain_linux_x86_64_ohos_clang__rule
command = /usr/local/bin/python3.9 ../../../build/lite/build_ext_components.py --path=../../../kernel/liteos_a --command=./build.sh\$ \"hispark_taurus\"\$ \"clang\"\$ \"//out/hispark_taurus/ipcamera_hispark_taurus\"\$ \"debug\"\$ \"false\"\$ \"hisilicon\"\$ \"/home/itsenlin/code/ohos_3.0/vendor/hisilicon/hispark_taurus\"\$ \"/home/itsenlin/code/ohos_3.0/out/hispark_taurus/ipcamera_hispark_taurus/obj/kernel/liteos_a/make_out\"\$ \"OpenHarmony\$ 2.3\$ beta\"\$ \"/home/itsenlin/code/ohos_3.0/out/hispark_taurus/ipcamera_hispark_taurus/sysroot\"\$ \"-mfloat-abi=softfp\$ -mfpu=neon-vfpv4\$ -mcpu=cortex-a7\"\$ \"/home/itsenlin/code/ohos_3.0/device/hisilicon/hispark_taurus/sdk_liteos\"\$ \"/home/itsenlin/code/ohos_3.0/prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-\"\$ \"/home/itsenlin/code/ohos_3.0/vendor/hisilicon/hispark_taurus/kernel_configs/debug.config\" --target_dir=/home/itsenlin/code/ohos_3.0/out/hispark_taurus/ipcamera_hispark_taurus/obj/kernel/liteos_a/build.log --out_dir=/home/itsenlin/code/ohos_3.0/out/hispark_taurus/ipcamera_hispark_taurus/error.log
description = ACTION //kernel/liteos_a:make(//build/lite/toolchain:linux_x86_64_ohos_clang)
restat = 1
build obj/kernel/liteos_a/make_build_ext_components.txt: __kernel_liteos_a_make___build_lite_toolchain_linux_x86_64_ohos_clang__rule | ../../../build/lite/build_ext_components.py obj/build/lite/prebuilts.stamp
从上面定义看,就是ninja在编译到这个build的时候就会执行//kernel/liteos-a/build.sh
脚本,而此脚本最后就是执行的make
命令,如下
itsenlin@itsenlin-PC:~/code/ohos_3.0$ tail kernel/liteos_a/build.sh
export OUTDIR="${outdir}"
export KCONFIG_CONFIG="${liteos_config_file}"
export LITEOS_MENUCONFIG_H="${outdir}/config.h"
export LITEOS_CONFIG_FILE="${outdir}/.config"
export LITEOS_COMPILER_PATH="${compile_prefix%/*}/"
export CROSS_COMPILE="${compile_prefix##*/}"
mkdir -p "${outdir}"
make -j all VERSION="${ohos_version}"
itsenlin@itsenlin-PC:~/code/ohos_3.0$
网友评论