1. 概述
本文档记录在 Ubuntu 24.04 上编译 OpenHarmony v6.1-release(SDK 6.1.0.31,API 23)的完整流程,包括环境准备、依赖安装、编译步骤以及遇到的问题与解决方案。
目标产品:RK3568 标准系统(ARM32)
2. 系统环境
| 项目 | 规格 |
|---|---|
| 操作系统 | Ubuntu 24.04 LTS (x86_64) |
| 内核 | Linux 6.17.0 |
| CPU | 24 核 |
| 内存 | 32 GB |
| 磁盘 | 建议 500 GB+ 可用空间 |
| 官方支持版本 | Ubuntu 18.04 / 20.04 / 22.04 |
注意:Ubuntu 24.04 非官方支持版本,需要额外适配(见第 6 节)。
3. APT 依赖安装
3.1 基础编译依赖(官方文档要求)
bash
sudo apt-get install -y \
bison ccache default-jdk flex gcc-arm-linux-gnueabi \
gcc-arm-none-eabi genext2fs liblz4-tool libssl-dev \
mtd-utils mtools openssl ruby scons unzip \
u-boot-tools zip
3.2 额外编译依赖
bash
# autotools(libnl 等第三方库编译需要)
sudo apt-get install -y autoconf automake libtool
# OpenGL / X11 图形库(Skia、graphic_2d 编译需要)
sudo apt-get install -y \
libgl1-mesa-dev libglu1-mesa-dev \
libxcursor-dev libxi-dev
# 镜像生成工具
sudo apt-get install -y genext2fs
3.3 特殊处理:libtinfo5
Ubuntu 24.04 的 libtinfo5 包是假的符号链接(指向 libtinfo6),缺少 NCURSES_TINFO_5 符号。需要从旧版 Ubuntu 手动安装真实的 libtinfo5:
bash
wget http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.4-2_amd64.deb
sudo dpkg -i libtinfo5_6.4-2_amd64.deb
4. 预编译工具链准备
4.1 下载预编译工具链
bash
cd v6.1-release
bash build/prebuilts_download.sh
此脚本会下载 clang-15 工具链、Node.js、hvigor 等到 prebuilts/ 目录。
4.2 两阶段编译策略
RK3568 系统编译依赖 ohos-sdk 中的 toolchains、previewer 等组件。如果 prebuilts/ohos-sdk/linux/23/ 不存在,需要先编译 SDK:
阶段一:编译 SDK
bash
./build.sh --product-name ohos-sdk --ccache
编译产物位于 out/sdk/packages/ohos-sdk/linux/。
阶段二:部署 SDK 到 prebuilts
bash
mkdir -p prebuilts/ohos-sdk/linux/23
# 解压各组件
unzip out/sdk/packages/ohos-sdk/linux/native-linux-x64-*.zip -d prebuilts/ohos-sdk/linux/23/
unzip out/sdk/packages/ohos-sdk/linux/toolchains-linux-x64-*.zip -d prebuilts/ohos-sdk/linux/23/
unzip out/sdk/packages/ohos-sdk/linux/ets-linux-x64-*.zip -d prebuilts/ohos-sdk/linux/23/
unzip out/sdk/packages/ohos-sdk/linux/js-linux-x64-*.zip -d prebuilts/ohos-sdk/linux/23/
unzip out/sdk/packages/ohos-sdk/linux/previewer-linux-x64-*.zip -d prebuilts/ohos-sdk/linux/23/
部署后目录结构:
prebuilts/ohos-sdk/linux/23/
├── ets/
├── js/
├── native/
├── previewer/
└── toolchains/
阶段三:编译 RK3568
bash
./build.sh --product-name rk3568 --ccache
5. 编译产物
成功编译后,镜像输出到:
out/rk3568/packages/phone/images/
6. 遇到的问题与解决方案
6.1 Ubuntu 24.04 版本不支持
错误 :OS version 24.04.4 is not supported for ohos build
原因 :build/scripts/tools_checker.py 中 available_releases 元组未包含 24.04。
修复:
python
# 文件:build/scripts/tools_checker.py
# 修改前:
available_releases = ('18.04', '20.04', '22.04')
# 修改后:
available_releases = ('18.04', '20.04', '22.04', '24.04')
6.2 大量头文件缺少 <cstdint> 包含
错误 :error: 'uint64_t' / 'uint32_t' / 'int32_t' has not been declared
原因 :OpenHarmony 使用的 clang-15 工具链中 libc++ 不再通过其他标准头文件间接包含 <cstdint>。
修复策略 :逐个文件添加 #include <cstdint>(用户明确拒绝全局 force-include 方案)。
需要修改的文件清单:
arkcompiler/ets_runtime/.../maple_util/include/utils.h
arkcompiler/ets_runtime/.../maple_util/include/namemangler.h
arkcompiler/ets_runtime/.../maple_util/include/mpl_logging.h
arkcompiler/toolchain/tooling/dynamic/base/pt_base64.h
arkcompiler/toolchain/tooling/dynamic/utils/utils.h
base/hiviewdfx/hilog/frameworks/libhilog/param/include/properties.h
foundation/arkui/ace_engine/frameworks/bridge/common/utils/module_buffer_reader.h
foundation/arkui/ace_engine/interfaces/inner_api/ace/ace_forward_compatibility.h
foundation/arkui/ace_engine/interfaces/inner_api/ace_kit/include/ui/base/inspector_filter.h
foundation/arkui/ace_engine/interfaces/inner_api/ace_kit/include/ui/base/type_info_base.h
foundation/arkui/ace_engine/adapter/ohos/entrance/ace_new_pipe_judgement.h
foundation/arkui/ace_engine/adapter/preview/entrance/ace_preview_helper.h
foundation/arkui/ace_engine/adapter/ohos/entrance/picker/picker_haptic_factory.h
foundation/arkui/ace_engine/frameworks/base/utils/feature_param.h
foundation/arkui/ace_engine/frameworks/base/log/ace_scoring_log.h
foundation/arkui/ace_engine/frameworks/base/log/jank_frame_report.h
foundation/arkui/ace_engine/frameworks/core/common/ime/text_input_formatter.h
foundation/graphic/graphic_2d/rosen/modules/platform/utils/directory_ex.h
foundation/graphic/graphic_2d/frameworks/text/adapter/skia/common_utils/string_util.h
foundation/graphic/graphic_2d/frameworks/text/service/texgine/.../opentype_basic_type.h
foundation/graphic/graphic_2d/rosen/modules/render_service_base/include/animation/rs_frame_rate_range.h
foundation/graphic/graphic_2d/rosen/modules/render_service_base/include/gfx/dump/rs_dump_manager.h
foundation/graphic/graphic_2d/rosen/modules/render_service_client/core/render_thread/jank_detector/rs_jank_detector.h
ide/tools/previewer/util/FileSystem.h
ide/tools/previewer/util/CommandParser.h
ide/tools/previewer/util/PublicMethods.h
ide/tools/previewer/jsapp/rich/external/StageContext.h
third_party/icu/icu4c/source/ohos/lunar_calendar.h
6.3 缺少 <string> 头文件
错误 :error: 'std::string' has not been declared
修复文件:
third_party/skia/m133/src/gpu/ganesh/GrPerfMonitorReporter.h --- 添加 #include <string>
foundation/arkui/ace_engine/frameworks/core/common/multi_thread_build_manager.h --- 添加 #include <string>
foundation/graphic/graphic_2d/rosen/modules/render_service_client/core/render_thread/jank_detector/rs_jank_detector.h --- 添加 #include <string>
6.4 缺少 <cstdlib> 头文件
错误 :error: 'std::malloc' / 'std::free' has not been declared
修复:
developtools/hdc/src/common/memory_pool.cpp --- 添加 #include <cstdlib>
6.5 默认参数 const 引用问题
错误 :error: default argument for parameter of type 'const std::string &' has type 'const char *'
修复:
cpp
// 文件:foundation/arkui/ace_engine/adapter/ohos/entrance/picker/picker_haptic_factory.h
// 修改前:
const std::string& uri = ""
// 修改后:
const std::string& uri = std::string()
6.6 StageContext.h const 返回值问题
错误 :warning: 'const' type qualifier on return type has no effect(-Werror 导致编译失败)
修复:
cpp
// 文件:ide/tools/previewer/jsapp/rich/external/StageContext.h
// 修改前:
const std::string ReadFileContents(const std::string& filePath);
// 修改后:
std::string ReadFileContents(const std::string& filePath);
同步修改对应 .cpp 文件。
6.7 Hvigor 找不到 SDK 组件
错误 :Unable to find the following components: toolchains:23 或 previewer:23
原因 :HAP 应用编译(hvigor)需要完整的 ohos-sdk 部署在 prebuilts/ohos-sdk/linux/23/。
修复:按照第 4.2 节部署所有 SDK 组件(native、toolchains、ets、js、previewer)。
6.8 npm install 失败(cb() never called)
错误 :npm ERR! cb() never called!(npm 6.14.17 的已知 bug)
修复:手动进入对应目录重新执行 npm install:
bash
cd <出错的目录>
../../prebuilts/build-tools/common/nodejs/node-v18.20.1-linux-x64/bin/npm install
6.9 libtinfo5 符号缺失
错误 :version 'NCURSES_TINFO_5' not found
原因:Ubuntu 24.04 的 libtinfo5 包实际是 libtinfo6 的符号链接,缺少旧版 ABI 符号。
修复:从 Ubuntu 22.04 归档安装真实的 libtinfo5(见第 3.3 节)。
6.10 构建进程被意外终止
现象:ninja 编译中途停止,无错误日志,进程消失。
原因:通过 CLI 工具启动的后台进程可能因 shell 超时被 kill。
修复 :使用 nohup + disown 或直接在独立终端中运行:
bash
cd v6.1-release
nohup ./build.sh --product-name rk3568 --ccache > /tmp/rk3568_build.log 2>&1 &
disown
7. 编译耗时参考
| 阶段 | 耗时(24核/32GB) |
|---|---|
| prebuilts_download.sh | ~10 分钟(取决于网速) |
| ohos-sdk 编译 | ~1.5 小时 |
| GN 配置(rk3568) | ~2-3 分钟 |
| Ninja 编译(rk3568,全量) | ~1-2 小时 |
| Ninja 编译(rk3568,增量) | 视改动范围而定 |
8. 常用调试命令
bash
# 查看编译进度
tail -f out/rk3568/build.log
# 查看编译错误
cat out/rk3568/error.log
# 检查编译进程是否存活
pgrep -af "ninja.*rk3568"
pgrep -af "build\.sh.*rk3568"
# 仅执行 GN 解析(不编译)
./build.sh --product-name rk3568 --build-only-gn
# 编译指定目标
./build.sh --product-name rk3568 -T <gn_target>
9. 独立编译:内核、部件与应用
全量编译耗时数小时,开发调试时通常只需编译改动的部分。build.sh 的 -T 参数支持指定 GN 目标进行独立编译。
9.1 -T 参数语法
bash
./build.sh --product-name rk3568 -T <GN目标路径>
GN 目标路径格式
<BUILD.gn所在目录>:<目标名>
| 部分 | 说明 | 示例 |
|---|---|---|
| 目录路径 | BUILD.gn 所在目录,相对于源码根目录 | device/board/hihope/rk3568/kernel |
: |
分隔符 | : |
| 目标名 | BUILD.gn 中定义的 target 名称 | kernel |
注意 :命令行
-T中不带 开头的//。//是 GN 文件内部语法(如import("//build/ohos.gni")),命令行中要省略。
多目标编译
可多次使用 -T 编译多个目标:
bash
./build.sh --product-name rk3568 \
-T kernel/linux/build:linux_kernel \
-T applications/sample/hello_world:hello_world
9.2 独立编译内核
内核 GN 目标
内核构建配置位于 kernel/linux/build/BUILD.gn,定义了以下目标链:
group("linux_kernel")
└── action("build_kernel") ← 执行 build_kernel.sh 脚本
└── action("check_build") ← 检查内核源码是否有变更
编译命令
bash
cd v6.1-release
./build.sh --product-name rk3568 -T device/board/hihope/rk3568/kernel:kernel
产物位置
| 产物 | 路径 |
|---|---|
| 内核镜像(ARM) | out/rk3568/packages/phone/images/uImage |
| 内核目标文件 | out/rk3568/../KERNEL_OBJ/ |
不同架构的内核镜像名
| target_cpu | 镜像文件名 |
|---|---|
arm |
uImage |
arm64 |
Image |
x86_64 |
bzImage |
riscv64 |
Image |
9.3 独立编译部件(Component)
查找部件的 GN 目标
每个部件的构建目标在其 bundle.json 的 component.build.sub_component 中声明。
步骤:
bash
# 1. 找到部件的 bundle.json
find . -path "*/部件目录/bundle.json"
# 2. 查看其 sub_component 字段
python3 -c "
import json
d = json.load(open('路径/bundle.json'))
for t in d['component']['build']['sub_component']:
print(t)
"
通用编译命令
bash
./build.sh --product-name rk3568 -T <sub_component中的路径(去掉开头//)>
常用部件编译示例
| 部件 | 编译命令 |
|---|---|
| hilog(日志) | ./build.sh --product-name rk3568 -T base/hiviewdfx/hilog:libhilog |
| c_utils(公共库) | ./build.sh --product-name rk3568 -T commonlibrary/c_utils/base:utils |
| samgr(系统服务管理) | ./build.sh --product-name rk3568 -T foundation/systemabilitymgr/samgr/services/samgr/native:samgr |
| hdc(调试工具) | ./build.sh --product-name rk3568 -T developtools/hdc/src:hdc |
| syscap_codec | ./build.sh --product-name rk3568 -T developtools/syscap_codec:syscap_tool_bin |
部件编译前提
部件必须已在产品配置中注册(vendor/hihope/rk3568/config.json 或其 inherit 文件),否则 GN 解析时会报 "component not found"。
如何确认一个部件是否已注册
bash
# 搜索 rk3568 config.json 及其继承的配置文件
python3 -c "
import json
files = [
'vendor/hihope/rk3568/config.json',
'productdefine/common/inherit/rich.json',
'productdefine/common/inherit/chipset_common.json',
]
target = '要查找的部件名'
for f in files:
try:
d = json.load(open(f))
for s in d.get('subsystems', []):
for c in s.get('components', []):
if c.get('component') == target:
print(f'Found in {f} under subsystem: {s[\"subsystem\"]}')
except: pass
"
9.4 独立编译应用(Application)
Native C 可执行程序
以 applications/sample/hello_world 为例:
bash
./build.sh --product-name rk3568 -T applications/sample/hello_world:hello_world
产物路径:out/rk3568/applications/sample/hello_world/hello_world
HAP 应用
HAP 应用通常由 hvigor 构建,GN 中通过 ohos_hap 模板定义。编译方式相同:
bash
# 示例:编译 Settings 应用
./build.sh --product-name rk3568 -T applications/standard/settings:settings_hap
注意 :HAP 编译需要 ohos-sdk 已部署到
prebuilts/ohos-sdk/linux/23/(见第 4.2 节)。
自定义应用的完整流程
bash
# 1. 创建源码目录
mkdir -p applications/sample/my_app
# 2. 编写 hello_world.c、BUILD.gn、bundle.json(参考第 10 节示例)
# 3. 注册到产品配置
# 在 vendor/hihope/rk3568/config.json 的 subsystems 中添加部件
# 4. 编译
./build.sh --product-name rk3568 -T applications/sample/my_app:my_app
# 5. 部署到设备
hdc file send out/rk3568/applications/sample/my_app/my_app /data/local/tmp/
hdc shell chmod +x /data/local/tmp/my_app
hdc shell /data/local/tmp/my_app
9.5 编译产物目录结构
out/rk3568/
├── packages/phone/images/ # 最终烧录镜像
│ ├── uImage # 内核镜像
│ ├── system.img # system 分区
│ ├── vendor.img # vendor 分区
│ └── userdata.img # 用户数据分区
├── packages/phone/system/bin/ # install_enable=true 的可执行文件
├── applications/ # 应用编译中间产物
├── kernel/ # 内核编译中间产物
└── obj/ # 所有模块的 .o 文件
9.6 常用编译选项完整参考
| 选项 | 说明 |
|---|---|
--product-name <name> |
必选,指定产品(rk3568、ohos-sdk 等) |
-T <target> |
编译指定 GN 目标,可多次使用 |
--ccache |
启用编译缓存,显著加速增量编译 |
--ninja-args=-j8 |
并行编译线程数 |
--gn-args="key=value" |
传递额外 GN 变量 |
--build-only-gn |
仅执行 GN 解析,不运行 Ninja(用于检查语法错误) |
--target-cpu <cpu> |
覆盖目标 CPU 架构(arm、arm64、x86_64) |
--compile-config <path> |
指定自定义编译配置文件 |
9.7 快速排错
| 错误信息 | 原因 | 解决 |
|---|---|---|
unknown target 'xxx' |
-T 路径格式错误 |
检查路径不带 // 开头,确认 BUILD.gn 中目标名正确 |
component xxx not found |
部件未注册到产品配置 | 在 config.json 中添加该部件 |
part_name must be defined |
BUILD.gn 缺少 part_name | 添加 part_name = "xxx" |
subsystem xxx not found |
subsystem_config.json 中无此子系统 | 检查拼写或添加子系统注册 |
Unable to find components: toolchains:23 |
ohos-sdk 未部署 | 按第 4.2 节部署 SDK |
10. 完整示例:Hello World Native C 应用
10.1 文件结构
applications/sample/hello_world/
├── BUILD.gn
├── bundle.json
└── hello_world.c
10.2 hello_world.c
c
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
return 0;
}
10.3 BUILD.gn
gn
import("//build/ohos.gni")
ohos_executable("hello_world") {
sources = [ "hello_world.c" ]
subsystem_name = "applications"
part_name = "hello_world"
install_enable = true
}
10.4 bundle.json
json
{
"name": "@ohos/hello_world",
"description": "Hello World sample executable",
"version": "1.0.0",
"license": "Apache License 2.0",
"publishAs": "code-segment",
"segment": {
"destPath": "applications/sample/hello_world"
},
"dirs": {},
"scripts": {},
"component": {
"name": "hello_world",
"subsystem": "applications",
"syscap": [],
"features": [],
"adapted_system_type": ["standard"],
"rom": "",
"ram": "",
"deps": {
"components": [],
"third_party": []
},
"build": {
"sub_component": [
"//applications/sample/hello_world:hello_world"
],
"inner_kits": [],
"test": []
}
}
}
10.5 产品配置注册
在 vendor/hihope/rk3568/config.json 的 subsystems 数组中添加:
json
{
"subsystem": "applications",
"components": [
{
"component": "hello_world",
"features": []
}
]
}
10.6 编译与运行
bash
# 编译
cd v6.1-release
./build.sh --product-name rk3568 -T applications/sample/hello_world:hello_world
# 推送到设备
hdc file send out/rk3568/applications/sample/hello_world/hello_world /data/local/tmp/
hdc shell chmod +x /data/local/tmp/hello_world
hdc shell /data/local/tmp/hello_world
# 输出:Hello World
11. 总结
在 Ubuntu 24.04 上编译 OpenHarmony v6.1-release 的主要挑战:
- 系统版本适配 :需修改
tools_checker.py添加 24.04 支持 - C++ 标准库变化 :clang-15 的 libc++ 不再隐式包含
<cstdint>,需逐文件修复(25+ 个文件) - 两阶段编译:RK3568 依赖 ohos-sdk,需先编译 SDK 并部署到 prebuilts 目录
- libtinfo5 兼容性:需要从旧版 Ubuntu 安装真实的 libtinfo5 包
- 长时间编译 :全量编译约 3-4 小时,建议在独立终端中运行并使用
disown
开发调试时优先使用 -T 参数进行独立编译,避免全量编译的等待。