读懂 README.OpenSource:开源合规里这张「身份证」写了什么?

欢迎大家加入开源鸿蒙跨平台开发者社区

前言

在 OpenHarmony / 鸿蒙生态做 C/C++ 三方库适配 时,仓库里常会看到一个名叫 README.OpenSource 的文件。它看起来是一段 JSON,不像普通 README 那样长篇大论,却是 开源治理与合规 里很常用的一种写法:用结构化数据,把「这个组件是谁的、什么协议、从哪来、当前版本是什么」说清楚。

本文以本仓库 thirdparty/AES/README.OpenSource 为例,逐字段说明含义,并解释为什么同一份文件里会出现 两条记录。读完你可以对照自己项目,检查是否缺项、是否与 HPKBUILD / 上游仓库 一致。


这个文件整体长什么样?

README.OpenSource 的根结构是一个 JSON 数组 [],数组里每一项是一个 对象 {},代表 一个需要声明开源信息的组件

本仓库里放了 两个对象,原因很实际:

  1. 第一条:描述 上游源码(tiny-AES-c)——算法实现本身从哪来、用什么协议。
  2. 第二条:描述 本仓库里的适配与打包部分(HPKBUILD、脚本、文档等)——和上游是 两套版权/协议,分开写更清楚,也避免误以为「整仓都是同一种协议」。

下面分条解读 每个字段 在合规与协作里通常代表什么、本仓库填的是什么。


第一条:上游库 tiny-AES-c

对应文件中的第一个 { ... }

字段名(英文) 通俗含义 本仓库示例值 说明
Name 组件 / 软件的名称 tiny-AES-c 一般与上游项目常用名一致,便于在清单、报表里检索。
License 开源许可证的 SPDX 或社区通用简称 Unlicense 表示上游采用 Unlicense(一种非常宽松、接近「公有领域」的声明)。实际条款以 License File 指向的文本为准。
License File 许可证 全文或官方链接 GitHub 上 unlicense.txt 的链接 方便审核人员 一键打开原文;也可填本仓库内相对路径(若你拷贝了许可证文件)。
Version Number 上游版本号 1.0.0 应对应本次适配所基于的 release / tag(本库与 HPKBUILDpkgver 一致)。
Owner 上游维护主体(组织或个人) kokke 通常填 GitHub/Gitee 上的组织或用户名,表示「谁维护上游」。
Upstream URL 上游 官方源码主页 https://github.com/kokke/tiny-AES-c 溯源用:从哪拉代码、issue/发布从哪看。
Description 简短 功能 + 适配要点 说明 英文一段 用一两句话说明 库做什么;可顺带写 OpenHarmony 侧产物(如静态库名、测试方式),方便读文件的人不用翻 HPKBUILD

一句话记住: 第一条回答的是——「我们用的那套 AES 源码,法律上是谁的、什么协议、哪个版本、从哪下载。」


第二条:本仓库的 HPK 打包与适配部分

对应文件中的第二个 { ... }

字段名(英文) 通俗含义 本仓库示例值 说明
Name 这一「层」组件的名称 AES OpenHarmony HPK packaging 这里不是上游库名,而是 适配层 的名称,表示「lycium HPK 相关脚本与文档」这一包。
License 这一层采用的协议 MIT MIT 很常见:保留版权声明即可再分发、修改,具体以 LICENSE 文件为准。
License File 许可证在哪里 LICENSE 本仓库根目录下的 LICENSE 文件,与 MIT 对应。
Version Number 适配层版本 1.0.0 常与 pkgver / 发布节奏 对齐;若只改脚本不改上游,也可单独递增。
Owner 适配仓库维护方 oh-tpc 与托管地址 oh-tpc/aes 一致,表示 谁在维护这份适配
Upstream URL 这一层代码的 托管地址 https://gitcode.com/oh-tpc/aes 这里填的是 适配仓库本身,方便别人 clone、提 PR。
Description 说明 哪些文件归 MIT、与上游关系 英文一段 明确写清:HPKBUILD、补丁、README、hnp.json 等 用 MIT;tiny-AES-c 上游仍是 Unlicense,避免混淆。

一句话记住: 第二条回答的是——「除了上游源码外,我们写的脚本和文档,谁维护、什么协议、放在哪个仓库。」


常见疑问(帮助理解)

Q:为什么不能只写一条记录?
A:可以只写一条,但本仓库 上游 Unlicense适配 MIT 不同。合成一条容易让人以为「整个仓库只有一种协议」。拆成两条,合规和审计时更清晰。

Q:Namepkgname=AES 为什么不一样?
A:pkgname 是 lycium 目录名 / 构建名;README.OpenSource 第一条 Name 通常跟 上游项目名 一致(tiny-AES-c)。第二条才描述 适配包 本身。各司其职。

Q:字段名必须和表里一模一样吗?
A:在 OpenHarmony 社区 / tpc 常见模板里,字段名会与 README.OpenSource 规范 对齐(如 Name、License、Version Number 等)。换平台时建议 不要改键名,只改值。


总结

  • README.OpenSourceJSON 数组 列出组件的开源信息,是 溯源 + 许可证声明 的精简载体。
  • 每个对象里的字段:Name 是谁、License 什么协议、License File 去哪看全文、Version Number 哪一版、Owner 谁维护、Upstream URL 从哪来、Description 一句话说明(可含适配说明)。
  • 本仓库 两条记录:一条给 上游 tiny-AES-c(Unlicense),一条给 OpenHarmony HPK 适配与打包(MIT),这样 协议边界清楚,也便于后续写材料或审计时直接使用。

若你扩展了补丁、新增依赖或更换上游版本,记得同步改 Version NumberLicense File 链接、Description,并与 HPKBUILD / README_zh.md 保持一致。


实战案例:如何维护 README.OpenSource

案例一:更换上游版本

当上游发布新版本时:

[
  {
    "Name": "tiny-AES-c",
    "License": "Unlicense",
    "License File": "https://github.com/kokke/tiny-AES-c/blob/master/unlicense.txt",
    "Version Number": "1.1.0",  // 更新版本号
    "Owner": "kokke",
    "Upstream URL": "https://github.com/kokke/tiny-AES-c",
    "Description": "Small portable AES128/192/256 in C (updated to v1.1.0)"
  }
]

同步修改:

  1. HPKBUILD 中的 pkgver
  2. hnp.json 中的 version
  3. SHA512SUM 文件
  4. 相关文档中的版本引用

案例二:添加新依赖

如果适配包新增了依赖:

[
  {
    "Name": "AES OpenHarmony HPK packaging",
    "License": "MIT",
    "License File": "LICENSE",
    "Version Number": "1.0.0",
    "Owner": "oh-tpc",
    "Upstream URL": "https://gitcode.com/oh-tpc/aes",
    "Description": "HPK packaging scripts for tiny-AES-c. Depends on zlib for compression support."
  }
]

案例三:许可证变更

如果上游更改了许可证:

[
  {
    "Name": "tiny-AES-c",
    "License": "MIT",  // 从 Unlicense 改为 MIT
    "License File": "https://github.com/kokke/tiny-AES-c/blob/master/LICENSE",
    "Version Number": "2.0.0",
    "Owner": "kokke",
    "Upstream URL": "https://github.com/kokke/tiny-AES-c",
    "Description": "Small portable AES128/192/256 in C. License changed to MIT in v2.0.0"
  }
]

开源合规检查清单

必查项目

  • 许可证文件存在:确认 License File 指向的文件可访问
  • 许可证兼容性:确认上游许可证与适配许可证兼容
  • 版权声明完整:源码中包含正确的版权声明
  • 版本号一致:所有文件中的版本号保持一致
  • 上游链接有效Upstream URL 可正常访问

许可证兼容性矩阵

上游许可证 可用的适配许可证 说明
Unlicense MIT, Apache-2.0, BSD Unlicense 最宽松
MIT MIT, Apache-2.0, BSD MIT 兼容性好
Apache-2.0 Apache-2.0 需保留 NOTICE
GPL-3.0 GPL-3.0 必须使用 GPL-3.0
LGPL-2.1 LGPL-2.1, GPL-3.0 动态链接可保持 LGPL

常见问题与解决方案

Q1: 如何处理多个许可证?

A: 如果上游使用双许可证:

{
  "Name": "library-name",
  "License": "MIT OR Apache-2.0",
  "License File": ["LICENSE-MIT", "LICENSE-APACHE"],
  "Description": "Dual-licensed under MIT or Apache-2.0"
}

Q2: 如何处理许可证冲突?

A: 常见情况:

  • GPL + 闭源:不可行,必须开源
  • Apache-2.0 + GPL-2.0:不兼容
  • MIT + 任意:通常兼容

解决方法:

  1. 咨询法务部门
  2. 选择兼容的许可证组合
  3. 必要时联系上游协商

Q3: 如何验证许可证文件?

A: 使用工具验证:

# 使用 SPDX 工具
spdx-validate LICENSE

# 使用 license-checker
license-checker --json > licenses.json

# 手动比对
diff LICENSE /path/to/upstream/LICENSE

自动化检查

CI/CD 集成

# .github/workflows/license-check.yml
name: License Check

on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Check README.OpenSource
        run: |
          # 验证 JSON 格式
          python -m json.tool README.OpenSource
          
          # 检查必需字段
          python scripts/check_opensource.py
          
      - name: Check License Files
        run: |
          # 检查许可证文件存在
          test -f LICENSE
          
      - name: Check Version Consistency
        run: |
          # 检查版本号一致性
          python scripts/check_versions.py

检查脚本示例

#!/usr/bin/env python3
import json
import sys

def check_readme_opensource():
    with open('README.OpenSource', 'r') as f:
        data = json.load(f)
    
    required_fields = ['Name', 'License', 'Version Number', 'Owner', 'Upstream URL']
    
    for item in data:
        for field in required_fields:
            if field not in item:
                print(f"ERROR: Missing field '{field}' in {item.get('Name', 'unknown')}")
                return False
    
    print("OK: All required fields present")
    return True

if __name__ == '__main__':
    sys.exit(0 if check_readme_opensource() else 1)

与其他文件的同步

版本号同步检查

#!/bin/bash
# check_versions.sh

# 从各文件提取版本号
pkgver=$(grep "^pkgver=" HPKBUILD | cut -d= -f2)
hnp_ver=$(jq -r .version hnp.json)
opensource_ver=$(jq -r '.[0]["Version Number"]' README.OpenSource)

echo "HPKBUILD:    $pkgver"
echo "hnp.json:    $hnp_ver"
echo "OpenSource:  $opensource_ver"

# 检查一致性
if [ "$pkgver" = "$hnp_ver" ] && [ "$hnp_ver" = "$opensource_ver" ]; then
    echo "✓ All versions consistent"
    exit 0
else
    echo "✗ Version mismatch detected"
    exit 1
fi

许可证文件同步

#!/bin/bash
# sync_license.sh

# 从 README.OpenSource 获取许可证文件 URL
license_url=$(jq -r '.[0]["License File"]' README.OpenSource)

# 下载并比对
curl -sL "$license_url" -o /tmp/upstream_license
if diff -q LICENSE /tmp/upstream_license > /dev/null; then
    echo "✓ License file matches upstream"
else
    echo "✗ License file differs from upstream"
    echo "Consider updating LICENSE from upstream"
fi

最佳实践总结

1. 及时更新

  • 上游发布新版本时立即更新
  • 许可证变更时重新评估兼容性
  • 定期检查链接有效性

2. 完整记录

  • 记录所有依赖的开源组件
  • 保留许可证原文
  • 记录许可证选择的原因

3. 自动化验证

  • CI/CD 中集成许可证检查
  • 定期运行合规扫描
  • 生成 SBOM (Software Bill of Materials)

4. 文档化

  • 在 README 中说明许可证信息
  • 记录许可证兼容性分析
  • 保留合规审查记录

扩展阅读

SPDX 标识符

SPDX (Software Package Data Exchange) 是开源许可证的标准标识符:

  • MIT:MIT License
  • Apache-2.0:Apache License 2.0
  • GPL-3.0:GNU General Public License v3.0
  • Unlicense:The Unlicense

完整列表:https://spdx.org/licenses/

合规工具

  • FOSSA:开源合规管理平台
  • Black Duck:开源风险分析
  • Snyk:开源安全与合规
  • license-checker:npm 许可证检查

若你扩展了补丁、新增依赖或更换上游版本,记得同步改 Version NumberLicense File 链接、Description,并与 HPKBUILD / README_zh.md 保持一致。


Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐