OpenHarmony 5.0 qemu 编译记录

HarmonyOS Next(Based on OpenHarmony)公测了,微信、QQ也都适配了,打算研究研究OpenHarmony,先下份代码,编译qemu镜像玩玩,没想到居然有坑,记录一下,供参考.

整体参考OpenHarmony的快速入门文档.
从官方文档看到,OpenHarmony编译,支持IDE环境、也支持命令行环境,支持Ubuntu、也支持Windows. 由于习惯使用Ubuntu和命令行,我先尝试基于Ubuntu系统、使用命令行编译.

获取源码

下载repo

玩过AOSP源码的同学,对repo工具应该不陌生. repo(源代码控制工具,Repo 命令参考资料,repo源代码)是Android为了方便管理多个git库而开发的Python脚本.

参考OpenHarmony的获取源码文档,我们需要安装git、git-lfs,配置git,下载repo工具,并加入PATH环境变量,这一步完成,我们就可以使用repo工具了.

使用repo下载代码

我希望同步openharmony-5.0的代码,所以使用如下命令:
本地创建新的目录,用于存放源代码.

1
2
mkdir ~/openharmony-5.0
cd ~/openharmony-5.0

开始下载

1
2
3
repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony-5.0.1-Release --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'

下载完成后,目录下能看到很多文件:

1
2
3
4
5
$ ls ~/openharmony-5.0
applications build.py device foundation napi_generator qemu-run
arkcompiler build.sh docs ide out test
base commonlibrary domains interface prebuilts third_party
build developtools drivers kernel productdefine vendor

然后,还需要执行prebuilts脚本,这个脚本会将一些编译工具压缩包下载到与源代码目录同级的~/openharmony_prebuilts目录,并解压、安装到源代码目录.
bash build/prebuilts_download.sh

下载压缩包

如果repo工具使用存在问题,还可以选择下载压缩包,解压.

例如OpenHarmony-v5.0.0源代码压缩包5.0发布文档可以找到. 下载完成后,解压即可拿到源代码.
tar -xzf code-v5.0.0-Release.tar.gz

配置编译环境

手动配置环境

参考准备开发环境安装库和工具集,安装相关工具.

Docker环境

OpenHarmony为开发者提供了Docker环境,以帮助开发者快速完成复杂的开发环境准备工作,很适合我们这种洁癖患者.
参考Docker编译环境
安装docker
sudo apt install docker.io
获取docker镜像
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/docker_oh_standard:3.2
进入docker构建环境
docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/docker_oh_standard:3.2

构建

我们尝试构建qemu的镜像,qemu的devicevendor已经跟随源代码同步到了device/qemu和vendor/ohemu

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ ls device/qemu
arm_mps2_an386 drivers LICENSE README_zh.md SmartL_E802
arm_mps3_an547 esp32 OAT.xml riscv32_virt x86_64_virt
arm_virt hardware README.md riscv64_virt
$ ls vendor/ohemu
common qemu_mini_system_demo
LICENSE qemu_riscv32_mini_system_demo
OAT.xml qemu_riscv64_linux_min
qemu_arm64_linux_min qemu_small_system_demo
qemu_arm_linux_headless qemu_x86_64_linux_min
qemu_arm_linux_min qemu_xtensa_mini_system_demo
qemu_ca7_mini_system_demo README.md
qemu_cm55_mini_system_demo README_zh.md
qemu_csky_mini_system_demo

开始构建

尝试构建x86_64架构的qemu镜像,参考README
执行build.sh脚本即可开始构建.
./build.sh --product-name qemu-x86_64-linux-min --ccache --jobs 4

编译报错解决

不知道是我的问题,还是OpenHarmony的源代码问题,关键我下载的是Release分支的代码,居然编译报错,,,没办法,只能想办法解决.

subsystem name config incorrect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[OHOS ERROR] Traceback (most recent call last):
[OHOS ERROR] File "/home/openharmony/build/hb/containers/status.py", line 47, in wrapper
[OHOS ERROR] return func(*args, **kwargs)
[OHOS ERROR] ^^^^^^^^^^^^^^^^^^^^^
[OHOS ERROR] File "/home/openharmony/build/hb/modules/ohos_build_module.py", line 67, in run
[OHOS ERROR] raise exception
[OHOS ERROR] File "/home/openharmony/build/hb/modules/ohos_build_module.py", line 65, in run
[OHOS ERROR] super().run()
[OHOS ERROR] File "/home/openharmony/build/hb/modules/interface/build_module_interface.py", line 70, in run
[OHOS ERROR] raise exception
[OHOS ERROR] File "/home/openharmony/build/hb/modules/interface/build_module_interface.py", line 66, in run
[OHOS ERROR] self._load()
[OHOS ERROR] File "/home/openharmony/build/hb/modules/ohos_build_module.py", line 83, in _load
[OHOS ERROR] self.loader.run()
[OHOS ERROR] File "/home/openharmony/build/hb/services/interface/load_interface.py", line 50, in run
[OHOS ERROR] self.__post_init__()
[OHOS ERROR] File "/home/openharmony/build/hb/services/loader.py", line 117, in __post_init__
[OHOS ERROR] self.parts_config_info = load_ohos_build.get_parts_info(
[OHOS ERROR] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[OHOS ERROR] File "/home/openharmony/build/hb/util/loader/load_ohos_build.py", line 914, in get_parts_info
[OHOS ERROR] _parts_variants = build_loader.parts_variants()
[OHOS ERROR] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[OHOS ERROR] File "/home/openharmony/build/hb/util/loader/load_ohos_build.py", line 504, in parts_variants
[OHOS ERROR] self.parse()
[OHOS ERROR] File "/home/openharmony/build/hb/util/loader/load_ohos_build.py", line 495, in parse
[OHOS ERROR] subsystem_config, parts_path_dict = self._merge_build_config()
[OHOS ERROR] ^^^^^^^^^^^^^^^^^^^^^^^^^^
[OHOS ERROR] File "/home/openharmony/build/hb/util/loader/load_ohos_build.py", line 625, in _merge_build_config
[OHOS ERROR] raise OHOSException("subsystem name config incorrect in '{}', build file subsystem name is {},"
[OHOS ERROR] exceptions.ohos_exception.OHOSException: subsystem name config incorrect in '/home/openharmony/device/qemu/x86_64_virt/linux/ohos.build', build file subsystem name is device_x86_64_virt,configured subsystem name is device_qemu-x86_64-linux.
[OHOS ERROR]
[OHOS ERROR] Code: 2014
[OHOS ERROR]
[OHOS ERROR] Reason: subsystem name config incorrect in '/home/openharmony/device/qemu/x86_64_virt/linux/ohos.build', build file subsystem name is device_x86_64_virt,configured subsystem name is device_qemu-x86_64-linux.
[OHOS ERROR]
[OHOS ERROR] Error Type: UNKNOWN ERROR TYPE
[OHOS ERROR]
[OHOS ERROR] Description: NO DESCRIPTION
[OHOS ERROR]
[OHOS ERROR] Solution: UNKNOWN REASON
[OHOS ERROR]

我的解决方案是修改build/compile_standard_whitelist.json,将报错的device/qemu/x86_64_virt/linux/ohos.build加到bundle_subsystem_error白名单

1
2
3
4
5
6
7
         "device/board/hisilicon/hispark_taurus/linux/ohos.build",
"device/board/hisilicon/hispark_taurus/ohos.build",
"device/qemu/arm_virt/linux/ohos.build",
+ "device/qemu/x86_64_virt/linux/ohos.build",
"third_party/flutter/glfw/bundle.json",
"vendor/hihope/rk3568/ohos.build",
"vendor/hihope/ipcamera/ohos.build"

find component failed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[OHOS ERROR] Traceback (most recent call last):
[OHOS ERROR] File "/home/openharmony/build/hb/containers/status.py", line 47, in wrapper
[OHOS ERROR] return func(*args, **kwargs)
[OHOS ERROR] ^^^^^^^^^^^^^^^^^^^^^
[OHOS ERROR] File "/home/openharmony/build/hb/modules/ohos_build_module.py", line 65, in run
[OHOS ERROR] super().run()
[OHOS ERROR] File "/home/openharmony/build/hb/modules/interface/build_module_interface.py", line 66, in run
[OHOS ERROR] self._load()
[OHOS ERROR] File "/home/openharmony/build/hb/modules/ohos_build_module.py", line 83, in _load
[OHOS ERROR] self.loader.run()
[OHOS ERROR] File "/home/openharmony/build/hb/services/interface/load_interface.py", line 50, in run
[OHOS ERROR] self.__post_init__()
[OHOS ERROR] File "/home/openharmony/build/hb/services/loader.py", line 117, in __post_init__
[OHOS ERROR] self.parts_config_info = load_ohos_build.get_parts_info(
[OHOS ERROR] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[OHOS ERROR] File "/home/openharmony/build/hb/util/loader/load_ohos_build.py", line 947, in get_parts_info
[OHOS ERROR] _output_parts_info(parts_config_dict,
[OHOS ERROR] File "/home/openharmony/build/hb/util/loader/load_ohos_build.py", line 765, in _output_parts_info
[OHOS ERROR] check_subsystem_and_component(parts_info_output_path, skip_partlist_check)
[OHOS ERROR] File "/home/openharmony/build/hb/util/loader/load_ohos_build.py", line 696, in check_subsystem_and_component
[OHOS ERROR] compare_subsystem_and_component(subsystem_name, components_name, subsystem_compoents_whitelist_info,
[OHOS ERROR] File "/home/openharmony/build/hb/util/loader/load_ohos_build.py", line 662, in compare_subsystem_and_component
[OHOS ERROR] raise Exception(message)
[OHOS ERROR] Exception: find component device_qemu-x86_64-linux failed, please check it in /home/openharmony/out/preloader/qemu-x86_64-linux-min/parts.json.
[OHOS ERROR]
[OHOS ERROR] Code: 0000
[OHOS ERROR]
[OHOS ERROR] Reason: find component device_qemu-x86_64-linux failed, please check it in /home/openharmony/out/preloader/qemu-x86_64-linux-min/parts.json.
[OHOS ERROR]
[OHOS ERROR] Error Type: UNKNOWN ERROR TYPE
[OHOS ERROR]
[OHOS ERROR] Description: NO DESCRIPTION
[OHOS ERROR]
[OHOS ERROR] Solution: NO SOLUTION
[OHOS ERROR]

聪明的你应该能看到很明显报错的堆栈中看到了subsystem_compoents_whitelist_info,又是添加白名单,陆陆续续,有好几个白名单问题,以下是简要的报错Log:
Exception: find subsystem device_x86_64_virt failed, please check it in /home/openharmony/out/preloader/qemu-x86_64-linux-min/parts.json.
Exception: find component product_qemu-x86_64-linux-min failed, please check it in /home/openharmony/out/preloader/qemu-x86_64-linux-min/parts.json.
我的解决方案是,修改build/compile_standard_whitelist.json,将找不到的device_qemu-x86_64-linux、device_x86_64_virt、product_qemu-x86_64-linux-min三个组件加到subsystem_components白名单.

1
2
3
4
5
6
7
8
     ],
- "subsystem_components": [],
+ "subsystem_components": [
+ "device_qemu-x86_64-linux",
+ "device_x86_64_virt",
+ "product_qemu-x86_64-linux-min"
+ ],
"gn_part_or_subsystem_error": [

不是很理解,OpenHarmony作为一个开放的操作系统,每个device都需要额外加到白名单?

你以为这就完了么,还有其他报错等着你呢!

Undefined identifier wifi_ffrt_enable

1
2
3
4
5
6
ERROR at //foundation/communication/wifi/wifi/utils/BUILD.gn:100:9: Undefined identifier
if (wifi_ffrt_enable) {
^---------------
See //foundation/communication/wifi/wifi/frameworks/native/BUILD.gn:295:7: which caused the file to be included.
"$WIFI_ROOT_DIR/utils:wifi_utils",
^--------------------------------

这个报错倒是不难,修改foundation/communication/wifi下的wifi/wifi.gni文件:

1
2
3
4
5
6
7
8
9
10
11
12
diff --git a/wifi/wifi.gni b/wifi/wifi.gni
index 5cd865d..67ed62c 100644
--- a/wifi/wifi.gni
+++ b/wifi/wifi.gni
@@ -31,6 +31,7 @@ declare_args() {
wifi_feature_non_seperate_p2p = false
wifi_feature_non_hdf_driver = false
wifi_feature_with_local_random_mac = true
+ wifi_ffrt_enable = false
if (defined(global_parts_info) &&
defined(global_parts_info.resourceschedule_efficiency_manager)) {
wifi_feature_with_app_frozen = true

内核编译报错

FAILED: packages/phone/images/bzImage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/tmp/wakemain-89feb8.s: Assembler messages:
/tmp/wakemain-89feb8.s:4: Error: junk at end of line, first unrecognized character is `"'
/tmp/wakemain-89feb8.s:4: Error: file number less than one
/tmp/wakemain-89feb8.s:5: Error: junk at end of line, first unrecognized character is `"'
/tmp/wakemain-89feb8.s:64: Error: junk at end of line, first unrecognized character is `"'
/tmp/wakemain-89feb8.s:282: Error: junk at end of line, first unrecognized character is `"'
/tmp/wakemain-89feb8.s:283: Error: junk at end of line, first unrecognized character is `"'
clang-15: error: assembler command failed with exit code 1 (use -v to see invocation)
make[5]: *** [/home/openharmony/out/KERNEL_OBJ/kernel/src_tmp/linux-5.10/scripts/Makefile.build:294: arch/x86/realmode/rm/wakemain.o] Error 1
make[5]: *** Waiting for unfinished jobs....
/tmp/video-mode-908659.s: Assembler messages:
/tmp/video-mode-908659.s:4: Error: junk at end of line, first unrecognized character is `"'
/tmp/video-mode-908659.s:4: Error: file number less than one
/tmp/video-mode-908659.s:5: Error: junk at end of line, first unrecognized character is `"'
/tmp/video-mode-908659.s:6: Error: junk at end of line, first unrecognized character is `"'
/tmp/video-mode-908659.s:7: Error: junk at end of line, first unrecognized character is `"'
/tmp/video-mode-908659.s:554: Error: junk at end of line, first unrecognized character is `"'
/tmp/video-mode-908659.s:621: Error: junk at end of line, first unrecognized character is `"'
clang-15: error: assembler command failed with exit code 1 (use -v to see invocation)
make[5]: *** [/home/openharmony/out/KERNEL_OBJ/kernel/src_tmp/linux-5.10/scripts/Makefile.build:294: arch/x86/realmode/rm/video-mode.o] Error 1
make[4]: *** [/home/openharmony/out/KERNEL_OBJ/kernel/src_tmp/linux-5.10/arch/x86/realmode/Makefile:23: arch/x86/realmode/rm/realmode.bin] Error 2
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [/home/openharmony/out/KERNEL_OBJ/kernel/src_tmp/linux-5.10/scripts/Makefile.build:537: arch/x86/realmode] Error 2
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [/home/openharmony/out/KERNEL_OBJ/kernel/src_tmp/linux-5.10/Makefile:1850: arch/x86] Error 2
make[2]: *** Waiting for unfinished jobs....
make[2]: Leaving directory '/home/openharmony/out/KERNEL_OBJ/kernel/OBJ/linux-5.10'
make[1]: *** [Makefile:192: __sub-make] Error 2
make[1]: Leaving directory '/home/openharmony/out/KERNEL_OBJ/kernel/src_tmp/linux-5.10'
make: *** [kernel.mk:90: /home/openharmony/out/KERNEL_OBJ/kernel/src_tmp/linux-5.10/arch/x86_64/boot/bzImage] Error 2

解决办法参考issue
修改kernel/linux/build

1
2
3
4
5
6
7
8
9
10
11
12
13
diff --git a/kernel.mk b/kernel.mk
index 5cbda86..f712c38 100644
--- a/kernel.mk
+++ b/kernel.mk
@@ -49,6 +49,8 @@ else ifeq ($(KERNEL_ARCH), riscv64)
else ifeq ($(KERNEL_ARCH), x86_64)
KERNEL_TARGET_TOOLCHAIN := gcc
KERNEL_TARGET_TOOLCHAIN_PREFIX :=
+ KERNEL_CROSS_COMPILE += LLVM=1
+ KERNEL_CROSS_COMPILE += LLVM_IAS=1
endif

ifeq ($(DEVICE_NAME), hispark_phoenix)

顺便,我们参考这个issue,修改一下foundation/distributeddatamgr/kv_store

1
2
3
4
5
6
7
8
9
10
11
12
13
diff --git a/kv_store.gni b/kv_store.gni
index 53071fb..8f68798 100644
--- a/kv_store.gni
+++ b/kv_store.gni
@@ -31,7 +31,7 @@ declare_args() {
dms_service_enable = false
}

- if (product_name != "qemu-arm-linux-min") {
+ if (device_company != "qemu") {
qemu_disable = true
} else {
qemu_disable = false

接下来的构建过程便很顺利了.

构建成功

[OHOS INFO] qemu-x86_64-linux-min build success
镜像已经打包到对应的out目录

1
2
3
$ ls out/qemu-x86_64-linux/packages/phone/images
bzImage ramdisk.img updater.img vendor.img
eng_system.img system.img userdata.img

按照qemu device的文档,执行脚本(需提前安装qemu-system-x86_64)即可运行构建好的镜像.
./vendor/ohemu/qemu_x86_64_linux_min/qemu_run.sh

参考

设备开发