强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

开源协议精讲 / 第八章:许可证兼容性与冲突

第八章:许可证兼容性与冲突

引言

在一个现代软件项目中,你可能同时依赖数十甚至数百个开源库,每个库可能使用不同的许可证。许可证兼容性(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 主流许可证兼容性总表

以下表格展示了常见许可证之间的兼容性(行许可证代码可纳入列许可证项目):

↓可纳入→MITBSDApache-2.0GPL-2.0GPL-3.0LGPL-2.1LGPL-3.0AGPL-3.0MPL-2.0EPL-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 v3GPL v3 明确与 Apache 2.0 兼容
使用 MIT/BSD 替代如果项目允许
移除 Apache 2.0 代码寻找替代实现
双重许可为涉及代码获得额外许可

8.3.2 GPL v2 与 GPL v3 的兼容性

复杂的兼容性

项目 A项目 B兼容性
GPL-2.0-onlyGPL-2.0-only
GPL-2.0-onlyGPL-3.0-only
GPL-2.0-onlyGPL-3.0-or-later✅(以 GPL-3.0 发布)
GPL-2.0-or-laterGPL-3.0-only✅(以 GPL-3.0 发布)
GPL-2.0-or-laterGPL-3.0-or-later✅(以 GPL-3.0 发布)
GPL-3.0-onlyGPL-3.0-only

关键点

  • GPL-2.0-onlyGPL-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 参考资源

  1. FSF 许可证兼容性图:https://www.gnu.org/licenses/license-compatibility.html
  2. Apache 许可证 FAQ:https://www.apache.org/foundation/license-faq.html
  3. SPDX 许可证列表:https://spdx.org/licenses/
  4. 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 隔离不同许可证组件
自动化扫描必要的合规工具

扩展阅读

  1. GNU 许可证兼容性:https://www.gnu.org/licenses/license-compatibility.html
  2. Apache 许可证兼容性:https://www.apache.org/licenses/license-compatibility
  3. SPDX 许可证列表:https://spdx.org/licenses/
  4. TLDRLegal:https://tldrlegal.com/
  5. Open Source License Compliance Handbook:https://github.com/openchain-project/license-compliance

上一章:双重授权与商业许可 下一章:SPDX 标准与工具