1.4 鸿蒙系统编译
1.4.1 鸿蒙设备编译
鸿蒙设备编译使用Gn+Ninja的编译框架。同时使用了makefile或CMake来编译部分软件,也运行shell脚本和python脚本执行拷贝、编译、打包等其他任务。
1.4.1.1 编译工具
1.4.1.1.1 Gn
Gn是google推出的编译工具,作为Chromium和Fuchsia的编译系统。
Gn可以在大多数流行的平台上为C、C++、Rust、Objective C和Swift源代码生成Ninja构建文件。其他语言可以使用Python或其他脚本语言执行的通用“操作”规则进行编译(谷歌这样做是为了编译Java和Go)。
Gn和Ninja一起使用,一个简单的例子是:
gn gen -C out
ninja -C out
./out/hello
Gn的配置文件包括:
- .gn
入口配置,包含配置文件路径、脚本可执行命令
- BUILDCONFIG.gn
配置文件,包含os、cpu及工具链配置
- Toolchain setup
工具链配置,包含编译工具链的编译、链接规则等
- Compiler setup
编译器配置,包含默认参数、包含目录、编译选项及链接选项等
Gn命令有许多选项。
常用的命令command:
#分析哪些目标受到文件列表的影响
gn analyze <out_dir> <input_path> <output_path>
#显示或配置由生成声明的参数
gn args <out_dir> [--list] [--short] [--args] [--overrides-only]
#检查标头相关性
gn check <out_dir> [<label_pattern>] [--force] [--check-generated]
#删除所有输出目录下的除了args.gn的文件
gn clean <out_dir>
#显示许多关于目标或配置的有见地的信息。
gn desc <out_dir> <label or pattern> [<what to show>] [--blame] [--format=json]
#格式化.gn文件。
gn format [--dump-tree] (--stdin | <list of build_files...>)
#生成ninja文件。
gn gen [--check] [<ide options>] <out_dir>
#列出匹配的目标。
gn ls <out_dir> [<label_pattern>] [--all-toolchains] [--as=...] [--type=...] [--testonly=...]
#列出目标元数据收集结果。
gn meta <out_dir> <target>* --data=<key>[,<key>*]* [--walk=<key>[,<key>*]*] [--rebase=<dest dir>]
#查找两个目标之间的路径。
gn path <out_dir> <target_one> <target_two>
#查找引用目标或文件的内容。
gn refs <out_dir> (<label_pattern>|<label>|<file>|@<response_file>)* [--all] [--all-toolchains] [--as=...] [--testonly=...] [--type=...]
gn文件中的目标申明:
- action:声明一个一次性运行脚本的目标。例如运行一个python脚本
- action_foreach:声明一个在一组文件上运行脚本的目标。
- copy:声明一个复制文件的目标。
- executable:声明一个可执行目标。
- generated_file:声明generated_file目标。
- group:声明一组命名的目标。
- loadable_module:声明一个可加载模块目标。
- rust_library:声明一个rust库目标。
- rust_proc_macro:声明rust过程宏目标。
- shared_library:声明一个共享库目标。
- source_set:声明一个源集目标。
- static_library:声明一个静态库目标。
- target:声明具有给定编程类型的目标。
1.4.1.1.2 Ninja
Ninja是一个注重速度的小型构建系统,他比make要快。
ninja基于build.ninja文件来执行编译。一个简单的build.ninja例子包含一个rule和一个build,如下:
cflags = -Wall
rule cc
command = gcc $cflags -c $in -o $out
build foo.o: cc foo.c
执行ninja,就会将foo.c源文件编译为foo.o文件
类似的,可以添加rule和build,再将.o文件链接为可执行程序。
cflags = -Wall
rule cc
command = gcc $cflags -c $in -o $out
rule link
command = gcc $cflags $in -o $out
build foo.o: cc foo.c
build sample: link foo.o
ninja命令常用选项:
-v, --verbose 展示所有的命令行
-C DIR 更改目录为DIR
-f FILE 指定输入文件,默认为build.ninja
-j N 并行执行任务个数
-k N 遇到多少错误停止运行
-l N 如果平均负载大于N,则不要启动新作业
-n dry run (不要运行命令,而是表现得像成功了一样)
-d MODE 是能测试
-t TOOL 子工具
-w FLAG 警告标记
ninja常用工具
ninja -t clean 清理生成的文件
ninja -t browse 浏览器中查看依赖关系图
ninja -t commands 命令列出重建给定目标所需的所有命令
ninja -t deps 显示存储在deps日志中的依赖项
ninja -t graph 输出目标的graphviz点文件
ninja -t query 显示路径的输入/输出
ninja -t targets 在DAG中按规则或深度列出目标
ninja -t compdb 将JSON编译数据库转储到stdout
ninja -t recompact 重组ninja内部数据结构
ninja -t restat 重新启动生成日志中的所有输出
ninja -t rules 列出所有规则
ninja -t cleandead清除清单不再生成的已生成文件
除了gn+ninja的编译工具,鸿蒙中还有部分软件使用Makefile和cmake进行编译,比如内核、三方库等,这里就不一一介绍了。
1.4.1.2 下载源码
1.4.1.2.1 repo下载
鸿蒙源码常用repo工具进行下载。
repo是谷歌推出的下载工具,主页地址
https://gerrit.googlesource.com/git-repo
repo工具的下载方法:
#谷歌源
curl https://storage.googleapis.com/git-repo-downloads/repo -o ~/bin/repo
#国内清华源
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o ~/bin/repo
#gitee源,鸿蒙官方推荐
curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 -o ~/bin/repo
chmod a+x ~/bin/repo
#将~/bin加入环境变量PATH中,或者直接将repo拷贝到/usr/bin下使用
#安装requests
pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests
repo的运行过程中会尝试访问官方的git源更新自己,如果想使用tuna的镜像源进行更新,可以将如下内容复制到你的~/.bashrc里
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'
鸿蒙的代码分支
在下载前,要搞清楚自己需要下载的代码分支,从网页上获取分支信息
OpenHarmony/manifest - Gitee.com
这里列出了鸿蒙全部的分支信息,默认分支为master。
repo下载鸿蒙源码方法很多,这里介绍常见的两种
- repo + https
repo init -u https://gitee.com/openharmony/manifest.git -b 分支名称 --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'
- repo + ssh
repo init -u git@gitee.com:openharmony/manifest.git -b 分支名称 --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'
除了gitee码云的网址,还可以使用github的网址下载鸿蒙源码。
#ssh下载
git@github.com:openharmony/manifest.git
#https下载
https://github.com/openharmony/manifest.git
1.4.1.2.2 发行版源码
除了使用repo工具下载鸿蒙源码,也可以直接下载发行版代码。
打开鸿蒙发行版页面,最新的发行版是v4.0 release:zh-cn/release-notes/Readme.md · OpenHarmony/docs - Gitee.com
点开需要下载的版本页面,找到“从镜像站点获取”,点击“站点”,下载源码,随后在linux操作系统下解压代码。
1.4.1.3 编译
1.4.1.3.1 编译准备
编译前,需要下载和安装必要的编译软件。通过ssh登录到ubuntu服务器上,在命令行执行命令,进行下载:
build/prebuilts_download.sh
下载过程如图:
下载完成后将安装python和nodejs依赖的组件,安装过程如下图:
安装完成后,prebuilts目录下为鸿蒙使用的编译工具,包括gn、ninja、llvm、nodejs、arkjs、clang、cmake、gcc、mingw、python、rust等。
prebuilts目录结构如下:
prebuilts/
├── ark_tools
│ └── ark_js_prebuilts
│ ├── llvm_prebuilts
│ ├── llvm_prebuilts_aarch64
│ └── llvm_prebuilts_windows
├── build-tools
│ ├── common
│ │ ├── js-framework
│ │ ├── nodejs
│ │ └── ts2abc
│ └── linux-x86
│ └── bin
├── clang
├── cmake
├── develop_tools
│ ├── bpftool
│ └── pahole
├── gcc
├── mingw-w64
├── python
└── rustc
下载的文件保存在../openharmony_prebuilts,在完成安装后,该文件夹可以删除。
说明
nodejs和python的依赖组件有时会安装失败,或随着代码的更新需要新安装依赖的组件,所以该命令有时需要多次执行,直到能够正常编译成功。
1.4.1.3.2 编译命令
鸿蒙有3种编译方式,以编译润和rk3568大禹200开发板为例:
- shell命令
./build.sh --product-name rk3568
- python命令
./build.py -p rk3568
- hb命令
hb set
#按键盘的上下键,选择standard,回车
#再按上下键,找到hihope->rk3568,回车
hb build -f
hb工具使用前,需要先进行安装。安装和卸载hb的命令:
#安装
python3 -m pip install --user build/hb
#卸载
python3 -m pip uninstall ohos-build
鸿蒙的编译命令虽然有三个入口,但最终入口为build/hb/main.py脚本。
编译使用的参数很多,常用的有:
-target-cpu {arm,arm64,x86_64,x64} 指定cpu架构,默认arm
-p PRODUCT_NAME, --product-name PRODUCT_NAME 设置产品名称
-T [BUILD_TARGET [BUILD_TARGET ...]], --build-target [BUILD_TARGET [BUILD_TARGET ...]] 指定编译的目标,用于编译一个或多个目标,而不是全部编译
-f [FULL_COMPILATION], --full-compilation [FULL_COMPILATION] 强制全部编译,耗时较长
--build-type {release,profile,debug} 指定编译类型,默认release
--log-level {info,debug} 日志级别,默认INFO
--fast-rebuild [FAST_REBUILD] 快速编译,直接执行ninja命令,默认关闭
--build-only-gn [BUILD_ONLY_GN] 仅执行gn命令
1.4.1.3.3 编译过程
鸿蒙的编译分为几个阶段:
- 第一个阶段是预处理,主要是读取设备产品配置,设置全局变量,执行一些脚本。
扫描产品配置,生成配置文件。检查配置,如果有问题,将报错退出编译。
- 第二个阶段是执行gn命令,生成build.ninja文件。
执行的gn命令如下图:
gn会执行一些BUILD.gn文件中指定的shell脚本和python脚本。例如下载openssl,解压mindspore源码等。
gn执行完成后,生成的build.ninja文件位于out/rk3568目录下,文件的内容是编译的rule和build目标,以及引用的subninja等。
- 第三个阶段是ninja命令,进行编译、链接,最后打包生成镜像文件。
执行的ninja命令如下:
prebuilts/build-tools/linux-x86/bin/ninja -w dupbuild=warn -C out/rk3568 images
编译过程如图
鸿蒙编译时,会占用全部的cpu资源,该过程较长,如下图,这里几乎64个cpu核心均为100%占用:
建议编译配置cpu16核、内存16G以上,存储空间1T。
编译之后,链接动态库、打包生成img文件。
最后输出统计信息,编译完成。
1.4.1.4 烧录镜像
这里依旧以润和rk3568大禹200开发板烧录为例。
开发板烧录工具可以从以下网址下载:
Docs: Hihope IOT物联网设备文档仓 - Gitee.com
首先安装usb驱动
打开文件夹DriverAssitant_v5.1.1,双击DriverInstall.exe运行程序,点击“驱动安装”进行安装。
安装CH340串口驱动,双击驱动程序进行安装。
用usb线(双公头)连接开发板的USB3.0 OTG口和pc机的USB口。用usb串口线,连接开发板的DEBUG口和PC机的USB口。连接后如图:
按住recovery键,接通电源。
打开烧录程序RKDevTool.exe,界面如下:
显示“发现一个LOADER设备”,就可以进行烧录了。
右键,点击“导入配置”,选择输出目录out/rk3568/packages/phone/images下的config.cfg文件,点击“打开”,显示分区配置。这里也可以手动修改分区配置。
点击文件路径后面的空白格,选择编译生成的image文件。
确认好文件后,点击执行,开始烧录,烧录期间,不要断开usb线,不要断电。
烧录完成后,开发板自动重启,即进入编译后的系统。