
第一次看到标题里的 openhamony我就知道大概率是把 OpenHarmony 拼顺手了。OpenHarmony 的编译环境搭建网上资料其实不少但多数写得要么太零散要么直接抄官方文档缺了最关键的“为什么”。很多新手照着做环境搭到一半就卡住最后根本不是源码问题而是工具版本不对、磁盘不够、或者仓库没同步完整。这篇文章我打算用一个可复现的完整路径讲清楚 OpenHarmony 下编译 HelloWorld 项目的环境搭建全过程。我会把两种“HelloWorld”的区别先捋明白然后从机器配置、工具链选型、构建工具安装到写工程、跑编译、看产物、排查问题一步步拆开讲。适合刚接触 OpenHarmony、想亲手编译一个可执行文件或应用包的开发者也适合那些已经搭过环境但总在某个环节反复失败的折腾党。1. 先想清楚你要编译的是系统组件还是应用安装包很多人在第一步就走偏了。OpenHarmony 里叫“HelloWorld”的东西至少有两个完全不同的形态一个是编译进系统镜像的 C/C 可执行组件另一个是运行在系统上的 ArkTS/JS 应用安装包也就是 HAP。这两个东西的工具链、源码组织方式、编译入口和产物都不一样。系统组件的典型场景是你从 OpenHarmony 源码树的applications或foundation目录下添加一个小程序最终通过hb工具把它编成一个二进制文件甚至打包进系统镜像。这类 HelloWorld 适合想理解整个 OpenHarmony 构建体系的人也是我这次主要展开的路线。应用安装包则是用户在桌面端开发工具里新建一个工程写一个页面点击构建最后生成一个.hap文件可以安装到开发板上运行。这需要 Node.js、ohpm、hvigor 这一套与系统构建不完全相同的工具对系统源码的依赖反而比较少。两条路线对机器环境的要求区别很大对比项系统组件C/C 可执行文件应用包HAP是否必须下载完整系统源码是否核心构建工具hb、GN、Ninja、Clang/GCChvigor、Node.js、ohpm产物位置镜像目录或指定 bin 目录entry 模块输出目录适合理解的内容OpenHarmony 整体构建关系应用开发和打包流程编译耗时全量编译几小时单目标较快秒级到分钟级我建议初学者先走系统组件这条路。理由很简单它能逼你把 OpenHarmony 的源码结构、构建工具、产品配置和镜像产物关系都过一遍。等这条链路通了再回去做应用开发你会对自己写的 HAP 到底装进系统哪个位置有更清晰的感知。2. 编译环境的硬性条件机器、系统和工具链选型OpenHarmony 是一个大体量项目编译环境不像普通的小工程那样随便装个编译器就能跑。你提前把下面这些条件准备好后面能少踩 90% 的坑。硬件方面编译标准系统镜像的建议门槛是 16GB 内存、8 核 CPU 以上。磁盘至少预留 150GB 空间因为同步源码本身就占 20~30GB编译过程还会产生大量中间文件和多个产品镜像。如果只编译一个 HelloWorld 目标而不做全量镜像占用会小很多但首次配置时我依然建议按全量编译的规格准备磁盘免得构建到一半空间不足。除非你只是想体验轻量系统如小型开发板那种否则我不建议在 Windows 上编译 OpenHarmony 标准系统。官方常规做法是在 Ubuntu 20.04 或 22.04 x86_64 上进行。在 WSL 里跑也不是绝对不行但文件系统映射、符号链接、挂载盘权限这些细节很容易让人头大我自己的结论是老老实实开一个 Ubuntu 虚拟机或者直接用一台原生 Ubuntu 机器最省心。工具链选型这块很多人会纠结要不要手动装 GN、Ninja、Clang。其实 OpenHarmony 源码树里通常已经内置了对应版本的编译工具构建脚本会自动选用你反而不需要手工安装这些。真正需要自己准备的是下面这些工具用途选型要点Python3运行 hb、repo 等脚本建议 3.8 以上且不要用系统默认 Python 直接裸装最好在源码目录的虚拟环境里操作repo同步 OpenHarmony 上千个子仓库一个可执行脚本放在 PATH 目录里Git仓库同步和分支管理常规版本即可GCC/G、make 等编译辅助和部分脚本依赖apt 安装系统基础包即可Node.js、ohpm、hvigor编译 HAP 应用时使用不编译应用包可以先不管这里要解释一个关键点为什么强调版本一致性。OpenHarmony 的各组件之间存在强耦合GN 生成规则、工具链版本、SDK 路径都互相绑定。如果你用主干源码配一个很老的 Python或者用发布分支配一个未来版工具构建脚本就可能在某个深层模块上报错。我的习惯是选定一个发布分支后Python 版本、repo 版本尽量都按该分支文档里的要求锁定而不是盲目追新。3. 逐步搭建编译环境从空 Ubuntu 到能跑 hb 命令环境搭建核心就是三件事装基础依赖、同步源码、安装并初始化 hb。下面我按顺序写命令和步骤都可以直接照做但我会额外说明每个步骤的目的是什么。3.1 先装系统基础依赖打开终端先执行一次系统更新然后安装编译过程中最常用的一批软件包sudo apt update sudo apt upgrade -y sudo apt install -y git curl python3 python3-pip python3-venv \ binutils build-essential gcc g make file lsof sudo这里面的python3-venv是很多新手容易漏掉的。OpenHarmony 构建脚本经常要求把 Python 依赖安装到一个干净的虚拟环境里如果你连 venv 模块都没有后续创建虚拟环境会直接报错。build-essential则是为你本机的 GCC 工具链兜底虽然 OpenHarmony 标准系统会用自己的编译工具但很多辅助脚本仍然依赖系统环境的 gcc 和 make。装完之后最好验证一下 Python 版本python3 --version低于 3.8 的话建议先升级再继续否则后面跑 hb 的时候会遇到语法不兼容的问题。3.2 安装 repo 并同步系统源码repo 本身是一个 Python 脚本。你可以从通用的软件源渠道下载这个工具放到/usr/local/bin/或者~/bin/下面然后给它可执行权限curl -o ~/bin/repo https://commondatastorage.googleapis.com/git-repo-downloads/repo chmod x ~/bin/repo如果你的网络环境访问这个地址不稳定也可以查看自己的 Linux 发行版是否提供了 repo 包或者直接把下载源替换为更可达的镜像。总之最后能执行repo --version就行。同步源码是真正耗时的一步。先建一个专门的源码目录mkdir -p ~/openharmony cd ~/openharmony repo init -u OpenHarmony 代码仓库清单地址 -b 发布分支 repo sync -c -j8-u后面填的是 OpenHarmony 官方开源仓库的 manifest 地址-b填发布分支或标签名。第一次同步时repo sync会拉取数百到上千个子仓库耗时取决于网络情况快则半小时慢则数小时。-c参数表示只同步当前分支能省下不少历史数据新手没必要拉全部分支。同步完成后源码目录里会有applications、foundation、build、vendor、device等一级目录。到这一步你已经把整套系统源码拿到了本地。3.3 安装 hb 构建工具hb 是 OpenHarmony 的构建入口工具。它不是一个独立安装包而是随源码仓库一起提供的常见位置在源码根目录的构建相关目录里。安装方式通常是在源码根目录下执行cd ~/openharmony python3 -m pip install --user build/litebuild/lite是 hb 工具源码所在的位置。安装完成后hb命令默认并不一定能直接使用因为它可能被安装到用户目录的 Python 脚本路径下。你需要在~/.bashrc里把 PATH 补上然后重新加载。export PATH~/.local/bin:$PATH source ~/.bashrc hb version如果你发现python3 -m pip install --user build/lite这种方式提示找不到包可以改在源码根目录下运行官方提供的安装脚本。不同发布分支的 hb 安装入口略有差别但最终目标都是让hb命令可用。3.4 初始化产品选择hb 安装好以后第一次使用要先设置并选择产品目标cd ~/openharmony hb set执行后会出现一个产品列表里面包含不同厂商的开发板和模拟器配置。如果你是刚开始建议选择标准系统的模拟器或默认参考产品而不是直接选某个开发板。选完之后hb 会把对应的产品配置写入本地状态后续hb build默认就能用上。这一步很容易被跳过很多新手直接执行hb build结果系统提示找不到产品配置。hb set本质上就是在告诉构建系统你要为哪个目标设备编译所有后续的模块归属、镜像生成规则都由这个产品决定。4. 编写 HelloWorld 组件并编译出可执行文件环境就绪后我们开始真正动手。下面这个 HelloWorld 是一个 C 语言可执行组件目标是通过 hb 单独构建出来不需要先做一次全量系统镜像。4.1 创建组件目录和源码文件在源码树里新建一个示例组件目录applications/sample/hello/ ├── hello.c └── BUILD.gnhello.c内容很简单#include stdio.h int main() { printf(Hello OpenHarmony!\n); return 0; }这个程序本身没什么可说的关键是BUILD.gn。GN 是 OpenHarmony 使用的构建描述语言它不直接管编译细节而是负责描述“我要生成一个什么样的目标以及它依赖哪些源文件”。我在实际项目里习惯把 GN 文件当成一个配置说明书来读。import(//build/ohos.gni) ohos_executable(hello) { sources [ hello.c ] include_dirs [] install_enable true module_install_dir bin module_install_name hello part_name hello }简单解释一下每个关键字段的含义字段作用ohos_executable生成一个可执行文件目标的 GN 模板sources需要参与编译的源文件列表install_enable是否允许把产物安装到镜像目录module_install_dir安装到镜像中的目录bin表示系统 PATH 可执行文件目录module_install_name安装后文件命名part_name声明这个目标属于哪个部件便于构建系统按部件管理依赖part_name对初学者有一点误导性它不代表你必须先去某个地方注册而是给这个模块一个部件归属名。真正的依赖挂载和镜像集成是在产品配置里完成的。4.2 用 hb 单独构建 HelloWorld 目标我不建议一开始就直接hb build -f做全量编译那会触发几十 GB 的中间产物。更合理的做法是先尝试只构建 HelloWorld 目标cd ~/openharmony hb build -T //applications/sample/hello:hello -f-T是目标过滤参数//applications/sample/hello:hello表示源码树中该路径下名为hello的 GN 目标。-f表示完整构建而不是跳过缓存第一次建议带上。执行后构建系统会先解析 GN 配置再拉起 Ninja 真正执行编译。这个过程的耗时取决于机器性能通常几分钟到十几分钟。如果编译成功终端会显示类似build success的提示。产物一般散落在out/所选产品/目录下因为安装目录被设成了bin所以最直接的验证方式是find out -name hello -type f找到的可执行文件就是 HelloWorld 的编译产物。如果这一步就报错去本篇文章第 6 部分对照排查思路。4.3 让 HelloWorld 随系统镜像一起输出单独构建目标适合快速验证但如果你想在开发板或模拟器启动后直接运行这个程序就需要把它挂到产品配置里。常见的做法是在对应产品的模块配置中增加一个部件声明把part_name注册进目标子系统的依赖列表然后再执行hb build -f这一步会产生完整的系统镜像。不同产品的配置路径不一样通常集中在vendor/厂商/产品/目录下。你需要改的是该产品配置文件中的子系统或部件列表而不是改动任何 GN 源码文件。这也是 OpenHarmony 构建体系里容易让人迷惑的地方模块本身用 GN 描述但模块是否进入最终镜像由产品配置决定。两者缺一不可。5. 编译成功之后检查产物、运行验证和日志观察环境搭得再好最终都要落到“编译出东西、运行起来、看到结果”这三件事上。如果你是走镜像路线完整编译后的镜像文件会在out/所选产品/packages/目录下。根据产品不同可能会生成类似系统镜像、用户态镜像等文件。把镜像烧录到开发板或者用模拟器启动这个具体操作和硬件有关。这里我更想说的是拿到镜像后如何验证 HelloWorld 真的跑起来了。OpenHarmony 系统启动后壳程序和应用日志通常通过hilog输出。你可以在系统串口或远程终端里执行hilog | grep Hello正常情况下应该能在启动阶段看到Hello OpenHarmony!的输出。如果没有先确认可执行文件是否真的被安装到了镜像的bin目录。这比怀疑代码更高效因为很多“编译成功但运行不到”的问题根子都在安装配置上而不是源码逻辑。如果你只是单独构建了目标那可以直接把编译产物手动拷贝到目标系统里执行省去整包烧录的等待。这种方式在开发调试阶段非常常见。开发板一般支持通过特定通道推送文件具体命令和工具因设备而异但思路一致先拿到可执行文件再想办法放到板子上跑起来。还有一点值得提不少初学者把“编译成功”等同于“整个系统正常”。实际上单独构建 HelloWorld 和构建完整系统镜像之间还差着产品集成这一步。我第一次跑通路时也很兴奋但后来发现这只是开始真正需要理解的是模块、部件、产品三层关系它们决定了你的产物最终会出现在镜像的哪个位置。6. 我实际踩过的高频坑从日志反推问题我整理了自己和身边朋友在搭建 OpenHarmony 编译环境时遇到的几个高频问题。每个问题都用一个我从实际排查中总结出来的定位思路而不是只给一个答案。6.1 磁盘不够全量构建中段报警最常见也最容易误判。报错看起来像编译失败但实际是磁盘写满。构建脚本在中途无法创建临时文件或输出文件于是链接阶段各种奇怪报错。排查思路一旦出现“no space left on device”字样或者多个模块相继失败先别急着改代码执行df -h看看根分区和源码分区还剩多少。解决也简单把源码和编译输出放到大分区或者删除out目录下的历史产物重新构建。个人经验120GB 的磁盘真心紧张150GB 以上才比较舒服。6.2 Python 模块安装了但 hb 依然报找不到模块这通常不是真的没装上而是 Python 的 PATH 指向错了。很多人同时用了系统 Python、虚拟环境 Python、用户目录 Python结果 pip 装到了 A 环境hb命令却从 B 环境启动。排查思路先看which python3和which hb分别指向哪里再执行python3 -m pip list | grep 模块名确认模块落在了哪个环境。如果hb命令是通过某个脚本启动的那就去看脚本开头的#!/usr/bin/env python3到底解析到了哪个 Python。解决办法也很简单统一用一个虚拟环境或者把用户 Python 的脚本目录放到 PATH 最前面。6.3 源码同步中断编译时缺文件repo 同步是非常吃网络和磁盘的过程。如果同步不够完整构建系统可能在任何一个模块上报“文件不存在”或“找不到 xxx 目录”。这种报错往往发生在深处你很难一眼看出是源码缺了。排查思路回到源码根目录重新执行一次repo sync -c -j8它会自动补全缺失的文件。如果反复失败先用repo sync -c -j1把并行度调低减少网络拥塞造成的超时。不要相信“上次同步成功了这次就不用再同步”的错觉我至少三次遇到构建到一半发现某个目录是空的。6.4 手滑选错产品编译出一堆用不上的东西hb set里可选产品很多选错之后构建系统会按照那个产品的目标拉取和编译对应模块可能白白编译大量组件。排查思路执行hb set查看当前选择确认它确实是你想用的产品配置再对比实际需要运行的环境。如果只是为了先跑通 HelloWorld选一个内置模拟器或最小参考产品即可没必要一上来就选全功能开发板产品。6.5 编译参数和缓存叠加导致“幽灵报错”重复编译时如果改了源码结构但没有清理缓存构建系统可能仍在使用旧的 GN 解析结果。表现是你明明改对了文件编译却还在报旧路径的错误。排查思路优先执行增量构建比如hb build -T //applications/sample/hello:hello不带-f。如果仍然报错果断清理out目录下的相关中间目录再重建。不要舍不得清理OpenHarmony 构建系统的缓存有时会机智得让人恼火。报错特征可能原因优先排查顺序文件系统空间不足磁盘写满df -h检查分区Python 模块找不到PATH 或虚拟环境混用检查 Python 路径编译中缺文件源码同步不完整重新 repo sync编译出多余内容产品选择错误hb set 查看当前产品改工程后报旧错误GN 缓存未清理清理 out 目录重建7. 老手建议让环境一次搭对别反复重来走过一遍完整流程后我最大的体会是OpenHarmony 的环境搭建本身并不难难的是把各种不确定变量固定下来。这里的变量主要是四个源码分支、Python 版本、产品配置、磁盘空间。四个里面只要有一个在悄悄变化你的排查成本就会成倍上升。我自己的做法是固定一套组合后就不再频繁换分支源码用稳定发布分支Python 用虚拟环境锁死版本产品只选真正要用的那一个磁盘尽量留出冗余。这样做的效果是后续再往系统里加新模块我只是重复“写 GN 配置部件 增量构建”这几步环境层面基本不会再出幺蛾子。最后再分享一个小技巧我会把 Python 的 pip 缓存目录和编译中间目录都指到同一块大容量磁盘上避免默认路径占用系统盘。你在hb构建过程中产生的各种临时文件通常远比你想象的大。提前把这个布局理顺会少很多“编译到一半系统盘满了”的尴尬。环境搭好之后OpenHarmony 的构建体系其实就是一个模块、部件、产品三层结构的组合游戏。HelloWorld 是你在这套体系里的第一个实验对象跑通它后面的路会顺很多。