在上一篇开源许可证全景:宽松、弱 Copyleft、强 Copyleft、网络 Copyleft中,我们按「传染性强弱」把常见许可证分成了四类。工程师真正头疼的不是分类,而是判定:我这个系统到底有没有触发 Copyleft?
- 我只把带 GPL 库的二进制部署到内网,算不算「分发」?
- 我的 Docker 镜像里有 glibc,是不是要公开所有源码?
- 我在 AWS 上跑 AGPL 数据库,算不算向用户「传递」?
- 我用 webpack 把一个 AGPL 的前端组件打包进 bundle,用户下载了 bundle.js,我要不要开源整个前端?
这些问题的答案,写在 GPLv2 的「distribute」、GPLv3 的「convey」、LGPL-2.1 的§4/§5、AGPL-3.0 的§13 这些条款里。本文把它们拆成可操作的工程判定规则,并用一张触发矩阵作为索引。
一、重新理解「分发」:从 distribute 到 convey
Copyleft 的全部义务,都挂在「触发事件」上。没有触发事件,GPL 就只是一份「你自己可以自由使用」的许可证,并不要求你做任何额外的事情。
1.1 GPLv2 的 distribute:物理传递的隐喻
GPL-2.0 通篇使用的动词是 distribute(分发)。GPLv2 §1 规定:
You may copy and distribute verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty…
以及 §3:
You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following…
这里的 distribute 继承的是 1991 年美国版权法(Copyright Act)里的「distribution right」概念:把作品的一份拷贝从一方转移到另一方,物理介质的隐喻非常明显——软盘、磁带、CD-ROM。
在这个语境下,内部使用(internal use)——哪怕是一个一万人的公司、服务器部署在一万台机器上——只要软件没有「离开公司的控制范围」,就不算 distribute,因此也不触发 GPLv2 的源代码披露义务。这一点在 FSF 的 GPL FAQ「Is making and using multiple copies within one organization or company ‘distribution’?」中有明确解释:同一法人实体内部的拷贝不构成分发。
1.2 GPLv3 的 convey:意图更宽泛的新动词
2007 年的 GPL-3.0 引入了一个新动词 convey(传递)。这并非同义替换,而是一次有意的语义升级。GPLv3 §0 给出了定义:
To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
然后 §6「Conveying Non-Source Forms」专门规定以目标代码(object code)形式传递时的义务,包括:
- §6(a):随物理介质附带机器可读的完整源代码;
- §6(b):随物理介质附带一份至少三年有效的书面要约(written offer);
- §6(c):在非商业性传递中附带从他处收到的书面要约;
- §6(d):从指定服务器提供等价访问;
- §6(e):通过 peer-to-peer 方式传递时的特殊安排。
convey 比 distribute 更宽泛的地方在于:它覆盖了 propagation(传播)的更多形态,包括「让第三方能够制作或接收副本的任何行为」。但 GPLv3 明确把「仅通过计算机网络与用户交互、没有副本转移」排除在外——这就是后来 AGPL-3.0 §13 要堵的「SaaS 漏洞」。
1.3 判定的黄金标准:软件是否离开了你的控制范围
抛开具体条款,工程师需要记住一条朴素的判断原则:
软件是否离开了你(你的法人实体)的控制范围,到达了另一个法人或自然人手里?
- 公司内部 1 万人使用 → 没离开,不触发。
- 给客户发了一份二进制 → 离开了,触发。
- 在自己的服务器上跑服务,用户通过 HTTP 访问 → 没离开(GPL 视角),但 AGPL 视角下网络交互也算离开。
- 把镜像推到 Docker Hub,任何人可以 pull → 离开了,触发。
这条原则不能覆盖所有边缘情况(比如控股子公司之间的传递、合资公司、外包开发),但足以处理 90% 的日常工程决策。
1.4 子组件:关联公司、承包商与云账号
FSF 在 GPL FAQ 里补充了两类常见的「灰色边界」:
- 承包商(contractor):如果你雇佣一个外部开发者,为你修改 GPL 代码,然后只把结果交还给你,FSF 认为这不构成「对外分发」——因为承包商是作为你的代理在工作。一旦承包商自己把代码给了第三方,那就是分发。
- 关联公司:同一母公司下的不同法人实体之间,严格意义上是不同的「party」。FSF 的立场较为宽松,认为通常不算分发;但若被收购或分立,代码跟随实体变更时可能构成分发事件。
在云原生场景,云账号的归属同样重要:如果用户登录自己的 AWS 账号运行你的镜像,那是他在「自我托管」;如果你在自己的账号里替用户跑镜像并把结果返回给他,那就接近 SaaS 语义,AGPL 立刻开始说话。
二、动态链接 vs 静态链接:LGPL 的精巧设计
Copyleft 有一个从立项之初就存在的争议:把一个 GPL 库链接进我的专有程序,我的程序是否变成「衍生作品(derivative work)」,从而必须整体开源?
Richard Stallman 和 FSF 的观点是:是。链接(无论静态还是动态)在运行时把两份代码合并成一个地址空间、共享内存、共享调用栈,法律上构成「combined work(组合作品)」——除非有明确的许可证例外。
但这显然过于激进。如果连 printf 都不能调用,GPL 库就没法被专有软件使用,开源生态的扩散就会受阻。于是 FSF 专门写了 LGPL(Lesser GPL,早期叫 Library GPL)来提供链接例外。
2.1 LGPL-2.1 的链接例外:§4、§5、§6
LGPL-2.1 是目前仍广泛使用的版本,它的核心在§5 和§6。
§5 规定:「使用但不包含(使用通过头文件、不包含实际代码)库中任何部分的作品」不是 derivative work,因此不受 LGPL 覆盖:
A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a “work that uses the Library”. Such a work, in isolation, is not a derivative work of the Library…
§6 则规定,你可以将你的程序与 LGPL 库「组合或链接」,并以你选择的条款分发组合作品,但必须允许接收者修改并替换 LGPL 库:
As an exception to the Sections above, you may also combine or link a “work that uses the Library” with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer’s own use and reverse engineering for debugging such modifications.
具体的「允许替换」包括以下形式之一:
- §6(a):附带完整源代码及足够的链接信息,使用户可以重新链接;
- §6(b):使用合适的「共享库机制」(即动态链接),使用户可以换掉 so/dll 而程序继续工作;
- §6(c)、(d)、(e):书面要约或等价安排。
这就是为什么动态链接 LGPL 库在工程上被视为安全——它天然满足§6(b)。静态链接也可以合规,但你必须额外提供目标文件(.o)或可重链接的形式。
2.2 LGPL-3.0:基于 GPL-3.0 的「薄层加法」
LGPL-3.0(2007)不再是一份独立的长文档,而是一份简短的「附加许可」,挂在 GPL-3.0 之上。它的核心是§4「Combined Works」:允许你把「Combined Work」——一个使用了 LGPL 库的程序——以你选择的条款分发,前提同样是保留用户替换库的能力(§4(d)(0) 动态链接或 §4(d)(1) 提供链接所需的目标文件)。
工程上的判断和 LGPL-2.1 基本一致:动态链接 → 安全;静态链接 → 需要额外提供目标文件。
2.3 Java 的 Classpath Exception:为什么需要它
OpenJDK 的许可证是「GPL-2.0 with Classpath Exception」。Classpath Exception 的原文简短但关键:
Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU General Public License cover the whole combination. As a special exception, the copyright holders of this library give you permission to link this library with independent modules to produce an executable, regardless of the license terms of these independent modules…
为什么要加这个例外?因为 Java 的标准类库和运行时是紧耦合的:任何一个 Java 程序都会隐式地 import java.lang.*,并运行在 JVM 上。如果没有 Classpath Exception,所有在 OpenJDK 上运行的 Java 应用都会变成 GPL 的 combined work,Java 生态将无法容纳任何专有软件。
GNU Classpath 项目(后来被 OpenJDK 大量吸收)就是在这个背景下设计了这条例外,它随 Sun 开源 Java 时一并进入 OpenJDK。
2.4 工程判断的速查表
| 链接关系 | 许可证组合 | 触发情况 | 必须做什么 |
|---|---|---|---|
| 静态链接 | 专有 + GPL-2.0 | 触发整体 GPL | 整个程序必须 GPL 发布 |
| 动态链接 | 专有 + GPL-2.0 | FSF 认为触发 | 整个程序必须 GPL 发布(争议) |
| 静态链接 | 专有 + LGPL-2.1 | 部分触发 | 提供目标文件允许重链接 |
| 动态链接 | 专有 + LGPL-2.1 | 部分触发 | 保留用户替换库的能力 |
| 静态链接 | 专有 + LGPL-3.0 | 部分触发 | 提供链接目标或源码 |
| 动态链接 | 专有 + LGPL-3.0 | 部分触发 | 满足§4(d)(0) |
| 链接 | 专有 + OpenJDK(Classpath) | 不触发 | 无额外义务 |
| 链接 | 专有 + MPL-2.0 库 | 文件级触发 | 修改过的 MPL 文件保持 MPL |
注意:关于「动态链接是否算 derivative work」,FSF、Linus Torvalds(Linux 内核作者)、以及不同法域的法院有不同观点。大多数企业合规团队采取保守立场:只对 LGPL、MPL 这类显式允许链接的库做动态链接,坚决避免专有软件动态链接 GPL 库。
2.5 CMake 中的正确链接示例
下面是一个工程上常见的场景:C++ 程序需要用 OpenSSL(Apache-2.0)和 SQLite(Public Domain),同时动态链接一个 LGPL-2.1 的库(比如 libzip 的某些版本,注意:实际许可请以最新上游为准)。
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(myapp CXX)
set(CMAKE_CXX_STANDARD 20)
find_package(OpenSSL REQUIRED)
find_package(SQLite3 REQUIRED)
# 关键:以共享库形式链接 LGPL 库,满足 LGPL-2.1 §6(b)
# 不要改成 libzip::libzip_static
find_package(libzip REQUIRED)
add_executable(myapp
src/main.cpp
src/db.cpp
src/archiver.cpp
)
target_link_libraries(myapp
PRIVATE
OpenSSL::SSL
SQLite::SQLite3
libzip::zip # 动态链接,so/dll 可被替换
)
# 在安装包中保留 so 文件为独立实体
install(TARGETS myapp RUNTIME DESTINATION bin)
install(FILES $<TARGET_FILE:libzip::zip> DESTINATION lib)
# 生成 NOTICE 文件,列出 LGPL 库及替换说明
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/NOTICE.in
${CMAKE_CURRENT_BINARY_DIR}/NOTICE
@ONLY
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/NOTICE DESTINATION share/myapp)对应的 NOTICE.in 模板:
myapp @VERSION@
Copyright (c) 2026 Acme Corp.
This product includes software developed by third parties,
licensed under their respective licenses. In particular:
libzip (LGPL-2.1-or-later)
Source: https://libzip.org/
This product dynamically links libzip. You may replace
the bundled libzip shared library (lib/libzip.so.5) with
a modified version of libzip compiled from source.
See <https://libzip.org/download/> for source code.
OpenSSL (Apache-2.0)
Source: https://www.openssl.org/
SQLite (Public Domain)
Source: https://sqlite.org/
三、容器镜像:layer 是独立的,镜像作为整体被分发
容器是过去十年最具破坏性的打包方式,也是 Copyleft 讨论里最容易出错的地方。
3.1 FSF 的立场:分发镜像等于传递
GNU 的 GPL FAQ 里明确讨论了「Is distributing a Docker image that includes a GPL-covered program distribution of that program?」。立场是:当然算。镜像只是一种打包格式,把 tar 变成 OCI layer 并不改变「分发」的法律性质。你把 Ubuntu 基础镜像叠上自己的应用 layer,然后 push 到 registry,用户从你的 registry 拉下来,这和给他发一个 tar 包或 USB 盘本质一样。
3.2 基础镜像的许可证:Alpine vs Debian
基础镜像里的每一个包都有自己的许可证。两种常见选择:
Alpine Linux:核心发行版使用 MIT,libc 使用 musl(MIT)。这意味着:基础镜像本身不带 Copyleft 包(除了 BusyBox 的 GPL-2.0,但 BusyBox 是作为独立可执行工具分发的,不作为共享库链接进你的程序)。
Debian / Ubuntu:核心是 Debian Free Software Guidelines 兼容的许可证混合体,glibc 是 LGPL-2.1,大量 GNU 工具是 GPL-2.0 或 GPL-3.0。
你的应用如果只是通过 syscall 调用 glibc(比如 Go 的 CGO、Python 的 C 扩展),业界的主流观点是:调用 LGPL-2.1 的 glibc 不触发整体 Copyleft,因为:
- LGPL-2.1 §5 明确把「使用但不包含」的作品排除在 derivative 之外;
- 动态链接 glibc 天然满足§6(b) 的「可替换」要求;
- 即便是 GPL 应用也明确认可 libc 不是 combined work(GPLv3 §1 的「System Library」例外)。
3.3 GPLv3 的 System Library 例外
GPLv3 §1 定义了「System Libraries」:
The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component…
然后在§6 要求「Corresponding Source」时,明确不需要把 System Library 的源代码包括进去:
The “Corresponding Source” need not include anything that users can regenerate automatically from other parts of the Corresponding Source. … However, it does not include the work’s System Libraries…
这一条从语义上解决了「容器里带 glibc 要不要公开 glibc 源码」的争议:不需要,因为 glibc 是 System Library。但是你自己的应用如果是 GPL,你仍然要提供应用的源码。
3.4 两种 Dockerfile:许可证影响
Alpine 基础镜像:
# syntax=docker/dockerfile:1.6
FROM alpine:3.19 AS runtime
# Alpine 核心 MIT,musl libc MIT,不带传染性
# BusyBox GPL-2.0 作为独立工具存在,不与你的应用链接
RUN apk add --no-cache ca-certificates tzdata
WORKDIR /app
COPY --from=build /out/myapp /app/myapp
ENTRYPOINT ["/app/myapp"]
# 合规义务:
# - 如果你修改了 Alpine 的任何 GPL 包,需要提供源码
# - 未修改则遵守 apk 包内的 NOTICE 即可Debian 基础镜像:
# syntax=docker/dockerfile:1.6
FROM debian:12-slim AS runtime
# glibc LGPL-2.1(System Library 例外下通常安全)
# coreutils GPL-3.0(工具级 Copyleft,不与你的应用链接)
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates tzdata && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=build /out/myapp /app/myapp
# 合规义务清单(放入镜像层)
COPY NOTICE /usr/share/doc/myapp/NOTICE
COPY WRITTEN-OFFER.txt /usr/share/doc/myapp/WRITTEN-OFFER.txt
ENTRYPOINT ["/app/myapp"]对应的 WRITTEN-OFFER.txt:
Written Offer for Source Code
This image contains software licensed under the GNU General
Public License (GPL) and related copyleft licenses, including
but not limited to: coreutils, bash, sed, grep.
For a period of three years from the date of distribution of
this image, you may request the complete corresponding source
code of any GPL-licensed component by writing to:
Acme Corp., Attn: Open Source Compliance
oss-compliance@acme.example
123 Example Street, City, Country
We will provide the source code either by mail on a physical
medium (at no charge beyond reasonable shipping cost) or by
pointing you to the exact upstream source used to build this
image, per GPL-3.0 Section 6.
3.5 FROM scratch 与静态二进制:看起来最干净
对 Go/Rust 这类可以产出静态二进制的语言,最干净的做法是:
# syntax=docker/dockerfile:1.6
FROM golang:1.22 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /out/myapp ./cmd/myapp
FROM scratch
COPY --from=build /out/myapp /myapp
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY NOTICE /NOTICE
ENTRYPOINT ["/myapp"]这个镜像里除了你自己的二进制,什么也没有。只要你的依赖里没有 GPL/LGPL 库(Go 生态主流是 BSD/MIT/Apache-2.0),这是最低合规负担的打包方式。
但有两个坑:
- CGO_ENABLED=1 时 Go 会链接 glibc(如果你用了 go-sqlite3 等 CGO 库),从 scratch 切到 Alpine 或 distroless 更稳;
- go.sum 中的间接依赖仍然需要 SCA 扫描——静态二进制不会让许可证消失,只是让它们变得不可见。相关实践见 SCA 与 SBOM:如何自动化治理开源合规。
3.6 Docker 官方镜像的 GPL 成分
Docker Hub 上的
debian、ubuntu、centos
等官方镜像都附带了完整的包清单与许可证信息。你可以用:
docker run --rm debian:12-slim \
sh -c "dpkg-query -W -f='\${Package} \${Version} \${Homepage}\n' | head -20"列出其中所有包。对 Alpine:
docker run --rm alpine:3.19 \
sh -c "apk info | head -20"一个合格的 SBOM(Software Bill of Materials)会把这些信息自动化提取。
四、SaaS 部署:AGPL 如何堵住「SaaS 漏洞」
4.1 GPL 的 SaaS 漏洞
GPLv2 是 1991 年写的,那时 Web 服务还不普遍;GPLv3 是 2007 年写的,Web 2.0 已经流行。但 FSF 仍然决定把 GPLv3 的 convey 定义为「副本转移」——显式把「单纯网络交互」排除在外。这就是所谓的 SaaS 漏洞。
后果非常戏剧:
- Google 把 MySQL(当时 GPL-2.0)跑在自己的服务器上,对用户提供搜索服务。Google 不向用户分发 MySQL 二进制,也不修改 MySQL 并分发,因此完全不触发 GPL 的源码公开义务。
- 同理,一个企业可以基于 PostgreSQL 插件(GPL 的情况不多,但假设如此)做一个 SaaS,把所有改动保留在自己的服务器上。
这对「贡献回社区」的哲学来说是个漏洞:用户享受到软件带来的服务价值,但永远无法拿到改进后的代码。
4.2 AGPL-3.0 §13:网络交互也触发
AGPL-3.0 在 GPL-3.0 基础上加了一条§13「Remote Network Interaction; Use with the GNU General Public License」:
Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software.
关键条件:
- 你修改了程序;
- 你修改的版本通过网络对远程用户提供交互;
- 你必须向这些远程用户明显地提供获取修改版源码的机会。
通常的做法是在 Web UI 的页脚放一个「Source Code」链接,指向自己的 Git 仓库或 tarball。
4.3 AGPL 的适用场景:数据库、搜索引擎、协作工具
AGPL 的典型使用者是那些「主要以服务形态交付价值」的项目:
- MongoDB(2018 年前)使用 AGPL-3.0,之后换到 SSPL-1.0(见商业开源与双许可);
- Elastic(早期 Elasticsearch)也经历过类似的迁移;
- Nextcloud 使用 AGPL-3.0 保护服务器端代码不被云厂商白嫖;
- Grafana Loki、Tempo 在某些阶段使用 AGPL-3.0;
- Ghost 博客平台使用 MIT(反例:选择宽松协议吸引生态)。
AGPL 的选择逻辑:我希望任何人都可以自托管,但云厂商不能简单地把我的代码变成 SaaS 却不回馈改动。
4.4 AGPL 的工程触发点:哪怕是一个内部改动
很多团队低估了 AGPL 的穿透性。几个常见陷阱:
- 分叉并修 bug:你 fork 了一个 AGPL 项目,修了一个 bug 自己用,还提供给客户通过网络访问——你必须把这个 fork 的源码对客户(远程用户)开放。
- 加一个内部管理接口:你在 AGPL 项目里加了一个 /admin 页面,只有公司内部用。这仍然「修改了程序」并「通过网络交互」,严格意义上仍需提供源码,哪怕只对公司内部 IT 员工。
- Sidecar 模式:你写了一个 AGPL 程序的 sidecar(比如一个认证代理),sidecar 本身是你的私有代码,但它和 AGPL 主程序是否构成 combined work 取决于交互方式。进程间通过 HTTP/gRPC 交互通常不构成;通过共享内存或库链接则可能构成。
4.5 前端也能被 AGPL 传染
一个容易被忽略的场景:前端 JavaScript 是 AGPL 的。因为浏览器从你的服务器下载了 JS bundle,严格说这已经是一次「convey」——用户拿到了副本。在 GPLv3 的语义下,这不算 SaaS,这就是分发。
所以:
- 如果你 webpack 打包了一个 AGPL 的前端库(比如 AG Grid Community 的某些版本,AG Grid 的社区版实际使用的是 MIT,这里仅作假设;另一个真实例子是 Mermaid 曾短暂考虑过,但最终采用 MIT),你分发 bundle.js 的时候,整个 bundle 包含的代码都必须在 AGPL 下可获取。
- 实践中常见做法:要么换一个 MIT/Apache 许可的等价库,要么购买商业许可(许多 AGPL 项目提供 dual-licensing)。
五、部署场景 × 许可证:触发矩阵
这一节是本文的核心工具。
5.1 五种部署场景
- 内部员工使用(不外发):代码/镜像只在公司内部使用,不提供给公司外的任何自然人或法人。
- 向客户分发二进制:以任何形式(物理介质、网络下载、容器镜像 pull)把二进制副本提供给客户。
- SaaS 服务(用户通过网络访问):你托管服务,用户通过 Web/API 使用,不获得二进制副本。
- 嵌入式设备固件:把软件烧进你卖给客户的硬件设备里。
- 云服务提供商(将其他人的软件作为服务提供):AWS/阿里云式的托管服务——把上游社区的开源软件作为托管服务卖给客户。
5.2 触发矩阵
| 部署场景 | GPL-2.0 | LGPL-2.1 | GPL-3.0 | AGPL-3.0 | SSPL-1.0 |
|---|---|---|---|---|---|
| 内部员工使用(不外发) | 不触发 | 不触发 | 不触发 | 不触发 | 不触发 |
| 向客户分发二进制 | 触发 | 部分触发 | 触发 | 触发 | 触发 |
| SaaS 服务(用户通过网络访问) | 不触发 | 不触发 | 不触发 | 触发 | 触发整个栈 |
| 嵌入式设备固件 | 触发 | 部分触发 | 触发 + 反 Tivoization | 触发 | 触发 |
| 云服务提供商托管 | 不触发 | 不触发 | 不触发 | 触发 | 触发整个栈 |
说明:
- 部分触发(LGPL):仅 LGPL 部分需公开,用户代码可保持专有,前提满足链接例外条件。
- 触发 + 反 Tivoization(GPL-3.0 嵌入式):除了源码公开,GPL-3.0 §6 还要求提供「Installation Information(安装信息)」,即用户重装修改版本到设备的所有必要手段(签名密钥、烧录工具等)。这是 2007 年 GPLv3 吸取 TiVo 数字录像机事件教训后增加的。
- 触发整个栈(SSPL):SSPL §13 要求「提供作为服务所有其他部分的源代码」——包含管理工具、用户界面、API、自动化脚本、监控工具、备份工具——这是比 AGPL 激进得多的条件,也是它不被 OSI 认可为开源许可证的原因。
5.3 嵌入式:TiVo 案例与§6 的「Installation Information」
TiVo 是一家美国数字录像机厂商,2000 年代初大量使用 Linux 内核(GPL-2.0)。他们满足了 GPL-2.0 的义务:提供了内核源码。但设备使用数字签名验证固件,普通用户即使修改了内核源码并编译,也无法把修改后的内核烧进 TiVo 设备——因为签名不匹配。
FSF 认为这违背了 Copyleft 的精神:用户拿到了源码,但无法实际运行修改版。GPL-3.0 §6 因此新增了 Installation Information 条款:
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term …, the Corresponding Source conveyed under this section must be accompanied by the Installation Information.
这就是为什么 Linux 内核至今停留在 GPL-2.0-only:Linus 和许多内核贡献者不认同 GPLv3 的「anti-Tivoization」,认为设备厂商有权锁定固件。
5.4 云服务商:SSPL 的「触发整个栈」
SSPL-1.0 §13 的原文:
If you make the functionality of the Program or a modified version available to third parties as a service, you must make the Service Source Code available via network download to everyone at no charge, under the terms of this License. Making the functionality of the Program or modified version available to third parties as a service includes, without limitation, enabling third parties to interact with the functionality of the Program or modified version remotely through a computer network… “Service Source Code” means the Corresponding Source for the Program or the modified version, and the Corresponding Source for all programs that you use to make the Program or modified version available as a service, including, without limitation, management software, user interfaces, application program interfaces, automation software, monitoring software, backup software, storage software and hosting software, all such that a user could run an instance of the service using the Service Source Code you make available.
这段「management software, user interfaces, APIs, automation, monitoring, backup, storage, hosting」几乎涵盖了运维整个栈。云厂商如果把 MongoDB(SSPL)作为托管服务卖,严格遵守 SSPL 就意味着要开源自己的整个管控面。这显然是 MongoDB 的设计意图:让大云厂商无法合规地托管 MongoDB。
结果:AWS、Azure、Google Cloud 都选择 fork 或换代(AWS DocumentDB 基于早期 MongoDB API;Amazon 的 OpenSearch fork 自 Apache-2.0 时期的 Elasticsearch)。
六、具体工程坑点
下面是六个真实的、容易踩的坑。
6.1 webpack 打包 AGPL 前端库
假设你的前端项目的 package.json 里混进了一个
AGPL 的组件:
{
"name": "my-frontend",
"version": "1.0.0",
"license": "UNLICENSED",
"dependencies": {
"react": "^18.2.0",
"some-agpl-grid": "^5.0.0"
}
}webpack build 后产出的 bundle.js 里,AGPL 库的代码被 tree-shaking 后仍然占了相当比例。你部署这个前端到 CDN,任何访问你网站的用户都会收到一份 bundle.js 副本——这是 convey,不是单纯网络交互。
合规动作:
# 1. 用 license-checker 扫描前端依赖
npx license-checker --production --summary
# 2. 设置 CI 检查,禁止 AGPL 进入前端依赖树
npx license-checker --production --failOn "AGPL-3.0;SSPL-1.0"
# 3. 如果必须使用,向供应商购买商业许可webpack 侧可以配置一个 plugin 自动写 LICENSES 文件:
// webpack.config.js
const LicensePlugin = require('webpack-license-plugin');
module.exports = {
// ...
plugins: [
new LicensePlugin({
outputFilename: 'oss-licenses.json',
unacceptableLicenseTest: (licenseId) =>
['AGPL-3.0', 'SSPL-1.0', 'GPL-3.0'].includes(licenseId),
}),
],
};6.2 Docker base image 中的 GPL glibc
前文已经给出了 Alpine 与 Debian 的对比 Dockerfile。补充一点:multi-stage build 的中间镜像也要注意。
错误示例:
# 第一阶段:带 GPL 工具的完整 Debian
FROM debian:12 AS build
RUN apt-get install -y gcc make libreadline-dev
# 你编译了自己的 C++ 程序,并静态链接了 libreadline(GPL-3.0)
RUN gcc -static main.c -o myapp -lreadline
# 第二阶段:看似干净
FROM scratch
COPY --from=build /myapp /myapp这个看似干净的最终镜像里,myapp 是静态链接的 libreadline——即你的 myapp 整体必须 GPL-3.0。静态链接一个 GPL-3.0 的 C 库是最危险的操作之一。正确做法是换成 BSD 许可的 libedit 或 linenoise。
6.3 Android ROM 中的 GPL 内核
Android 的架构设计有意做了 GPL/非-GPL 隔离:
- Linux 内核:GPL-2.0-only。必须开源。
- bionic libc:Google 自研,Apache-2.0。不是 LGPL 的 glibc——这是有意的设计选择。
- HAL 层:Android HAL 通过 binder IPC 与内核交互,而不是直接链接内核符号。binder 被 FSF 认为是「arms-length interaction」,不构成 combined work(这是 Google 和 FSF 之间长期的一个不公开表达的默契,未在法庭被测试)。
- 应用层:Apache-2.0(Android Framework)+ 各应用自有许可证。
因此 Android ROM 厂商(小米、OPPO、Samsung、LineageOS)的合规做法是:
- 公开修改后的 Linux 内核源码(在 GitHub 上,如
MiCode/Xiaomi_Kernel_OpenSource); - 不公开上层应用框架的专有修改(因为是 Apache-2.0,无此义务);
- 公开修改的 GPL 组件(如 BusyBox、mkbootimg 等)。
LineageOS 由于是整个项目开源,合规压力小;商业 ROM 厂商的主要合规点是内核 tag 与厂商分支的及时推送。华为在 OpenHarmony 项目里使用 Linux 内核(LiteOS-A 是自研,HarmonyOS Next 据称完全自研内核以摆脱 GPL 义务,但 OpenHarmony 标准系统仍然使用 Linux 内核)时,也在 gitee.com/openharmony 上维护了对应的 kernel_linux_5.10 仓库以满足 GPL-2.0 义务。
6.4 Java 应用链接 GPL 库
OpenJDK 的 Classpath Exception 让你可以在 GPL JVM 上跑专有 Java 应用。但不是所有 Java 库都带 Classpath Exception。
例如:
- 一个纯 GPL-3.0 的 Java 库(无 Classpath Exception,极少数,但存在):你 import 它,整个应用变 GPL-3.0。
- LGPL Java 库:几乎没有人这样发布(Java 本身没有「动态链接」概念,LGPL 在 Java 世界意义模糊,FSF 推荐用 GPL + Classpath Exception 代替)。
- 常见的「安全」许可:Apache-2.0、MIT、BSD、EPL-2.0(Eclipse)、MPL-2.0。
Maven 侧的检查:
<!-- pom.xml -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<id>check-licenses</id>
<goals><goal>enforce</goal></goals>
<configuration>
<rules>
<bannedDependencies>
<excludes>
<!-- 防止引入 GPL 无例外的 Java 库 -->
<exclude>com.example:pure-gpl-lib</exclude>
</excludes>
</bannedDependencies>
</rules>
</configuration>
</execution>
</executions>
</plugin>更系统的方案是使用 SCA 工具自动化检查。
6.5 动态插件系统:宿主与插件的许可证边界
一个经常被忽略的场景:你的程序有插件机制,用户可以加载第三方 .so/.dll。
- 如果你的宿主是 GPL,那么用户加载的插件也必须 GPL(FSF 立场);
- 如果你的宿主是 LGPL,插件可以是任意许可证,但插件加载机制必须让用户可以替换 LGPL 部分;
- 如果你的宿主是专有,插件是 GPL:这个组合是危险的。FSF 认为「动态加载 GPL 插件」构成 combined work,整个宿主-插件组合必须 GPL。
Linux 内核是这个问题的经典战场:内核是 GPL-2.0,内核模块(.ko)如果和内核紧密耦合就必须 GPL-2.0。但 NVIDIA 闭源驱动多年来使用一个「shim 层」——一个开源的 GPL 小内核模块,通过它与闭源的二进制 blob 通信——来规避这个问题。FSF 明确反对,Linux 社区内部也有持续争议,至今仍是灰色地带。
6.6 SaaS 里的客户端 SDK
如果你做的是 SaaS,但同时给客户发一个 SDK(Python/Java/Go 的 client library),这个 SDK 的许可证就脱离了 AGPL 的网络交互语境——它被 convey 到客户手里,如果 SDK 依赖了 AGPL 库,SDK 就要以 AGPL 形式对外。
实践:SDK 通常采用 Apache-2.0 或 MIT 独立维护,与服务端的 AGPL 代码库严格隔离。
六点五、并排对比:一段真实的开源软件供应链
为了让上面的坑点更具体,下面用一个虚构但写实的产品「Acme Analytics」走一遍典型的开源供应链审计过程。
6.5.1 产品架构
┌─────────────────────────────────────────────────────────┐
│ 用户浏览器 │
│ └── bundle.js (webpack) │
│ ├── React (MIT) │
│ ├── Ant Design (MIT) │
│ ├── ECharts (Apache-2.0) │
│ └── X-license-unknown-grid (???) ← 红灯 │
└─────────────────────────────────────────────────────────┘
│ HTTPS
┌─────────────────────────────────────────────────────────┐
│ Acme Analytics Server (Go 1.22) │
│ ├── gin (MIT) │
│ ├── gorm (MIT) │
│ ├── readline-go (BSD-3-Clause) │
│ └── go-ffmpeg-bindings │
│ └── CGO → libavcodec (LGPL-2.1 / GPL-2.0) │
│ ↑ 动态链接?静态链接? │
└─────────────────────────────────────────────────────────┘
│ TCP
┌─────────────────────────────────────────────────────────┐
│ PostgreSQL 16 (PostgreSQL License, BSD-like) │
│ └── TimescaleDB extension (Apache-2.0 + TSL) │
│ TSL: Timescale License (source-available) │
└─────────────────────────────────────────────────────────┘
6.5.2 审计过程
第一步:前端 SBOM
cd frontend
npx @cyclonedx/cyclonedx-npm --output-format JSON --output-file sbom.json
cat sbom.json | jq '.components[] | {name, version, licenses}' | grep -iE "agpl|gpl|sspl"输出发现 x-license-unknown-grid 的 license
字段为空——这要么是作者忘了写,要么是故意不写。直接联系作者或从仓库
LICENSE 文件确认;如果是 AGPL,必须下架或替换。
第二步:Go 后端依赖
cd backend
go install github.com/google/go-licenses@latest
go-licenses report ./... > licenses.csv
awk -F',' '$3 ~ /GPL|AGPL/ {print}' licenses.csv这里的大坑是 CGO 链接的 native
库——go-licenses 只能看到 Go
源码里声明的,看不见
#cgo LDFLAGS: -lavcodec。需要额外手工审计所有
CGO 绑定。
第三步:native 库的许可证核查
# 在构建机器上看实际链接的动态库
ldd ./acme-analytics | grep -iE "avcodec|avformat"
apt-cache show libavcodec59 | grep -E "License|Source"
# 或者在 Debian 上
cat /usr/share/doc/libavcodec59/copyrightFFmpeg 的情况尤其复杂——同一个 FFmpeg 二进制可以编译成
LGPL-2.1 模式或 GPL-2.0 模式,取决于
--enable-gpl 选项。如果用发行版的
libavcodec,通常是
LGPL-2.1(因为发行版要保持商业友好);如果自己从源码编译,要特别注意是否启用了
GPL 模块(如 x264)。
第四步:数据库许可证
PostgreSQL License 是一个 BSD-like 的宽松许可,没有问题。但 TimescaleDB 的结构特殊:
- 开源核心部分 Apache-2.0;
- 企业增强部分(
ts_insert_blocker等)使用 Timescale License(TSL),一个 source-available 的非开源许可; - 两部分在同一个
.so扩展里,但通过宏隔离,加载时根据 license key 激活不同功能。
如果你只用 Apache-2.0 部分,无义务;如果用了 TSL 功能,TSL 禁止「提供 TimescaleDB-as-a-Service」——与 SSPL 类似的限制,但用的是不同的机制。
6.5.3 审计结论与行动项
| 组件 | 许可证 | 风险 | 行动 |
|---|---|---|---|
| React, Ant Design, ECharts | MIT / Apache-2.0 | 低 | 保留 NOTICE |
| X-license-unknown-grid | 未知 | 高 | 下架或替换 |
| gin, gorm | MIT | 低 | 保留 NOTICE |
| libavcodec(LGPL 构建) | LGPL-2.1 | 中 | 确保动态链接,加替换说明 |
| libavcodec(GPL 构建) | GPL-2.0 | 高 | 切换到 LGPL 构建,避免整体 GPL |
| PostgreSQL | PostgreSQL License | 低 | 保留 NOTICE |
| TimescaleDB TSL 部分 | Timescale License | 中 | 不提供作为托管服务 |
6.5.4 产物打包策略
# Multi-stage:build 阶段静态检查许可证,runtime 阶段最小化
FROM golang:1.22 AS build
WORKDIR /src
COPY . .
# 构建前先跑 license check,失败则不出镜像
RUN go install github.com/google/go-licenses@latest && \
go-licenses check --disallowed_types=forbidden,restricted ./...
RUN CGO_ENABLED=1 go build -o /out/acme ./cmd/acme
FROM debian:12-slim AS runtime
RUN apt-get update && apt-get install -y --no-install-recommends \
libavcodec59 ca-certificates tzdata && \
rm -rf /var/lib/apt/lists/*
COPY --from=build /out/acme /usr/local/bin/acme
COPY NOTICE WRITTEN-OFFER.txt /usr/share/doc/acme/
# 关键:不静态链接 libavcodec,让用户可以替换
ENTRYPOINT ["/usr/local/bin/acme"]七、合规义务清单
不论触发的是哪种 Copyleft,合规核心是三件事:
7.1 保留版权和许可证声明
所有源代码文件的头注释、所有依赖的 LICENSE 文件,都必须原样随产品/镜像分发。
project/
├── LICENSE # 你自己的许可证
├── NOTICE # 你的归属声明
└── third_party/
├── libzip/
│ ├── LICENSE # LGPL-2.1 原文
│ └── NOTICE # libzip 的版权声明
├── openssl/
│ └── LICENSE # Apache-2.0
└── ...
7.2 提供源代码(Written Offer)
对 GPL 家族,源代码交付有几种合规形式(见 GPLv3 §6):
- §6(a) 物理介质:随二进制一起发一张光盘/U 盘(极少见);
- §6(b) 书面要约:附带一份三年有效的要约,用户可以联系你要源码(常见);
- §6(d) 等价下载:提供一个 URL,用户可以下载相同版本的源码(推荐)。
书面要约的模板见 3.4 节的 WRITTEN-OFFER.txt。
7.3 NOTICE 文件的写法
一个典型的 NOTICE 文件:
MyApp 2.3.1
Copyright (c) 2024-2026 Acme Corp. All rights reserved.
This product includes the following third-party software:
1. libzip 1.10.1
Licensed under LGPL-2.1-or-later.
Source: https://libzip.org/
Modifications: none
Replacement: dynamic link (lib/libzip.so.5)
2. OpenSSL 3.2.0
Licensed under Apache-2.0.
Source: https://www.openssl.org/
Modifications: none
3. Linux kernel 6.1.73
Licensed under GPL-2.0-only.
Source: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
Tag: v6.1.73
Our patches: https://github.com/acme/linux-acme-6.1/compare/v6.1.73...acme-v6.1.73-rc1
4. BusyBox 1.36.1
Licensed under GPL-2.0-only.
Source: https://busybox.net/downloads/busybox-1.36.1.tar.bz2
Modifications: none
For the complete corresponding source code of any GPL/LGPL
component, please see section 3 of this NOTICE or contact
oss-compliance@acme.example within three years of your receipt
of this product.
7.4 给运维的一张检查表
八、中国案例:OpenHarmony 对 Linux 内核的合规处理
8.1 OpenHarmony 的架构与许可证
OpenHarmony(开放原子开源基金会托管)是华为主导、社区共建的操作系统。它实际包含三种形态:
- 轻量系统(LiteOS-M):自研微内核,Apache-2.0;
- 小型系统(LiteOS-A):自研,Apache-2.0;
- 标准系统:使用 Linux 内核(GPL-2.0-only)+ 自研 HDF 驱动框架(Apache-2.0)+ 自研 ArkUI/ArkTS 框架(Apache-2.0)。
标准系统里内核是 GPL-2.0,这就要求华为及所有分发者必须满足 GPL-2.0 §3 的源码交付义务。
8.2 合规做法
OpenHarmony 在 gitee.com/openharmony 组织下维护了:
kernel_linux_5.10:带华为补丁的 Linux 5.10 分支;kernel_linux_6.6:带华为补丁的 Linux 6.6 分支;third_party_*:所有上游 GPL/LGPL 依赖的同步仓库。
对应用层框架(ArkUI、ArkTS 等)则采用 Apache-2.0,避免把上层生态传染进 GPL。这是一种典型的「底层 GPL,上层 Apache-2.0」的隔离架构,与 Android 的思路一致。
8.3 HarmonyOS Next 的内核重写
根据华为 2024 年的公开说明,HarmonyOS Next(面向终端设备的商业发行版)据称完全采用自研 HongMeng 内核,不再使用 Linux。如果属实,这会让 HarmonyOS Next 完全脱离 GPL-2.0 的义务链条——这不是许可证层面的违规,而是通过工程替换合法地绕开 Copyleft。
与此类似,许多厂商在战略层面选择:
- 底层用 BSD 家族(FreeBSD 内核、LLVM)而非 GPL 家族(Linux、GCC);
- C 库用 Apache-2.0 的自研(如 Android 的 bionic)而非 glibc(LGPL-2.1)或 musl(MIT,但无品牌控制)。
这种选择的动机是减少对 GPL 生态的长期依赖——而不是反对开源。
8.4 反面案例:红芯浏览器事件
2018 年,北京红芯时代科技宣称发布「自主可控」的红芯浏览器,后被发现实际是 Chromium 的壳。这是一个许可证层面完全合规但技术叙事严重误导的典型案例:
- Chromium 的主许可是 BSD-3-Clause,允许商业化、修改和闭源分发;
- 红芯作为分发者,在许可证层面只需保留 BSD 的版权声明,即为合规;
- 问题出在对用户和投资人的事实陈述——宣称「自研内核」但未披露 Chromium 基础,属于商业伦理和广告法范畴,与开源许可证无关。
详细分析见 红芯 / 深度等国产软件的合规争议。
这个案例的开源工程学启示:宽松许可证给你提供了最大的商业自由,但不能替代对用户的诚信。
八点五、延伸:Copyleft 与现代开发模式的张力
8.5.1 Monorepo 与 Copyleft 边界
现代开发普遍使用 monorepo:一个巨大的 Git 仓库里放着几十个独立服务。Copyleft 边界在 monorepo 里变得微妙:
- 如果 monorepo 里有一个 AGPL 的子项目
services/analytics,另一个子项目services/billing是 Apache-2.0,两者是否「合并」? - 严格说,只要两个项目是独立的程序,不通过进程内链接共享代码,就是独立作品。即使代码在同一仓库。
- 但如果它们共享一个
libs/common工具库,并且这个工具库被 AGPL 服务和 Apache 服务都 import 了,libs/common的许可证必须兼容两者——即必须是 MIT/BSD/Apache 之类的宽松许可证。
Google 的 monorepo 策略:内部工具库永远使用
Apache-2.0(或 BSD-3-Clause),不允许把 GPL/AGPL 代码放进
//third_party。这不是法律要求,而是工程上为了避免跨项目污染。
8.5.2 微服务、gRPC 与 Copyleft
微服务架构下,服务之间通过 HTTP/gRPC 通信,每个服务是独立的进程、独立的二进制。FSF 明确表态:通过进程间通信(pipe、socket、RPC、REST)交互的程序不构成 combined work(GPL FAQ: “CommunicatingWithNonfreeProgram”)。
这意味着:
- 你的 Apache-2.0 网关可以调用一个 AGPL 的后端服务,网关本身不被传染;
- 但如果 AGPL 服务「通过网络对用户提供交互」,AGPL 服务本身(不包括网关)需要公开源码给远程用户。
注意远程用户的定义:AGPL-3.0 §13 说的是「users interacting with it remotely through a computer network」。如果是你公司内部的网关代为转发用户请求,那么 AGPL 义务仍然指向最终用户——他们是真正的 remote user。但这里的因果链有点绕,法律上尚未有清晰判例。
8.5.3 Kubernetes Operator 与 CRD 的许可证传染
许多开源项目以 Kubernetes Operator 形式发布(Prometheus Operator、Cert-Manager、ArgoCD 等)。Operator 本身是一个进程,通过 Kubernetes API 读写 CRD(Custom Resource Definition)。
- 如果 Operator 是 Apache-2.0,你部署它不产生任何义务;
- 如果 Operator 是 AGPL-3.0,且你修改了 Operator 源码并给多租户客户提供服务,AGPL 义务指向那些客户;
- 但 CRD 本身只是 YAML 结构定义,不是可版权保护的程序,不会传染。
8.5.4 AI / LLM 时代的新问题
2023 年以来一个新兴的问题:大语言模型(LLM)训练数据里包含大量 GPL 代码,模型输出的代码片段是否继承 GPL?
这是一个活跃争议:
- FSF 倾向:如果模型输出与训练集中的 GPL 代码有明显相似性,输出应视为衍生作品,受 GPL 约束;
- OpenAI / GitHub Copilot 倾向:训练是 fair use,输出不继承许可证;
- 法院:2022 年开始的 GitHub Copilot 集体诉讼尚未给出明确答案。
工程上的保守做法:
- 生产代码库设置 CI 检查,扫描 AI 生成片段是否与已知 GPL 代码相似;
- 使用 Copilot 等工具时启用「exclude suggestions matching public code」选项;
- 对高度敏感的商业代码禁用 AI 辅助。
九、选型建议
基于上面的分析,给出一份面向不同场景的许可证选型建议。
9.1 我要发布一个库,希望被广泛使用
- 首选:Apache-2.0 或 MIT。Apache-2.0 额外有专利条款(详见下一篇专利授权与商标),更适合企业贡献者。
- 不要用:GPL 家族。库用 GPL 会阻止大多数商业软件链接。
9.2 我要发布一个应用,希望强制下游回馈
- 桌面/命令行应用:GPL-3.0。用户必须拿到源码,修改分发必须 GPL-3.0。
- 网络服务:AGPL-3.0。额外堵住 SaaS 漏洞。
- 数据库/搜索引擎:AGPL-3.0 或 SSPL-1.0(后者更激进,不被 OSI 认可为开源)。
9.3 我要链接一个我不想被传染的库
- 优先:Apache-2.0、MIT、BSD、ISC 的等价库。
- 次选:LGPL-2.1 / LGPL-3.0,但必须动态链接,并提供替换说明。
- 避免:GPL-2.0 / GPL-3.0 的库(除非我的程序本身就是 GPL)。
9.4 我要打包 Docker 镜像
- 最干净:Go/Rust 静态二进制 + FROM scratch + 所有依赖都是 BSD/MIT/Apache。
- 次干净:Alpine 基础镜像(musl libc MIT + 核心工具 MIT)。
- 主流选择:Debian/Ubuntu + 利用 GPL-3.0 §1 的 System Library 例外。
- 合规动作:CI 里生成 SBOM,镜像里放 NOTICE 和 Written Offer。
9.5 我是云服务商
- 安全品类:Apache-2.0、MIT、BSD 的上游——托管无义务。
- 需要隔离:AGPL 上游——必须把修改版源码对远程用户开放。
- 几乎不可能:SSPL 上游——要公开整个管控面。
- 策略选择:如果上游迁移到 SSPL/AGPL,选择 fork 最后的 Apache 版本(Elasticsearch → OpenSearch 模式)或停止托管。
9.6 我做嵌入式
- 内核:必须使用 Linux 就接受 GPL-2.0 义务,按 kernel.org 的惯例发布内核源码。
- 用户空间:优先 Apache-2.0、MIT、BSD;LGPL 谨慎动态链接。
- 避免:GPL-3.0(反 Tivoization 让签名固件无法合规)。这是为什么许多嵌入式厂商使用 GCC 的最后 GPL-2.0 版本或切换到 LLVM。
十、参考资料
10.1 许可证原文
- GNU General Public License, version 2. https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- GNU General Public License, version 3. https://www.gnu.org/licenses/gpl-3.0.html
- GNU Lesser General Public License, version 2.1. https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
- GNU Lesser General Public License, version 3. https://www.gnu.org/licenses/lgpl-3.0.html
- GNU Affero General Public License, version 3. https://www.gnu.org/licenses/agpl-3.0.html
- Server Side Public License, version 1. https://www.mongodb.com/licensing/server-side-public-license
10.2 官方解释与 FAQ
- Frequently Asked Questions about the GNU Licenses. https://www.gnu.org/licenses/gpl-faq.html
- SPDX License List. https://spdx.org/licenses/
- OpenJDK GPL v2 + Classpath Exception. https://openjdk.org/legal/gplv2+ce.html
- Linux Kernel Licensing Rules. https://www.kernel.org/doc/html/latest/process/license-rules.html
- Open Source Initiative, “The Open Source Definition”. https://opensource.org/osd
10.3 工程实践与案例
- OpenHarmony Kernel Linux. https://gitee.com/openharmony/kernel_linux_5.10
- Xiaomi Kernel OpenSource. https://github.com/MiCode/Xiaomi_Kernel_OpenSource
- LineageOS Source. https://github.com/LineageOS
- FFmpeg Legal. https://www.ffmpeg.org/legal.html
- Docker Official Images Licensing. https://github.com/docker-library/official-images
10.4 学术与书籍
- Eben Moglen, “Free Software and the Death of Copyright,” 2001.
- Heather Meeker, “Open (Source) for Business: A Practical Guide to Open Source Software Licensing,” 2020.
- Lawrence Rosen, “Open Source Licensing: Software Freedom and Intellectual Property Law,” 2004.
- Andrew M. St. Laurent, “Understanding Open Source and Free Software Licensing,” O’Reilly, 2004.
10.5 工具
go-licenses— https://github.com/google/go-licenseslicense-checker(npm) — https://github.com/davglass/license-checker- CycloneDX — https://cyclonedx.org/
- SPDX Tools — https://github.com/spdx/tools
- FOSSology — https://www.fossology.org/
十一、本系列其他文章
- 开源许可与版权工程 · 总目录
- 开源许可证全景:宽松、弱 Copyleft、强 Copyleft、网络 Copyleft
- 专利授权与商标:Apache 2.0、GPLv3 与「兼容性」陷阱
- GPL 与 LGPL 实战:从内核模块到共享库
- AGPL / SSPL / BSL:网络时代的 Copyleft 与商业化变种
- 中国开源合规争议案例:红芯、深度与国产软件
- SCA 与 SBOM:自动化治理开源合规
免责声明:本文为工程技术文章,提供的是面向工程师的 Copyleft 判定思路与工程实践参考,不构成任何形式的法律意见。具体的合规事宜请咨询专业的知识产权律师或法务顾问。不同法域(美国、欧盟、中国大陆)对「衍生作品」「分发」「网络交互」的法律解释可能不一致,商业决策时请以当地法律与专业法律建议为准。文中提及的具体项目、公司与许可证信息基于写作时的公开资料,可能随时间变化,请以上游与官方最新公告为准。
上一篇:开源许可证全景:宽松、弱 Copyleft、强 Copyleft、网络 Copyleft
下一篇:专利授权与商标:Apache 2.0、GPLv3 与「兼容性」陷阱
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【开源许可与版权工程】闭源项目如何选择开源依赖:公司内部合规实操
面向做闭源/商业产品的团队:逐一拆解 MIT、LGPL、GPL、AGPL、SSPL、BSL 在 SaaS、私有化部署、移动 App、嵌入式固件等形态下的许可边界,给出三级名单模板、CI 扫描配置、SBOM 存证方案与出海补充要求。
【开源许可与版权工程】开源许可证全景:宽松、弱 Copyleft、强 Copyleft、网络 Copyleft
从 MIT 到 AGPL,从 SPDX 标识符到 OSI 认证:一篇讲清楚四类开源许可证的边界、兼容性矩阵、SSPL/BSL 的争议、Commons Clause 事件,以及工程里最常见的踩坑场景和选型建议。
【开源许可与版权工程】GPLv2、GPLv3、LGPL:Linux 内核为什么停在 v2
深入解析 GPLv2 到 GPLv3 的条款变化、Tivoization 反规避与 DRM 条款、专利终止条款;LGPL 链接例外的工程边界;以及 Linus Torvalds 拒绝升级到 v3 的真实原因与嵌入式生态影响。包含路由器厂商、国内 Android 设备的 GPL 合规真实案例。
【开源许可与版权工程】开源许可证实操手册:从选型到发布
面向工程团队的开源许可证完整操作手册:许可证选型决策树、LICENSE/NOTICE/SPDX 文件写法、第三方依赖声明、CI 自动化检查、发布物合规标注,以及六套真实可复制的项目结构模板。