HarmonyOS开发:OpenHarmony社区——源码结构与贡献指南

举报
Jack20 发表于 2026/06/28 21:14:57 2026/06/28
【摘要】 HarmonyOS开发:OpenHarmony社区——源码结构与贡献指南📌 核心要点:搞懂OpenHarmony源码结构是参与社区贡献的前提,从clone代码到提交PR,这条路没有你想的那么难走。 背景与动机你用HarmonyOS开发应用,写了不少ArkTS代码,有一天突然想:这系统底层到底长什么样?能不能自己改一改?然后你打开了OpenHarmony的gitee仓库,一看——好家伙,几...

HarmonyOS开发:OpenHarmony社区——源码结构与贡献指南

📌 核心要点:搞懂OpenHarmony源码结构是参与社区贡献的前提,从clone代码到提交PR,这条路没有你想的那么难走。

背景与动机

你用HarmonyOS开发应用,写了不少ArkTS代码,有一天突然想:这系统底层到底长什么样?能不能自己改一改?

然后你打开了OpenHarmony的gitee仓库,一看——好家伙,几百个仓库,几十万行代码,连README都长得像论文。你关了浏览器,心想算了算了。

这反应太正常了。OpenHarmony的源码体系确实庞大,但它不是一团乱麻,而是有清晰的分层和组织逻辑的。你之所以觉得乱,是因为还没找到那根"线头"。

这篇文章,我帮你把这根线头拽出来。从源码结构到编译构建,从社区贡献流程到SIG组织参与,一条线串起来。看完之后,你至少知道往哪个方向走,不会再在仓库首页发呆了。

核心原理

OpenHarmony源码全景

OpenHarmony不是一个大仓库,而是一个仓库集合。每个子系统有独立仓库,通过repo工具统一管理。这跟Android的AOSP用repo管理多仓库是一个思路。

graph TB
    A[OpenHarmony 源码体系] --> B[内核层 kernel]
    A --> C[系统服务层 system]
    A --> D[框架层 arkui]
    A --> E[应用层 apps]
    A --> F[编译构建 build]
    A --> G[测试 testing]
    A --> H[驱动框架 drivers]

    B --> B1[linux_kernel]
    B --> B2[liteos_m]
    B --> B3[liteos_a]

    C --> C1[abilitymgr]
    C --> C2[bundlemgr]
    C --> C3[accountmgr]
    C --> C4[communication]

    D --> D1[arkui_ace_engine]
    D --> D2[arkcompiler]
    D --> D3[ability_runtime]

    E --> E1[launcher]
    E --> E2[settings]
    E --> E3[camera]

    classDef root fill:#E91E63,stroke:#880E4F,color:#fff
    classDef layer fill:#2196F3,stroke:#1565C0,color:#fff
    classDef component fill:#4CAF50,stroke:#2E7D32,color:#fff

    class A root
    class B,C,D,E,F,G,H layer
    class B1,B2,B3,C1,C2,C3,C4,D1,D2,D3,E1,E2,E3 component

四层架构与仓库映射

OpenHarmony的架构分四层,每层对应一组仓库:

层级 职责 核心仓库 你会接触的频率
内核层 操作系统内核 kernel_linux_5.10, kernel_liteos_a 低(除非做驱动)
系统服务层 系统基础服务 abilitymgr_runtime, bundle_framework 中(改系统行为时)
框架层 UI框架与编译器 arkui_ace_engine, arkcompiler_toolchain 高(写应用经常查源码)
应用层 系统应用 apps_launcher, apps_settings 高(参考系统应用实现)

关键目录结构

当你用repo拉下完整源码后,根目录长这样:

openharmony/
├── applications/        # 系统应用(Launcher、Settings等)
├── ark/                 # ArkCompiler编译器
├── base/                # 系统基础服务
│   ├── account/         # 账号管理
│   ├── communication/   # 通信服务(蓝牙、WiFi等)
│   ├── location/        # 定位服务
│   └── ...
├── build/               # 编译构建脚本
├── drivers/             # 驱动框架
├── foundation/          # 核心基础能力
│   ├── arkui/           # ArkUI引擎
│   ├── ability/         # Ability运行时
│   └── ...
├── kernel/              # 内核
├── out/                 # 编译输出
├── test/                # 测试框架
├── third_party/         # 三方库
└── vendor/              # 厂商配置

你不用记住每个目录,但你需要知道:改UI框架去foundation/arkui,改系统服务去base/,改系统应用去applications/

编译构建体系

OpenHarmony用GN + Ninja做构建。GN负责生成构建配置,Ninja负责实际编译。整个流程:

graph LR
    A[repo sync 拉取源码] --> B[./build.sh --product-name <产品名>]
    B --> C[GN生成Ninja文件]
    C --> D[Ninja编译]
    D --> E[输出镜像到out/目录]
    E --> F[烧录到设备]

    classDef step fill:#FF9800,stroke:#E65100,color:#fff
    classDef output fill:#4CAF50,stroke:#2E7D32,color:#fff

    class A,B,C,D step
    class E,F output

编译命令很简单,但选对产品名是关键:

# 编译标准系统(手机/平板)
./build.sh --product-name rk3568

# 编译小型系统(IoT设备)
./build.sh --product-name hi3861

# 编译迷你系统(穿戴设备)
./build.sh --product-name hi3516dv300

SIG组织架构

SIG(Special Interest Group)是OpenHarmony社区的组织形式。每个SIG负责一个技术方向,有独立的维护者和贡献者。

SIG名称 负责方向 活跃度
sig-arkui ArkUI框架 ⭐⭐⭐⭐⭐
sig-compiler 编译器与运行时 ⭐⭐⭐⭐
sig-application 应用框架 ⭐⭐⭐⭐
sig-distributedhw 分布式硬件 ⭐⭐⭐
sig-security 安全 ⭐⭐⭐
sig-drivers 驱动框架 ⭐⭐

代码实战

基础用法:拉取源码与首次编译

第一步,你得把代码拉下来。别用git clone一个个拉,OpenHarmony有几百个仓库,你clone到猴年马月?用repo工具。

// 这不是ArkTS代码,是shell脚本,用于拉取和编译OpenHarmony源码
// 1. 安装repo工具
// curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > ~/bin/repo
// chmod a+x ~/bin/repo

// 2. 初始化仓库(以master分支为例)
// mkdir openharmony && cd openharmony
// repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify

// 3. 拉取源码
// repo sync -c

// 4. 首次编译(RK3568开发板)
// ./build.sh --product-name rk3568 -ccache

// 5. 查看编译输出
// ls out/rk3568/packages/phone/images/

首次编译时间很长,快的也要一两个小时,慢的四五个小时都有。别急,去喝杯咖啡。

进阶用法:贡献代码的完整流程

光拉代码不够,你得会提交贡献。OpenHarmony的贡献流程遵循标准的开源社区模式:Fork → 修改 → PR → Review → Merge。

// 贡献流程示例:修复ArkUI的一个Bug
// 
// 步骤1:在Gitee上Fork目标仓库
// 比如你要修改arkui_ace_engine,先Fork到自己的仓库
//
// 步骤2:添加你的Fork为远程仓库
// git remote add myfork https://gitee.com/你的用户名/arkui_ace_engine.git
//
// 步骤3:创建特性分支
// git checkout -b fix/issue-12345-text-overflow
//
// 步骤4:修改代码并提交
// git add .
// git commit -s -m "fix: 修复Text组件overflow属性在特定场景下失效的问题"
// 注意:-s 参数会自动添加 Signed-off-by 行,这是DCO要求
//
// 步骤5:推送到你的Fork
// git push myfork fix/issue-12345-text-overflow
//
// 步骤6:在Gitee上创建Pull Request
// 目标:openharmony/arkui_ace_engine 的 master 分支
// 来源:你的 fix/issue-12345-text-overflow 分支
//
// 步骤7:等待Review
// 维护者会审查你的代码,可能提出修改意见
// 根据意见修改后,追加提交即可

完整示例:自动化贡献检查工具

手动走贡献流程容易出错——忘了sign-off、commit message格式不对、没跑测试……写个脚本把这些检查自动化。

// ContributionChecker.ets - 贡献前自动检查工具
import { exec } from '@ohos.child_process';

interface CheckResult {
  passed: boolean;
  message: string;
}

export class ContributionChecker {
  private projectPath: string;
  
  constructor(projectPath: string) {
    this.projectPath = projectPath;
  }

  // 执行所有检查
  async runAllChecks(): Promise<CheckResult[]> {
    const results: CheckResult[] = [];
    
    results.push(await this.checkGitStatus());
    results.push(await this.checkCommitMessage());
    results.push(await this.checkSignedOff());
    results.push(await this.checkLicenseHeader());
    results.push(await this.checkBuildPass());
    
    return results;
  }

  // 检查1:确认工作区干净
  async checkGitStatus(): Promise<CheckResult> {
    try {
      const result = await this.execCommand('git status --porcelain');
      if (result.trim().length > 0) {
        return {
          passed: false,
          message: '❌ 工作区有未提交的修改,请先提交或暂存'
        };
      }
      return { passed: true, message: '✅ 工作区干净' };
    } catch (err) {
      return { passed: false, message: `❌ Git状态检查失败: ${err}` };
    }
  }

  // 检查2:commit message格式
  async checkCommitMessage(): Promise<CheckResult> {
    try {
      const result = await this.execCommand('git log -1 --format=%s');
      const subject = result.trim();
      
      // OpenHarmony要求的格式:type: 描述
      const validPrefixes = ['feat:', 'fix:', 'docs:', 'style:', 'refactor:', 
                             'test:', 'chore:', 'revert:'];
      const hasValidPrefix = validPrefixes.some(prefix => subject.startsWith(prefix));
      
      if (!hasValidPrefix) {
        return {
          passed: false,
          message: `❌ Commit message格式不对: "${subject}"\n   应以 feat:/fix:/docs: 等前缀开头`
        };
      }

      if (subject.length > 72) {
        return {
          passed: false,
          message: `❌ Commit message太长(${subject.length}字符),建议不超过72字符`
        };
      }
      
      return { passed: true, message: `✅ Commit message格式正确: "${subject}"` };
    } catch (err) {
      return { passed: false, message: `❌ Commit message检查失败: ${err}` };
    }
  }

  // 检查3:Signed-off-by(DCO要求)
  async checkSignedOff(): Promise<CheckResult> {
    try {
      const result = await this.execCommand('git log -1 --format=%B');
      const body = result.trim();
      
      if (!body.includes('Signed-off-by:')) {
        return {
          passed: false,
          message: '❌ 缺少Signed-off-by行,提交时请使用 -s 参数'
        };
      }
      return { passed: true, message: '✅ Signed-off-by检查通过' };
    } catch (err) {
      return { passed: false, message: `❌ Signed-off-by检查失败: ${err}` };
    }
  }

  // 检查4:文件头License声明
  async checkLicenseHeader(): Promise<CheckResult> {
    try {
      // 查找修改的文件列表
      const diffResult = await this.execCommand('git diff --name-only HEAD~1');
      const files = diffResult.trim().split('\n').filter(f => f.length > 0);
      
      const ohosLicense = 'Copyright (c) 2024 Huawei Device Co., Ltd.';
      let missingFiles: string[] = [];
      
      for (const file of files) {
        // 只检查.ts/.ets/.cpp/.h文件
        if (/\.(ts|ets|cpp|h)$/.test(file)) {
          const catResult = await this.execCommand(`head -5 ${file}`);
          if (!catResult.includes(ohosLicense) && !catResult.includes('Copyright')) {
            missingFiles.push(file);
          }
        }
      }
      
      if (missingFiles.length > 0) {
        return {
          passed: false,
          message: `❌ 以下文件缺少License头:\n   ${missingFiles.join('\n   ')}`
        };
      }
      return { passed: true, message: '✅ License头检查通过' };
    } catch (err) {
      return { passed: false, message: `❌ License检查失败: ${err}` };
    }
  }

  // 检查5:编译是否通过
  async checkBuildPass(): Promise<CheckResult> {
    try {
      // 只做增量编译检查
      const result = await this.execCommand(
        './build.sh --product-name rk3568 --build-target arkui_ace_engine 2>&1 | tail -5'
      );
      
      if (result.includes('FAILED')) {
        return { passed: false, message: '❌ 编译未通过,请修复编译错误' };
      }
      return { passed: true, message: '✅ 编译检查通过' };
    } catch (err) {
      return { 
        passed: true, 
        message: '⚠️ 跳过编译检查(可能不在源码根目录)' 
      };
    }
  }

  // 执行命令的辅助方法
  private execCommand(cmd: string): Promise<string> {
    return new Promise((resolve, reject) => {
      exec(cmd, { cwd: this.projectPath }, (err, stdout) => {
        if (err) reject(err);
        else resolve(stdout);
      });
    });
  }
}

// 使用示例
async function main() {
  const checker = new ContributionChecker('/path/to/openharmony');
  const results = await checker.runAllChecks();
  
  console.log('===== 贡献检查报告 =====');
  let allPassed = true;
  for (const result of results) {
    console.log(result.message);
    if (!result.passed) allPassed = false;
  }
  
  if (allPassed) {
    console.log('\n🎉 所有检查通过,可以提交PR了!');
  } else {
    console.log('\n⚠️ 存在未通过的检查,请修复后再提交');
  }
}

踩坑与注意事项

坑1:repo sync失败

这是新手最常遇到的问题。几百个仓库,总有一个会超时。

解法:加-j1参数,单线程拉取。慢是慢了点,但稳定:

repo sync -c -j1

如果某个仓库反复失败,单独拉它:

repo sync -c kernel_linux_5.10

坑2:编译依赖缺失

首次编译报错"xxx not found",大概率是依赖没装全。OpenHarmony的编译依赖列表很长,官方文档有,但容易漏。

关键依赖(Ubuntu环境):

sudo apt-get install gcc g++ make zlib1g-dev libffi-dev \
  libssl-dev python3 python3-pip flex bison
pip3 install pyyaml

坑3:PR被拒——DCO检查失败

OpenHarmony社区要求所有提交都带Signed-off-by行,这是DCO(Developer Certificate of Origin)的要求。你忘了加这个,PR直接被CI拦截。

解法:提交时加-s参数:

git commit -s -m "fix: 修复xxx问题"

坑4:commit message格式不对

OpenHarmony对commit message有严格要求,格式必须是:

<type>: <subject>

<body>

< trailers >

type只能是这几个:featfixdocsstylerefactortestchorerevert。你写个"update"或"修改bug",直接打回。

坑5:找不到对应的SIG

你想贡献代码,但不知道该找哪个SIG。这很常见,因为有些仓库的归属不太明显。

解法:看仓库的OWNERS文件。每个仓库根目录都有这个文件,里面列出了维护者。你给维护者发邮件或在Gitee上@他,比漫无目的地在社区里问效率高得多。

坑6:编译时间过长

全量编译动辄几小时,改一行代码等几小时,谁受得了?

解法:用增量编译。只编译你修改的模块:

# 只编译ArkUI引擎
./build.sh --product-name rk3568 --build-target arkui_ace_engine

# 只编译某个测试
./build.sh --product-name rk3568 --build-target ace_engine_unittest

HarmonyOS 6适配说明

HarmonyOS 6基于OpenHarmony 5.x,有几个重要变化:

  1. 构建系统升级:从GN逐步迁移到hvigor构建体系,部分模块的构建配置文件格式变了。如果你之前改过BUILD.gn,需要检查是否需要适配hvigorfile.ts

  2. ArkUI引擎重构:ACE引擎的部分C++接口做了调整,如果你贡献过ArkUI底层代码,需要关注API变更。

  3. CI流程更新:社区CI新增了静态分析步骤,对代码规范的要求更严格了。以前能过的PR,现在可能被拦截。

  4. 新增SIG:HarmonyOS 6引入了AI能力框架,对应新增了sig-ai_framework。如果你对端侧AI感兴趣,这是个好的切入点。

总结

OpenHarmony的源码体系和贡献流程,看着吓人,其实就那几步:拉代码、找模块、改代码、提PR。难的不是技术,是你第一次打开那个几百个仓库的页面时,不知道从哪下手。

维度 评价
学习难度 ⭐⭐⭐⭐ 源码量大,需要耐心摸索
使用频率 ⭐⭐⭐ 做系统级开发时经常需要
重要程度 ⭐⭐⭐⭐⭐ 深入理解系统的必经之路

几个关键建议:

  • 从应用层入手:别一上来就啃内核,先从applications/目录的系统应用开始,这些代码量小、逻辑清晰,容易上手。
  • 先修Bug再提Feature:社区更信任修过Bug的人。你在Issue列表里找一个简单Bug修了,比直接提一个大Feature更容易被接受。
  • 多看别人的PR:看别人怎么写的commit message、怎么组织代码的、Review意见是什么。这是最快的学习方式。
  • 加入SIG的例会:大部分SIG都有定期线上会议,参加一次比看十篇文档管用。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。