开源协议精讲 / 第八章:许可证兼容性与冲突
第八章:许可证兼容性与冲突
引言
在一个现代软件项目中,你可能同时依赖数十甚至数百个开源库,每个库可能使用不同的许可证。许可证兼容性(License Compatibility)决定了你是否能合法地将这些代码组合在一起。
本章将系统讲解许可证兼容性的规则、常见冲突、以及如何在实际项目中处理兼容性问题。
8.1 许可证兼容性的基本概念
8.1.1 什么是许可证兼容性?
许可证兼容性是指:两个或多个不同许可证的代码能否合法地组合在一个作品中。
代码 A(许可证 X)+ 代码 B(许可证 Y)= 组合作品
问:组合作品应该以什么许可证发布?
答:取决于 X 和 Y 的兼容性
8.1.2 兼容性的方向性
许可证兼容性是有方向的:
许可证 A 可以与许可证 B 兼容(A → B 兼容)
但反过来不一定成立(B → A 不一定兼容)
示例:
- MIT 代码可以纳入 GPL 项目(MIT → GPL 兼容)
- GPL 代码不能纳入 MIT 项目(GPL → MIT 不兼容)
原因:GPL 要求衍生作品必须以 GPL 发布,而 MIT 没有这个要求。所以 MIT 代码可以加入 GPL 项目(用 GPL 发布),但 GPL 代码不能加入 MIT 项目(因为 MIT 项目不想被 GPL 传染)。
8.1.3 兼容性的判断标准
判断两个许可证是否兼容,核心问题是:
组合后的作品能否同时满足两个许可证的所有要求?
| 情况 | 结果 |
|---|---|
| 两个许可证的要求可以同时满足 | ✅ 兼容 |
| 两个许可证的要求互相矛盾 | ❌ 不兼容 |
| 一个许可证的要求被另一个禁止 | ❌ 不兼容 |
8.2 许可证兼容性矩阵
8.2.1 主流许可证兼容性总表
以下表格展示了常见许可证之间的兼容性(行许可证代码可纳入列许可证项目):
| ↓可纳入→ | MIT | BSD | Apache-2.0 | GPL-2.0 | GPL-3.0 | LGPL-2.1 | LGPL-3.0 | AGPL-3.0 | MPL-2.0 | EPL-2.0 |
|---|---|---|---|---|---|---|---|---|---|---|
| MIT | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| BSD-3 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Apache-2.0 | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ⚠️ |
| GPL-2.0 | ❌ | ❌ | ❌ | ✅ | ⚠️ | ❌ | ⚠️ | ⚠️ | ❌ | ❌ |
| GPL-3.0 | ❌ | ❌ | ❌ | ⚠️ | ✅ | ❌ | ✅ | ✅ | ⚠️ | ❌ |
| LGPL-2.1 | ❌ | ❌ | ❌ | ✅ | ⚠️ | ✅ | ⚠️ | ⚠️ | ❌ | ❌ |
| LGPL-3.0 | ❌ | ❌ | ❌ | ⚠️ | ✅ | ⚠️ | ✅ | ✅ | ⚠️ | ❌ |
| AGPL-3.0 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| MPL-2.0 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| EPL-2.0 | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
⚠️ 注意:标有 ⚠️ 的情况需要特殊条件或存在争议,具体见下文分析。
8.2.2 兼容性分组
宽松许可证组(MIT、BSD、ISC、Apache-2.0)
├── 彼此完全兼容
├── 可以纳入几乎所有其他许可证
└── 是"万能接受者"
Copyleft 许可证组(GPL、AGPL)
├── 与宽松许可证兼容(可以接受)
├── 彼此之间兼容性复杂
└── 不兼容被其他 Copyleft 许可证接受(传染性)
弱 Copyleft 许可证组(MPL、EPL、LGPL)
├── 与宽松许可证兼容
├── 与 GPL 的兼容性视具体条款而定
└── 彼此之间兼容性有限
8.3 常见兼容性问题分析
8.3.1 Apache 2.0 与 GPL v2 的冲突
问题:Apache 2.0 包含专利终止条款,与 GPL v2 不兼容。
具体冲突:
Apache 2.0 Section 3:
"If You institute patent litigation against any entity..."
→ 专利许可自动终止
GPL v2 Section 7:
"You may not impose any further restrictions..."
→ 不得添加额外限制
冲突:Apache 2.0 的专利终止条款被视为 GPL v2 的"额外限制"
解决方案:
| 方案 | 说明 |
|---|---|
| 使用 GPL v3 | GPL v3 明确与 Apache 2.0 兼容 |
| 使用 MIT/BSD 替代 | 如果项目允许 |
| 移除 Apache 2.0 代码 | 寻找替代实现 |
| 双重许可 | 为涉及代码获得额外许可 |
8.3.2 GPL v2 与 GPL v3 的兼容性
复杂的兼容性:
| 项目 A | 项目 B | 兼容性 |
|---|---|---|
| GPL-2.0-only | GPL-2.0-only | ✅ |
| GPL-2.0-only | GPL-3.0-only | ❌ |
| GPL-2.0-only | GPL-3.0-or-later | ✅(以 GPL-3.0 发布) |
| GPL-2.0-or-later | GPL-3.0-only | ✅(以 GPL-3.0 发布) |
| GPL-2.0-or-later | GPL-3.0-or-later | ✅(以 GPL-3.0 发布) |
| GPL-3.0-only | GPL-3.0-only | ✅ |
关键点:
GPL-2.0-only与GPL-3.0-only不兼容GPL-2.0-or-later可以升级到 GPL v3,从而与 GPL-3.0 兼容- Linux 内核使用
GPL-2.0-only,因此不能直接包含 GPL v3 代码
8.3.3 EPL 与 GPL 的冲突
EPL 和 GPL 之间存在根本性冲突:
EPL 要求:
- 修改 EPL 代码必须以 EPL 发布
- 可以选择次级许可证(Secondary License)
GPL 要求:
- 衍生作品必须以 GPL 发布
冲突:
- EPL 代码想保持 EPL
- GPL 代码想传染整个项目
- 两者不能同时满足
解决方案:
| 方案 | 说明 |
|---|---|
| 使用次级许可证 | EPL 2.0 允许声明 GPL 为次级许可证 |
| 隔离使用 | 将 EPL 和 GPL 代码放在独立组件中 |
| 寻找替代 | 用兼容的许可证替换其中一个 |
8.3.4 AGPL 的特殊性
AGPL 是兼容性最严格的许可证:
AGPL 的传染范围:
├── 分发软件 → 传染
├── 网络服务 → 传染
└── 几乎任何组合都会被 AGPL 传染
结果:
- MIT 代码可以纳入 AGPL 项目 ✅
- AGPL 代码几乎不能纳入其他项目 ❌
8.3.5 MPL 2.0 的"逃生条款"
MPL 2.0 包含条款 3.3,允许将 MPL 代码与 GPL 代码组合:
MPL 2.0 Section 3.3:
"You may additionally convey a work that is a combination of the
Covered Software with a work governed by a Secondary License..."
这使得 MPL 2.0 成为与 GPL 兼容的弱 Copyleft 许可证。
8.4 混合使用的实际场景
8.4.1 场景分析
场景 1:Web 应用的许可证组合
项目:Node.js Web 应用
依赖:
├── Express.js (MIT)
├── React (MIT)
├── PostgreSQL driver (MIT)
├── Redis (BSD-3-Clause → RSALv2/SSPL)
├── 图像处理库 (Apache-2.0)
└── 加密库 (GPL-2.0)
问题:GPL-2.0 加密库是否传染整个项目?
分析:
- 如果是动态链接(npm 模块通常是独立的)
- FSF 认为可能构成衍生作品
- 实践中存在争议
建议:
- 寻找 MIT/Apache 替代品
- 或接受 GPL 传染并开源项目
场景 2:企业内部工具
项目:内部管理系统
依赖:
├── Spring Boot (Apache-2.0)
├── Hibernate (LGPL-2.1)
├── 数据库 (GPL)
└── 前端框架 (MIT)
问题:LGPL 和 GPL 的影响
分析:
- 内部使用不分发 → 不触发 GPL/LGPL 义务
- 如果分发给子公司 → 可能触发
- 如果作为 SaaS → 不触发
结论:纯内部使用通常安全
场景 3:嵌入式设备
项目:IoT 设备固件
依赖:
├── Linux 内核 (GPL-2.0)
├── BusyBox (GPL-2.0)
├── 自有驱动 (Proprietary)
└── 应用层 (MIT)
问题:专有驱动是否被 GPL 传染?
分析:
- Linux 内核有"用户空间例外"
- 但内核模块(驱动)需要 GPL 兼容
- 闭源驱动存在法律风险
建议:
- 将驱动以 GPL 发布
- 或使用用户空间驱动
8.4.2 组件隔离策略
架构层面的许可证隔离:
┌─────────────────────────────────────┐
│ 应用层(你的代码) │
│ 许可证:Apache-2.0 │
├─────────────────────────────────────┤
│ 服务层 │
│ ┌──────────┐ ┌──────────┐ │
│ │ MIT 模块 │ │ BSD 模块 │ │
│ └──────────┘ └──────────┘ │
├─────────────────────────────────────┤
│ 隔离层(IPC/API) │
├─────────────────────────────────────┤
│ GPL 组件(独立进程) │
│ 许可证:GPL-3.0 │
└─────────────────────────────────────┘
策略:
- GPL 组件作为独立进程运行
- 通过 IPC/API 与主应用通信
- 避免直接链接
8.5 合规挑战与解决方案
8.5.1 供应链中的许可证冲突
现代软件依赖链很深:
你的应用
└── 直接依赖 A (MIT)
└── 间接依赖 B (Apache-2.0)
└── 间接依赖 C (GPL-2.0)
└── 间接依赖 D (AGPL-3.0) ← 最终你有 AGPL 代码!
解决方案:
| 方法 | 说明 |
|---|---|
| 依赖审查 | 在引入新依赖前审查许可证 |
| 自动化扫描 | 使用工具自动检测许可证 |
| 依赖锁定 | 锁定已审查的依赖版本 |
| 替代方案 | 为冲突依赖寻找替代品 |
8.5.2 多许可证代码的声明
当项目包含多种许可证的代码时,需要明确声明:
许可证声明示例:
本项目使用以下许可证:
主要代码:Apache License 2.0
Copyright 2024 Your Company
第三方组件:
- library-a (MIT License)
- library-b (BSD 3-Clause)
- library-c (GPL v2, 见 NOTICE 文件)
- library-d (Apache License 2.0)
完整许可证文本见 LICENSES/ 目录。
8.5.3 NOTICE 文件的维护
NOTICE 文件示例:
Apache Foo Library
Copyright 2020-2024 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (https://www.apache.org/).
This product includes:
- Bar Library (MIT License)
Copyright 2019 John Doe
- Baz Library (BSD 3-Clause)
Copyright 2020 Jane Smith
8.6 兼容性决策流程
8.6.1 引入新依赖的审查流程
引入新依赖前:
│
├── 1. 检查许可证类型
│ └── 宽松?Copyleft?自定义?
│
├── 2. 检查与项目许可证的兼容性
│ └── 参考兼容性矩阵
│
├── 3. 检查与现有依赖的兼容性
│ └── 所有依赖之间的兼容性
│
├── 4. 评估传染风险
│ └── 是否会影响项目许可证?
│
├── 5. 决策
│ ├── 兼容 → 引入
│ ├── 有条件兼容 → 评估条件
│ └── 不兼容 → 寻找替代
│
└── 6. 记录
└── 更新许可证清单
8.6.2 常见冲突的解决模式
| 冲突类型 | 解决方案 |
|---|---|
| 宽松 + 宽松 | 直接组合,保留所有声明 |
| 宽松 + GPL | 以 GPL 发布组合作品 |
| GPL + GPL(同版本) | 以该 GPL 版本发布 |
| GPL + GPL(不同版本) | 使用 -or-later 版本升级 |
| Apache-2.0 + GPL-2.0 | 升级到 GPL-3.0 或移除一方 |
| EPL + GPL | 使用 EPL 次级许可证条款或隔离 |
8.7 工具与资源
8.7.1 兼容性检查工具
| 工具 | 类型 | 功能 |
|---|---|---|
| FOSSology | 开源 | 许可证扫描、合规分析 |
| ScanCode Toolkit | 开源 | 代码扫描、许可证检测 |
| WhiteSource/Mend | 商业 | 全面的 SCA 平台 |
| Black Duck | 商业 | 开源风险管理 |
| licensee | 开源 | GitHub 使用的检测工具 |
8.7.2 参考资源
- FSF 许可证兼容性图:https://www.gnu.org/licenses/license-compatibility.html
- Apache 许可证 FAQ:https://www.apache.org/foundation/license-faq.html
- SPDX 许可证列表:https://spdx.org/licenses/
- Choose A License:https://choosealicense.com/
8.8 本章小结
| 核心要点 | 说明 |
|---|---|
| 兼容性有方向 | A→B 兼容不等于 B→A 兼容 |
| Copyleft 传染 | GPL/AGPL 要求衍生作品使用相同许可证 |
| Apache-2.0 + GPL-2.0 | 不兼容,需要 GPL-3.0 |
| 宽松许可证 | 是万能接受者 |
| 隔离策略 | 通过进程/IPC 隔离不同许可证组件 |
| 自动化扫描 | 必要的合规工具 |
扩展阅读
- GNU 许可证兼容性:https://www.gnu.org/licenses/license-compatibility.html
- Apache 许可证兼容性:https://www.apache.org/licenses/license-compatibility
- SPDX 许可证列表:https://spdx.org/licenses/
- TLDRLegal:https://tldrlegal.com/
- Open Source License Compliance Handbook:https://github.com/openchain-project/license-compliance
上一章:双重授权与商业许可 下一章:SPDX 标准与工具