读懂README.OpenSource:开源合规里这张「身份证」写了什么?
欢迎大家加入开源鸿蒙跨平台开发者社区
前言
在 OpenHarmony / 鸿蒙生态做C/C++ 三方库适配时,仓库里常会看到一个名叫README.OpenSource的文件。它看起来是一段JSON,不像普通 README 那样长篇大论,却是开源治理与合规里很常用的一种写法:用结构化数据,把「这个组件是谁的、什么协议、从哪来、当前版本是什么」说清楚。
本文以本仓库thirdparty/AES/README.OpenSource为例,逐字段说明含义,并解释为什么同一份文件里会出现两条记录。读完你可以对照自己项目,检查是否缺项、是否与HPKBUILD/ 上游仓库一致。
这个文件整体长什么样?
README.OpenSource的根结构是一个JSON 数组[],数组里每一项是一个对象{},代表一个需要声明开源信息的组件。
本仓库里放了两个对象,原因很实际:
- 第一条:描述上游源码(tiny-AES-c)——算法实现本身从哪来、用什么协议。
- 第二条:描述本仓库里的适配与打包部分(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(本库与HPKBUILD里pkgver一致)。 |
| 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:Name和pkgname=AES为什么不一样?
A:pkgname是 lycium 目录名 / 构建名;README.OpenSource第一条 Name通常跟上游项目名一致(tiny-AES-c)。第二条才描述适配包本身。各司其职。
Q:字段名必须和表里一模一样吗?
A:在 OpenHarmony 社区 / tpc 常见模板里,字段名会与README.OpenSource规范对齐(如Name、License、Version Number等)。换平台时建议不要改键名,只改值。
总结
README.OpenSource用JSON 数组列出组件的开源信息,是溯源 + 许可证声明的精简载体。- 每个对象里的字段:Name是谁、License什么协议、License File去哪看全文、Version Number哪一版、Owner谁维护、Upstream URL从哪来、Description一句话说明(可含适配说明)。
- 本仓库两条记录:一条给上游 tiny-AES-c(Unlicense),一条给OpenHarmony HPK 适配与打包(MIT),这样协议边界清楚,也便于后续写材料或审计时直接使用。
若你扩展了补丁、新增依赖或更换上游版本,记得同步改Version Number、License 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)"}]同步修改:
HPKBUILD中的pkgverhnp.json中的versionSHA512SUM文件- 相关文档中的版本引用
案例二:添加新依赖
如果适配包新增了依赖:
[{"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 + 任意:通常兼容
解决方法:
- 咨询法务部门
- 选择兼容的许可证组合
- 必要时联系上游协商
Q3: 如何验证许可证文件?
A:使用工具验证:
# 使用 SPDX 工具spdx-validate LICENSE# 使用 license-checkerlicense-checker--json>licenses.json# 手动比对diffLICENSE /path/to/upstream/LICENSE自动化检查
CI/CD 集成
# .github/workflows/license-check.ymlname:License Checkon:[push,pull_request]jobs:check:runs-on:ubuntu-lateststeps:-uses:actions/checkout@v2-name:Check README.OpenSourcerun:|# 验证 JSON 格式 python -m json.tool README.OpenSource# 检查必需字段python scripts/check_opensource.py-name:Check License Filesrun:|# 检查许可证文件存在 test -f LICENSE-name:Check Version Consistencyrun:|# 检查版本号一致性 python scripts/check_versions.py检查脚本示例
#!/usr/bin/env python3importjsonimportsysdefcheck_readme_opensource():withopen('README.OpenSource','r')asf:data=json.load(f)required_fields=['Name','License','Version Number','Owner','Upstream URL']foritemindata:forfieldinrequired_fields:iffieldnotinitem:print(f"ERROR: Missing field '{field}' in{item.get('Name','unknown')}")returnFalseprint("OK: All required fields present")returnTrueif__name__=='__main__':sys.exit(0ifcheck_readme_opensource()else1)与其他文件的同步
版本号同步检查
#!/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"];thenecho"✓ All versions consistent"exit0elseecho"✗ Version mismatch detected"exit1fi许可证文件同步
#!/bin/bash# sync_license.sh# 从 README.OpenSource 获取许可证文件 URLlicense_url=$(jq-r'.[0]["License File"]'README.OpenSource)# 下载并比对curl-sL"$license_url"-o/tmp/upstream_licenseifdiff-qLICENSE /tmp/upstream_license>/dev/null;thenecho"✓ License file matches upstream"elseecho"✗ 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 LicenseApache-2.0:Apache License 2.0GPL-3.0:GNU General Public License v3.0Unlicense:The Unlicense
完整列表:https://spdx.org/licenses/
合规工具
- FOSSA:开源合规管理平台
- Black Duck:开源风险分析
- Snyk:开源安全与合规
- license-checker:npm 许可证检查
若你扩展了补丁、新增依赖或更换上游版本,记得同步改Version Number、License File链接、Description,并与HPKBUILD/README_zh.md保持一致。