本系列前二十篇把协议理论、历史案例、合规治理讲了个遍,但每次有工程师问「我的项目该怎么落地」,都需要翻好几篇文章凑答案。这篇是「做菜手册」——你打开它,照着抄,直接可以用。
本文假设读者已经对常见许可证有基本认知(如果没有,先看 开源许可证全景 和 MIT、BSD、Apache 2.0 详解)。文中所有命令均在 Linux/macOS 下验证过逻辑,CI 片段基于 GitHub Actions。
一、这篇文章怎么读
1.1 与系列其他篇的关系
本文是 01—20 篇的操作汇总,和以下几篇互补而非重复:
- 03-license-taxonomy:协议分类体系,选型前先理解分类逻辑。
- 06-mit-bsd-apache:MIT/BSD/Apache 2.0 条款逐条解读,NOTICE 义务详解。
- 07-gpl-lgpl:GPL 家族触发条件,供货文本(written offer)模板。
- 08-agpl-sspl-bsl:Elastic/Sentry 改协议历史,AGPL 网络触发机制。
- 16-sca-sbom:SCA/SBOM 工具链的完整自动化方案。
- 18-cla-dco:CLA/DCO 签署流程,贡献者协议。
- 22-closed-source-deps:闭源项目使用开源依赖的合规策略。
1.2 阅读地图
| 你想做什么 | 直接跳到 |
|---|---|
| 给新项目选协议 | §二 |
| 写 LICENSE 文件 | §三 |
| 给源文件加头 | §四 |
| 处理 Copyright 声明 | §五 |
| 处理 NOTICE 文件 | §六 |
| 组织第三方依赖目录 | §七 |
| 生成 THIRD_PARTY_NOTICES | §八 |
| 打包发布时的合规要求 | §九 |
| README 和 About 页最小要求 | §十 |
| 复制整套项目结构模板 | §十一 |
| 变更已有项目的许可证 | §十二 |
| 中国特殊场景 | §十三 |
| 排查已知工程坑 | §十四 |
1.3 贯穿全文的原则
- SPDX 优先:所有许可证标识符使用 SPDX
表达式(
Apache-2.0、GPL-2.0-only、MIT OR Apache-2.0),而非自然语言。SPDX(Software Package Data Exchange)是 Linux 基金会维护的开放标准,详见 https://spdx.org/licenses/。 - 机器可读:LICENSE 文件、SPDX 头、package manifest 字段都要让工具能自动扫描,人可读只是附带好处。
- 义务最小化原则:在满足合规要求的前提下,选择义务最少的路径,降低维护负担。
二、给你的项目选一个协议(三问决策树)
决策树如文章顶部 SVG 所示,三问浓缩如下:
2.1 三个问题
问题一:是否担心 SaaS 服务商「白嫖」?
所谓「白嫖」指他人将你的代码包进云服务直接售卖,却不向你回馈代码也不付费。典型案例:AWS 基于 Elasticsearch 推出 Amazon Elasticsearch Service,而 Elastic 公司认为 AWS 未回馈社区。如果这一场景让你不安,进入左分支;否则进入右分支。
问题二(左分支——担心白嫖):是否仍希望闭源商业产品可以内嵌?
若是,则代码的「开源」主要是公关/生态目的,但你需要商业利益保护 → 考虑 BSL(Business Source License)或双许可(开源 + 商业许可证)。若否,则你希望任何产品用了你的代码都必须回馈 → AGPL-3.0(需专利明示)或 GPL-3.0-or-later。
问题二(右分支——不担心白嫖):是否希望闭源商业产品可以无条件内嵌?
若是,继续第三问。若否(即希望基于你的库开发的程序,至少「文件级」修改要开源)→ MPL-2.0 或 LGPL-2.1。
问题三(右分支是):是否需要显式专利授权条款?
若是 → Apache-2.0(含专利授权 + 专利反制条款)。若否 → MIT 或 BSD-3-Clause。
2.2 决策速查表
| 需求组合 | 推荐协议 | SPDX 标识符 |
|---|---|---|
| 最大传播、无专利要求 | MIT | MIT |
| 最大传播、不得以原作者名义背书 | BSD-3-Clause | BSD-3-Clause |
| 宽松、含专利授权、企业首选 | Apache 2.0 | Apache-2.0 |
| 宽松、Rust 生态双许可 | MIT OR Apache-2.0 | MIT OR Apache-2.0 |
| 弱 copyleft、文件级传染 | Mozilla Public License 2.0 | MPL-2.0 |
| 弱 copyleft、库链接豁免 | GNU Lesser GPL 2.1 | LGPL-2.1-or-later |
| 强 copyleft、分发触发 | GPL 3.0 | GPL-3.0-or-later |
| 强 copyleft、网络触发(反 SaaS) | AGPL 3.0 | AGPL-3.0-only |
| 商业保护 + 延迟开源 | Business Source License | BUSL-1.1 |
| 中国司法管辖适配 | 木兰宽松许可证 v2 | MulanPSL-2.0 |
2.3 双许可(dual-license)的条件
双许可要求:所有贡献者都必须已签 CLA,将版权或至少使用权转让给项目持有人,才能对外宣布双许可。关于 CLA 流程,见 CLA、DCO 与贡献者协议。
三、LICENSE 文件
3.1 基本规则
- LICENSE 文件必须位于仓库根目录。
- 文件名约定(各协议惯例):
| 协议 | 推荐文件名 |
|---|---|
| MIT、BSD、Apache 2.0 | LICENSE 或 LICENSE.txt |
| GPL 家族 | COPYING(FSF 传统)或
LICENSE |
| LGPL 附加例外 | COPYING + COPYING.LESSER |
| Apache 2.0 | LICENSE +
NOTICE(必须同时存在) |
| 多协议项目 | LICENSE(主协议)+
LICENSE-<name> |
- 文件内容:许可证完整文本,不得只放超链接。
- 如果项目包含多种协议的代码(如主体 Apache-2.0,部分文件 MIT),在 README 里说明,并在对应子目录放各自的 LICENSE。
3.2 官方文本获取方式
不要手打许可证原文,从官方渠道下载:
# Apache-2.0
curl -o LICENSE https://www.apache.org/licenses/LICENSE-2.0.txt
# GPL-3.0
curl -o LICENSE https://www.gnu.org/licenses/gpl-3.0.txt
# LGPL-3.0
curl -o COPYING.LESSER https://www.gnu.org/licenses/lgpl-3.0.txt
# MIT(SPDX 托管版本)
curl -o LICENSE https://spdx.org/licenses/MIT.txt
# MulanPSL-2.0
curl -o LICENSE https://license.coscl.org.cn/MulanPSL2/license.txt3.3 各协议 LICENSE 文件模板(填空部分)
以下模板只展示需要人工填写的占位符部分,完整正文请从官方 URL 获取(§3.2)。
MIT
MIT License
Copyright (c) [yyyy]-[yyyy] [持有人姓名或公司名]
Permission is hereby granted...(此处粘贴 MIT 官方正文)
填写规则: - [yyyy]
填项目创建年份到当前年份,如
2021-2026;若只有一年填单年 2026。
- [持有人]
填个人真实姓名或公司全称(法人名称),不填昵称。
BSD-3-Clause
BSD 3-Clause License
Copyright (c) [yyyy], [持有人]
All rights reserved.
Redistribution and use...(粘贴官方正文)
Neither the name of [持有人/项目名] nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
第三条(non-endorsement clause)是 BSD-3 相对 BSD-2
增加的,其中 [持有人/项目名]
需要填你的实际名称,否则该条款无意义。
Apache-2.0
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
(此处粘贴 Apache 2.0 官方正文全文)
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
注意:Apache 2.0 官方文本底部有一段
APPENDIX,其中有填空: - [yyyy]
填版权年份范围。 - [name of copyright owner]
填公司或个人全名。 这段 APPENDIX 文字本身不放在
LICENSE 文件里,它是给源文件头部用的(见
§四)。LICENSE 文件只放官方正文。
GPL-2.0-only
(粘贴 GNU GPL v2 全文,来自 https://www.gnu.org/licenses/gpl-2.0.txt)
如果用 GPL-2.0-or-later(“v2 or
later”),在文件末尾附注:
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GPL-3.0-or-later
(粘贴 GNU GPL v3 全文,来自 https://www.gnu.org/licenses/gpl-3.0.txt)
AGPL-3.0-only
(粘贴 GNU AGPL v3 全文,来自 https://www.gnu.org/licenses/agpl-3.0.txt)
AGPL 和 GPL v3 文本几乎完全相同,只是第 13 节(Remote Network Interaction)不同。请务必从官方下载,不要把 GPL v3 错用为 AGPL。
MPL-2.0
(粘贴 Mozilla Public License 2.0 全文,来自 https://www.mozilla.org/media/MPL/2.0/index.txt)
MPL-2.0 文件级 copyleft:只要求你修改的 .js/.go/.py 等文件在分发时开源,未修改的和新增的业务文件不受影响。
MulanPSL-2.0(木兰宽松许可证第2版)
(粘贴木兰宽松许可证第2版全文,来自 https://license.coscl.org.cn/MulanPSL2/license.txt)
版权所有 (c) [yyyy] [版权持有人]
木兰宽松许可证同时提供中英双语正文,中英文版本具有同等法律效力。
四、SPDX 头:源文件级声明
4.1 为什么要加 SPDX-License-Identifier
一个文件脱离仓库之后(例如被复制、被打包、被二次分发),LICENSE 文件可能不再随行。SPDX 头(SPDX header)在每个源文件内部声明了该文件的协议,让任何扫描工具、任何开发者都能在不依赖仓库上下文的情况下确认授权状态。
Linux 内核、Zephyr RTOS、CNCF 多数项目都强制要求每个文件都有 SPDX 头。
4.2 SPDX 头格式
最简形式(任何语言,注释符号替换为本语言的注释方式):
SPDX-License-Identifier: Apache-2.0
SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
REUSE(见 §4.5)规范要求: 1.
SPDX-License-Identifier: 后接 SPDX 表达式。 2.
SPDX-FileCopyrightText: 后接标准 copyright
声明。
4.3 各主流语言注释格式
C / C++ / Java / Go / Rust / JavaScript / TypeScript
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0Python
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0Shell(Bash / sh)
#!/usr/bin/env bash
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.注意:shebang 行(#!)必须是第一行,SPDX
头紧接其后。
YAML / Helm Chart
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
---
apiVersion: apps/v1
kind: DeploymentMarkdown / reStructuredText
<!--
SPDX-License-Identifier: Apache-2.0
SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
-->XML / HTML
<!--
SPDX-License-Identifier: Apache-2.0
SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
-->Dockerfile
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
FROM ubuntu:24.04Go(完整模板,Apache-2.0)
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package exampleRust(完整模板,MIT OR Apache-2.0)
// SPDX-License-Identifier: MIT OR Apache-2.0
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
//! 模块文档注释放在 SPDX 头之后。4.4 Linux 内核 / Zephyr / CNCF 实践
Linux 内核:自 4.16
起,内核强制要求所有新提交的文件包含
SPDX-License-Identifier:。内核代码库包含超过
500 种不同的 SPDX 标识符组合,由
scripts/spdxcheck.py 在 CI 中验证。
Zephyr RTOS:使用 west
构建工具集成 reuse lint,拒绝不含 SPDX
头的文件合并。
CNCF
项目(Kubernetes、Prometheus、containerd 等):通过
addlicense 工具在 CI 中检查并自动修复缺失的
SPDX 头。
4.5 REUSE 规范(reuse.software)
REUSE(Reuse Everything Uniformly Specified and Easily)是 FSFE(自由软件基金会欧洲分部)制定的许可证合规规范,核心要求:
- 每个源文件包含
SPDX-License-Identifier:和SPDX-FileCopyrightText:。 - 每种用到的许可证全文保存在
LICENSES/目录(文件名为<SPDX-ID>.txt,如LICENSES/Apache-2.0.txt)。 - 可选:对无法修改头部的二进制文件,在
.reuse/dep5文件中批量声明。
仓库根/
├── LICENSES/
│ ├── Apache-2.0.txt
│ └── MIT.txt
├── .reuse/
│ └── dep5 # 二进制文件的批量声明
├── src/
│ └── main.go # 含 SPDX 头
└── LICENSE # 指向主协议(可与 LICENSES/ 共存)
安装与使用 reuse lint
# 安装
pip install reuse
# 检查仓库合规性
reuse lint
# 为某个文件批量添加 SPDX 头(--force-dot-license 跳过二进制)
reuse annotate --license Apache-2.0 --copyright "Copyright (c) 2026 Example Corp." \
src/**/*.go
# 生成 REUSE SPDX SBOM
reuse spdx -o sbom.spdxreuse lint 输出示例:
* Missing license information for:
- assets/logo.png
- docs/diagrams/arch.svg
SUMMARY
* Used licenses: Apache-2.0, MIT
* Files with copyright information: 42 / 44
* Files with license information: 42 / 44
Unfortunately, not all files have license and copyright information.
.reuse/dep5 批量声明二进制文件:
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: my-project
Upstream-Contact: team@example.com
Source: https://github.com/example/my-project
Files: assets/*.png assets/*.svg docs/diagrams/*.svg
Copyright: 2024-2026 Example Corp.
License: Apache-2.0
五、Copyright notice
5.1 格式规范
标准 copyright 声明格式:
Copyright (c) 2020-2026 Example Corp. All rights reserved.
或(更简洁,MIT 惯例):
Copyright (c) 2020-2026 Example Corp.
说明: - (c) 是 © 符号的 ASCII
替代,法律效力相同。 -
年份范围:起始年份填首次发布年份,结束年份填最近一次有实质性代码变更的年份。
- All rights reserved
在宽松许可证下是冗余的(因为已通过 LICENSE
授权),但保留无害。
5.2 年份更新策略
争议点:每年维护是否需要更新 copyright 年份?
实务答案:
- 按美国版权法,copyright 声明中的年份标注首次发表时间,后续修改不需要更新年份也受保护。
- 按 FSF 指引,每次实质性修改都建议更新到最新年份,以便明确保护范围。
- 工程建议:使用范围格式(
2020-2026),每次大版本发布时 CI 自动更新结尾年份。
# 使用 addlicense 批量更新年份(-y 不指定则使用当前年份)
go install github.com/google/addlicense@latest
addlicense -c "Example Corp." -l apache -y 2020-2026 ./...5.3 贡献者署名策略
个人持有:Copyright (c) 2024 Alice Wang
法人持有(推荐企业项目):Copyright (c) 2024 Example Corp.
CLA 转让后持有:若使用 CLA
要求贡献者将版权转让给项目法人,则统一写法为法人持有,贡献者署名通过
AUTHORS 文件体现。
DCO 模式:每个贡献者保留其贡献部分的版权,文件头可能出现多行:
// SPDX-FileCopyrightText: Copyright (c) 2024 Alice Wang
// SPDX-FileCopyrightText: Copyright (c) 2025 Bob Chen
5.4 AUTHORS / CONTRIBUTORS 文件
多贡献者项目通常在根目录维护:
AUTHORS # 版权持有人列表(有贡献版权的人)
CONTRIBUTORS # 贡献者列表(含只提过 PR 的人)
AUTHORS 文件示例:
# This file lists the copyright holders for this project.
# For a full list of contributors, see git log or CONTRIBUTORS.
Example Corp. <legal@example.com>
Alice Wang <alice@example.com> # Original author, 2020-2022
CONTRIBUTORS 文件示例:
# Contributors to this project (alphabetical by last name):
Bob Chen <bob@example.com>
David Li <david@example.com>
Alice Wang <alice@example.com>
自动从 git log 生成 CONTRIBUTORS(供参考,仅列出提交数 ≥1 的作者):
git log --format='%aN <%aE>' | sort -u > CONTRIBUTORS六、NOTICE 文件(Apache 2.0 必须)
6.1 什么时候必须有 NOTICE 文件
Apache 2.0 第 4 条(Redistribution)明确:
If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file.
结论: - 你的项目是 Apache-2.0 → 必须提供 NOTICE 文件(即便内容很简单)。 - 你引用了一个 Apache-2.0 的库 → 必须在你的发布物中保留该库的 NOTICE 内容(合并或原样附带均可)。 - MIT、BSD、GPL 项目 → NOTICE 文件不是强制要求(但习惯上 GPL 项目用 COPYING)。
6.2 NOTICE 文件最小内容
My Awesome Project
Copyright 2024-2026 Example Corp.
This product includes software developed by
Example Corp. (https://example.com/).
6.3 引入多个 Apache-2.0 库时的 NOTICE 合并
假设你的项目(Apache-2.0)依赖了以下库:
- grpc-go(Apache-2.0,Google LLC 版权)
- prometheus/client_golang(Apache-2.0,Prometheus 作者版权)
- zap(MIT,Uber Technologies 版权)
合并后的 THIRD_PARTY_NOTICES.txt 或扩展
NOTICE 文件:
My Project
Copyright 2024-2026 Example Corp.
=============================================================
Dependency: google.golang.org/grpc (grpc-go)
License: Apache-2.0
Copyright 2014 gRPC authors.
NOTICE content:
Copyright 2014 gRPC authors.
Licensed under the Apache License, Version 2.0...
(以下为 grpc-go/NOTICE 原文)
=============================================================
Dependency: github.com/prometheus/client_golang
License: Apache-2.0
Copyright 2012-2015 The Prometheus Authors
NOTICE content:
(以下为 prometheus/client_golang/NOTICE 原文)
=============================================================
Dependency: go.uber.org/zap
License: MIT
Copyright (c) 2016-2022 Uber Technologies, Inc.
(MIT 无 NOTICE 文件,copyright 声明在此处保留即可满足义务)
=============================================================
6.4 自动化生成 NOTICE 与第三方声明
Go
# 安装 go-licenses
go install github.com/google/go-licenses@latest
# 生成 CSV 报告
go-licenses report ./... > third_party_licenses.csv
# 直接保存所有依赖 LICENSE 文本
go-licenses save ./... --save_path=./third_party/
# 检查是否有禁止的协议(如 GPL)
go-licenses check ./... --allowed_licenses=MIT,Apache-2.0,BSD-2-Clause,BSD-3-Clause,ISCNode.js
# 安装
npm install -g license-checker
# 生成 JSON 报告
license-checker --production --json > licenses.json
# 生成 Markdown 格式的第三方声明
license-checker --production --markdownTable > THIRD_PARTY_NOTICES.md
# 只允许指定协议(CI 检查用)
license-checker --production \
--onlyAllow "MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;0BSD;CC0-1.0;CC-BY-3.0;CC-BY-4.0"Python
pip install pip-licenses
# 生成 Markdown 格式
pip-licenses --format=markdown --with-urls --with-description \
--output-file=THIRD_PARTY_NOTICES.md
# 仅列出非 MIT/Apache 协议(用于审查)
pip-licenses --fail-on="GPL;LGPL;AGPL" --format=plain-verticalRust / Cargo
# 安装 cargo-about
cargo install cargo-about
# 初始化配置
cargo about init
# 生成 HTML 报告
cargo about generate about.hbs > THIRD_PARTY_NOTICES.html
# 生成 JSON
cargo about generate --format json > licenses.jsoncargo-about 的 about.toml
配置示例:
[accepted]
licenses = [
"MIT",
"Apache-2.0",
"BSD-2-Clause",
"BSD-3-Clause",
"ISC",
"Unicode-DFS-2016",
"CC0-1.0",
]
[ignored.crates]
# 忽略只在 dev 环境用的 crate
criterion = "*"Java / Maven
<!-- pom.xml 中添加 license-maven-plugin -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>2.3.0</version>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
<thirdPartyFilename>THIRD_PARTY_NOTICES.txt</thirdPartyFilename>
<failIfWarning>true</failIfWarning>
<includedLicenses>
<includedLicense>Apache-2.0</includedLicense>
<includedLicense>MIT</includedLicense>
<includedLicense>BSD-2-Clause</includedLicense>
<includedLicense>BSD-3-Clause</includedLicense>
</includedLicenses>
</configuration>
<executions>
<execution>
<id>aggregate-add-third-party</id>
<goals>
<goal>aggregate-add-third-party</goal>
</goals>
<phase>generate-resources</phase>
</execution>
</executions>
</plugin>Docker 镜像层
# 使用 syft 扫描镜像并生成 SBOM
syft myimage:latest -o spdx-json > sbom.spdx.json
# 使用 ort(OSS Review Toolkit)分析整个项目
ort analyze -i . -o ort-results/
ort report -i ort-results/analyzer-result.yml \
-o ort-reports/ -f PlainTextTemplate七、third_party 目录组织
7.1 目录结构约定
仓库根/
├── third_party/
│ ├── libcurl/
│ │ ├── LICENSE # libcurl 的 LICENSE 原文
│ │ ├── README.md # 出处、版本、修改说明
│ │ └── src/ # 源码(若直接内嵌)
│ ├── jsmn/
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── jsmn.h # 单文件库直接放这里
│ └── openssl/
│ ├── LICENSE # OpenSSL License + SSLeay License
│ ├── README.md
│ └── include/
└── THIRD_PARTY_NOTICES.txt # 自动生成或手工汇总
7.2 README.md 必须说明的内容
每个 third_party/<lib>/README.md
必须包含:
# libcurl
- **来源**:https://curl.se/libcurl/
- **版本**:8.6.0(commit: a8e5f3b)
- **许可证**:curl License(MIT 风格),见 LICENSE 文件
- **修改内容**:
- 移除了 FTP 协议支持(`lib/ftp.c` 已删除)
- 在 `lib/url.c` 中增加了对 IPv6 zone ID 的处理(见 patch/ipv6-zoneid.patch)
- **上游状态**:修改未提交上游
> 根据 curl License,修改内容须保留原始 Copyright 声明和免责声明。7.3 fork / patched 代码的修改声明义务
| 原协议 | 义务 |
|---|---|
| MIT | 保留 Copyright notice + LICENSE,无需声明修改内容(但 README 里写清楚是好习惯)。 |
| BSD-3-Clause | 同 MIT,另外不得用原作者名义背书你的修改版。 |
| Apache-2.0 | 必须在修改的文件中添加「此文件已被修改」声明(第 4 条 b 款),并保留 NOTICE 文件。 |
| GPL-2.0 / GPL-3.0 | 修改的文件头部必须注明修改日期和修改内容,并在分发时随附或可获得完整源码。 |
| LGPL-2.1 | 同 GPL 要求,另外允许以链接方式与闭源程序结合,但 LGPL 部分修改后的源码必须可获得。 |
| MPL-2.0 | 修改的文件必须在分发时以 MPL-2.0 开源,其余文件不受限制。 |
Apache-2.0 修改声明示例(在修改的文件头部):
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
//
// This file has been modified from the original source.
// Original source: https://github.com/original/repo
// Modifications:
// - 2025-03-01: Added IPv6 zone ID support (Author: Bob Chen)
// - 2026-01-15: Removed FTP protocol (Author: Alice Wang)八、生成 THIRD_PARTY_NOTICES / LICENSES.txt
8.1 各语言工具命令速查
Go 项目
# 生成 THIRD_PARTY_NOTICES.txt
go-licenses report ./... --template=third_party_notices.tpl \
> THIRD_PARTY_NOTICES.txt
# 自定义模板 third_party_notices.tpl(Go text/template 语法)
# {{range .}}
# ================================================================
# {{.Name}} {{.Version}}
# License: {{.LicenseID}}
# URL: {{.LicenseURL}}
# {{end}}Node.js 项目
# 生成 LICENSES.txt(包含完整 LICENSE 文本)
license-checker --production --csv > licenses.csv
license-checker --production --out THIRD_PARTY_NOTICES.txt \
--customFormat '{"name":"","version":"","licenses":"","copyright":"","licenseText":""}'Rust 项目
# 生成 about.html(包含每个 crate 的 LICENSE 全文)
cargo about generate about.hbs
# 简洁 text 格式(需自定义模板 about.hbs)about.hbs 最小模板示例:
{{#each overview}}
================================================================
Package: {{name}} {{version}}
License: {{expr}}
{{#if license.text}}
{{license.text}}
{{/if}}
{{/each}}
Java / Maven 项目
mvn license:aggregate-add-third-party
# 输出文件位置:target/generated-sources/license/THIRD-PARTY.txtPython 项目
pip-licenses --format=plain-vertical \
--with-license-file \
--output-file=THIRD_PARTY_NOTICES.txtDocker 镜像
# syft 扫描并生成 SPDX SBOM
docker pull myimage:latest
syft myimage:latest -o spdx-json=sbom.spdx.json
# 从 SBOM 提取协议信息
cat sbom.spdx.json | jq '[.packages[] | {name:.name, version:.versionInfo, license:.licenseConcluded}]'8.2 示例输出片段
以 Go 项目 go-licenses report 输出为例:
github.com/google/uuid,https://github.com/google/uuid/blob/v1.6.0/LICENSE,BSD-3-Clause
github.com/prometheus/client_golang,https://github.com/prometheus/client_golang/blob/v1.19.0/LICENSE,Apache-2.0
go.uber.org/zap,https://github.com/uber-go/zap/blob/v1.27.0/LICENSE,MIT
golang.org/x/net,https://cs.opensource.google/go/x/net/+/v0.24.0:LICENSE,BSD-3-Clause
google.golang.org/grpc,https://github.com/grpc/grpc-go/blob/v1.63.2/LICENSE,Apache-2.0
8.3 CI 集成:license-check YAML 片段
GitHub Actions(Go 项目)
# .github/workflows/license-check.yml
name: License Check
on:
pull_request:
paths:
- 'go.mod'
- 'go.sum'
- '**/*.go'
jobs:
license-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Install go-licenses
run: go install github.com/google/go-licenses@latest
- name: Check allowed licenses
run: |
go-licenses check ./... \
--allowed_licenses=MIT,Apache-2.0,BSD-2-Clause,BSD-3-Clause,ISC,0BSD,\
MPL-2.0,CC0-1.0,Unlicense,BlueOak-1.0.0
- name: Generate THIRD_PARTY_NOTICES
run: |
go-licenses report ./... > THIRD_PARTY_NOTICES.txt
git diff --exit-code THIRD_PARTY_NOTICES.txt || \
(echo "THIRD_PARTY_NOTICES.txt is outdated, run: go-licenses report ./... > THIRD_PARTY_NOTICES.txt" && exit 1)GitHub Actions(Node.js 项目)
# .github/workflows/license-check.yml
name: License Check
on:
pull_request:
paths:
- 'package.json'
- 'package-lock.json'
jobs:
license-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- name: Check licenses
run: |
npx license-checker --production \
--onlyAllow "MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;0BSD;\
CC0-1.0;CC-BY-3.0;CC-BY-4.0;BlueOak-1.0.0;Python-2.0" \
--excludePrivatePackages \
--excludePackages "my-private-package"
- name: Generate THIRD_PARTY_NOTICES
run: |
npx license-checker --production --markdownTable \
> THIRD_PARTY_NOTICES.md
git diff --exit-code THIRD_PARTY_NOTICES.md || \
(echo "THIRD_PARTY_NOTICES.md outdated" && exit 1)GitHub Actions(Rust 项目)
# .github/workflows/license-check.yml
name: License Check
on:
pull_request:
paths:
- 'Cargo.toml'
- 'Cargo.lock'
jobs:
license-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install cargo-deny
uses: taiki-e/install-action@cargo-deny
- name: Check licenses with cargo-deny
run: cargo deny check licenses
- name: Install cargo-about
run: cargo install cargo-about
- name: Generate notices
run: |
cargo about generate about.hbs > THIRD_PARTY_NOTICES.html
git diff --exit-code THIRD_PARTY_NOTICES.html || \
(echo "THIRD_PARTY_NOTICES.html outdated" && exit 1)deny.toml(cargo-deny 配置):
[licenses]
allow = [
"MIT",
"Apache-2.0",
"Apache-2.0 WITH LLVM-exception",
"BSD-2-Clause",
"BSD-3-Clause",
"ISC",
"Unicode-DFS-2016",
"CC0-1.0",
"0BSD",
]
deny = [
"GPL-2.0",
"GPL-3.0",
"AGPL-3.0",
"LGPL-2.0",
"LGPL-2.1",
"LGPL-3.0",
]
copyleft = "warn"
private = { ignore = true }GitLab CI(Python 项目)
# .gitlab-ci.yml 片段
license-check:
stage: test
image: python:3.12-slim
script:
- pip install pip-licenses
- pip install -r requirements.txt
- pip-licenses --fail-on="GPL;LGPL;AGPL" \
--allow-only="MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;
Python-2.0;Public Domain;CC0-1.0;Unlicense" \
--format=plain-vertical
only:
changes:
- requirements.txt
- requirements*.txt
- setup.py
- pyproject.toml九、发布物上的协议声明
9.1 源码 tarball
# 打 tarball 时确保 LICENSE 和 NOTICE 在根目录
tar czf myproject-1.0.0.tar.gz \
--exclude='.git' \
--exclude='node_modules' \
--exclude='.venv' \
myproject-1.0.0/
# 验证 LICENSE 文件已包含
tar tzf myproject-1.0.0.tar.gz | grep -E "LICENSE|NOTICE|COPYING"输出应包含:
myproject-1.0.0/LICENSE
myproject-1.0.0/NOTICE
myproject-1.0.0/THIRD_PARTY_NOTICES.txt
9.2 二进制发布物
安装包(.deb / .rpm / .msi / .pkg):
- LICENSE 文件打包进
/usr/share/doc/<package>/或等效位置。 - 若为 GPL 分发,还需随附完整源码(或附书面要约 written offer,见 GPLv2/v3 详解)。
About 对话框(GUI 应用):
About 对话框至少需要展示: 1. 项目名称 + 版本号。 2. 本项目的协议名称(如 Apache License 2.0)及全文链接。 3. 第三方依赖声明(「This product includes third-party software, see THIRD_PARTY_NOTICES.html for details」)。
9.3 Docker 镜像
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
FROM ubuntu:24.04
# OCI 标准镜像注解(org.opencontainers.image.*)
LABEL org.opencontainers.image.title="My Service"
LABEL org.opencontainers.image.version="1.0.0"
LABEL org.opencontainers.image.description="Example microservice"
LABEL org.opencontainers.image.url="https://github.com/example/my-service"
LABEL org.opencontainers.image.source="https://github.com/example/my-service"
LABEL org.opencontainers.image.licenses="Apache-2.0"
LABEL org.opencontainers.image.vendor="Example Corp."
LABEL org.opencontainers.image.authors="team@example.com"
# 将 LICENSE 和 THIRD_PARTY_NOTICES 打入镜像
COPY LICENSE /usr/share/doc/my-service/LICENSE
COPY NOTICE /usr/share/doc/my-service/NOTICE
COPY THIRD_PARTY_NOTICES.txt /usr/share/doc/my-service/THIRD_PARTY_NOTICES.txtorg.opencontainers.image.licenses
字段值:SPDX 表达式,如
Apache-2.0、MIT、GPL-2.0-only。
9.4 包管理器 manifest 字段
npm(package.json)
{
"name": "my-library",
"version": "1.0.0",
"license": "Apache-2.0",
"author": "Example Corp. <legal@example.com>",
"repository": {
"type": "git",
"url": "https://github.com/example/my-library.git"
}
}双许可写法:
{
"license": "(MIT OR Apache-2.0)"
}PyPI(pyproject.toml / setup.cfg)
# pyproject.toml
[project]
name = "my-library"
version = "1.0.0"
license = {text = "Apache-2.0"}
# 或者引用文件
# license = {file = "LICENSE"}
classifiers = [
"License :: OSI Approved :: Apache Software License",
]# setup.cfg(旧格式)
[metadata]
name = my-library
version = 1.0.0
license = Apache-2.0
license_files = LICENSE
NOTICE
THIRD_PARTY_NOTICES.txtMaven(pom.xml)
<project>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<distribution>repo</distribution>
</license>
</licenses>
</project>Cargo(Cargo.toml)
[package]
name = "my-crate"
version = "1.0.0"
edition = "2021"
license = "MIT OR Apache-2.0"
license-file = "LICENSE" # 若只用单许可证
repository = "https://github.com/example/my-crate"Go module(go.mod 不含协议字段,靠根目录 LICENSE)
Go module 没有专门的 license 字段,工具链(如
go-licenses、pkg.go.dev)通过扫描根目录
LICENSE 文件识别协议。确保根目录 LICENSE 文件存在即可。
9.5 Android APK
Android 生态惯例:在 Settings > About > Open Source Licenses(或 App > About > Open source licenses)展示第三方 OSS 声明。
使用 Google Play Services OSS Plugin 自动生成(Gradle):
// build.gradle (app)
plugins {
id 'com.google.android.gms.oss-licenses-plugin' version '0.10.6'
}
dependencies {
implementation 'com.google.android.gms:play-services-oss-licenses:17.1.0'
}// 在 About 页启动 OssLicensesMenuActivity
OssLicensesMenuActivity.setActivityTitle(getString(R.string.custom_licenses_title))
startActivity(Intent(this, OssLicensesMenuActivity::class.java))如果不用 Google Play Services(如纯 AOSP 应用),使用
AboutLibraries 库:
// build.gradle.kts
plugins {
id("com.mikepenz.aboutlibraries.plugin") version "11.1.0"
}9.6 iOS App(Settings Bundle)
iOS 惯例:将第三方声明以 Property List(.plist)格式放在
Settings.bundle/Acknowledgements.plist,可在「设置
> 隐私 > 致谢」中显示。
# 使用 LicensePlist 工具自动生成
brew install mono0926/license-plist/licenseplist
# 在项目根目录运行(需先 pod install 或 swift package resolve)
licenseplist --output-path MyApp/Settings.bundle
# 生成文件:Settings.bundle/Root.plist + Settings.bundle/Acknowledgements.plistAcknowledgements.plist 片段:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>FooterText</key>
<string>Alamofire
Copyright (c) 2014-2024 Alamofire Software Foundation
Permission is hereby granted, free of charge...(MIT 正文)</string>
<key>Title</key>
<string>Alamofire</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
</array>
</dict>
</plist>9.7 嵌入式设备(路由器 / 摄像头)
嵌入式 Linux 产品通常包含 GPL/LGPL 内核和驱动,必须满足 GPL 的源码提供义务(§3 or §3b of GPLv2)。
书面要约(Written Offer)模板(置于产品手册、Web 界面或包装说明中,有效期不少于三年):
Source Code Availability Notice
This product contains software distributed under the GNU General Public
License version 2 (GPLv2) and/or the GNU Lesser General Public License
version 2.1 (LGPLv2.1).
To obtain the complete corresponding source code for GPL/LGPL-licensed
components included in this product, please visit:
https://opensource.example.com/source
Or send a written request (valid for 3 years from the date of product
purchase) to:
Open Source Compliance Team
Example Corp., Legal Department
Building A, 123 Tech Road, Shenzhen, Guangdong 518000, China
Email: opensource@example.com
Please include your product model number, firmware version, and a
description of the component you need the source for.
The offer is valid for any third party to request the source code.
该文本还应放在设备的 Web 管理界面「关于」页面,以及固件更新说明中。
十、README / About 页的最低要求
10.1 License badge
在 README 顶部(通常在项目简介之后的第一行 badge):
[](https://opensource.org/licenses/Apache-2.0)常用 badge 格式(shields.io):
<!-- MIT -->
[](https://opensource.org/licenses/MIT)
<!-- Apache-2.0 -->
[](https://opensource.org/licenses/Apache-2.0)
<!-- GPL-3.0 -->
[](https://www.gnu.org/licenses/gpl-3.0)
<!-- AGPL-3.0 -->
[](https://www.gnu.org/licenses/agpl-3.0)
<!-- 双许可 MIT OR Apache-2.0 -->
[](#license)
<!-- MulanPSL-2.0 -->
[](https://license.coscl.org.cn/MulanPSL2)10.2 引用的主要依赖声明
README 底部(License 小节之前)加一段:
## Third-party licenses
This project uses third-party software. See [THIRD_PARTY_NOTICES.txt](./THIRD_PARTY_NOTICES.txt)
for details. Key dependencies:
- [grpc-go](https://github.com/grpc/grpc-go) — Apache-2.0
- [zap](https://github.com/uber-go/zap) — MIT
- [prometheus/client_golang](https://github.com/prometheus/client_golang) — Apache-2.010.3 CONTRIBUTING 里链到 CLA/DCO
CONTRIBUTING.md 或
CONTRIBUTING.rst 顶部:
## Contributor License Agreement (CLA)
By submitting a pull request, you confirm that:
1. You have the right to submit the contribution under the project license.
2. You agree to the [Contributor License Agreement](./CLA.md).
3. Your contribution does not include any third-party code that would
be incompatible with the project's license (Apache-2.0).
Alternatively, if the project uses DCO instead of CLA, every commit
must be signed-off with `git commit --signoff`.
See [Developer Certificate of Origin](https://developercertificate.org/).10.4 商标使用声明(Apache 风格项目)
若项目是 Apache Software Foundation(ASF)孵化或毕业项目,README 中必须包含:
## Trademark
"Apache", "Apache Foo", and the Apache feather logo are trademarks of
The Apache Software Foundation. See [ASF Trademark Policy](https://www.apache.org/foundation/marks/)
for usage guidelines.非 ASF 项目若有注册商标,类似加一段:
## Trademark
"MyProject" is a registered trademark of Example Corp. Use of the name
is subject to the [Trademark Policy](https://example.com/trademark-policy).十一、典型项目模板(样板仓库结构)
11.1 纯前端(React / Vite,MIT)
my-frontend/
├── LICENSE # MIT,Copyright (c) 2026 Example Corp.
├── THIRD_PARTY_NOTICES.md # npm license-checker 生成
├── README.md # 含 License badge
├── CONTRIBUTING.md # 含 DCO 说明
├── package.json # "license": "MIT"
├── vite.config.ts
├── src/
│ ├── main.tsx # SPDX-License-Identifier: MIT
│ ├── App.tsx # SPDX-License-Identifier: MIT
│ └── components/
└── .github/
└── workflows/
└── license-check.yml
package.json 关键字段:
{
"name": "my-frontend",
"version": "0.1.0",
"license": "MIT",
"author": "Example Corp. <legal@example.com>",
"scripts": {
"license:check": "license-checker --production --onlyAllow 'MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;0BSD;CC0-1.0;CC-BY-4.0'",
"license:generate": "license-checker --production --markdownTable > THIRD_PARTY_NOTICES.md"
}
}src/main.tsx 头部:
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright (c) 2026 Example Corp.CI
协议检查(.github/workflows/license-check.yml):
name: License Check
on:
pull_request:
paths: ['package.json', 'package-lock.json']
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run license:check
- run: npm run license:generate
- run: git diff --exit-code THIRD_PARTY_NOTICES.md11.2 Go 微服务(Apache-2.0)
my-service/
├── LICENSE # Apache-2.0 官方全文
├── NOTICE # Copyright 2026 Example Corp.
├── THIRD_PARTY_NOTICES.txt # go-licenses report 生成
├── README.md
├── CONTRIBUTING.md # 含 CLA 链接
├── CLA.md
├── go.mod
├── go.sum
├── cmd/
│ └── server/
│ └── main.go # SPDX-License-Identifier: Apache-2.0
├── internal/
│ └── handler/
│ └── http.go # SPDX-License-Identifier: Apache-2.0
├── third_party/
│ └── some-vendor-patch/
│ ├── LICENSE
│ └── README.md
└── .github/
└── workflows/
└── license-check.yml
cmd/server/main.go 头部:
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
package mainNOTICE 文件:
My Service
Copyright 2024-2026 Example Corp.
This product includes software developed by Example Corp.
(https://example.com/).
Makefile 中的协议检查:
.PHONY: license-check license-generate
license-check:
go-licenses check ./... \
--allowed_licenses=MIT,Apache-2.0,BSD-2-Clause,BSD-3-Clause,ISC,0BSD,MPL-2.0
license-generate:
go-licenses report ./... > THIRD_PARTY_NOTICES.txt11.3 Python 库(BSD-3-Clause)
my-pylib/
├── LICENSE # BSD-3-Clause 官方全文
├── THIRD_PARTY_NOTICES.txt # pip-licenses 生成
├── README.md
├── CONTRIBUTING.md
├── pyproject.toml # license = {text = "BSD-3-Clause"}
├── src/
│ └── mylib/
│ ├── __init__.py # SPDX-License-Identifier: BSD-3-Clause
│ └── core.py # SPDX-License-Identifier: BSD-3-Clause
└── .github/
└── workflows/
└── license-check.yml
pyproject.toml:
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.backends.legacy:build"
[project]
name = "my-pylib"
version = "1.0.0"
license = {text = "BSD-3-Clause"}
classifiers = [
"License :: OSI Approved :: BSD License",
"Programming Language :: Python :: 3",
]
[project.optional-dependencies]
dev = ["pip-licenses", "pytest"]src/mylib/__init__.py 头部:
# SPDX-License-Identifier: BSD-3-Clause
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
# All rights reserved.Makefile / tox.ini
中的协议检查:
license-check:
pip-licenses --fail-on="GPL;LGPL;AGPL" \
--allow-only="MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;Python-2.0;\
Unlicense;CC0-1.0;Public Domain" \
--format=plain-vertical
license-generate:
pip-licenses --format=plain-vertical --with-license-file \
--output-file=THIRD_PARTY_NOTICES.txt11.4 Rust crate(MIT OR Apache-2.0 双许可惯例)
my-crate/
├── LICENSE-MIT # MIT 全文,Copyright (c) 2026 Example Corp.
├── LICENSE-APACHE # Apache-2.0 官方全文
├── THIRD_PARTY_NOTICES.html # cargo-about 生成
├── README.md
├── CONTRIBUTING.md # 含 CLA 或 DCO 说明
├── Cargo.toml # license = "MIT OR Apache-2.0"
├── deny.toml # cargo-deny 协议白名单
├── about.toml # cargo-about 配置
├── about.hbs # cargo-about 模板
└── src/
└── lib.rs # SPDX-License-Identifier: MIT OR Apache-2.0
Cargo.toml 关键字段:
[package]
name = "my-crate"
version = "1.0.0"
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/example/my-crate"
readme = "README.md"src/lib.rs 头部:
// SPDX-License-Identifier: MIT OR Apache-2.0
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
//! My Crate — 一个示例 Rust 库。双许可时 README 必须说明用户如何选择:
## License
This project is dual-licensed under the terms of both the MIT license
and the Apache License, Version 2.0.
- [LICENSE-MIT](./LICENSE-MIT)
- [LICENSE-APACHE](./LICENSE-APACHE)
You may use this software under the terms of either license..github/workflows/license-check.yml:
name: License Check
on:
pull_request:
paths: ['Cargo.toml', 'Cargo.lock']
jobs:
deny:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: taiki-e/install-action@cargo-deny
- run: cargo deny check licenses
about:
runs-on: ubuntu-latest
needs: deny
steps:
- uses: actions/checkout@v4
- run: cargo install cargo-about
- run: cargo about generate about.hbs > THIRD_PARTY_NOTICES.html
- run: git diff --exit-code THIRD_PARTY_NOTICES.html11.5 Java Maven 库(Apache-2.0)
my-java-lib/
├── LICENSE # Apache-2.0 官方全文
├── NOTICE # Copyright 2026 Example Corp.
├── THIRD-PARTY.txt # maven license plugin 生成
├── README.md
├── CONTRIBUTING.md
├── pom.xml
├── src/
│ └── main/
│ └── java/
│ └── com/example/
│ └── MyLib.java # SPDX 头
└── .github/
└── workflows/
└── license-check.yml
src/main/java/com/example/MyLib.java
头部:
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
package com.example;pom.xml 协议声明和检查配置(完整片段):
<project>
<groupId>com.example</groupId>
<artifactId>my-java-lib</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<distribution>repo</distribution>
</license>
</licenses>
<build>
<plugins>
<!-- 生成 THIRD-PARTY.txt -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>2.3.0</version>
<configuration>
<outputDirectory>${project.basedir}</outputDirectory>
<thirdPartyFilename>THIRD-PARTY.txt</thirdPartyFilename>
<useMissingFile>true</useMissingFile>
<failIfWarning>true</failIfWarning>
<includedLicenses>
<includedLicense>Apache-2.0</includedLicense>
<includedLicense>MIT</includedLicense>
<includedLicense>BSD-2-Clause</includedLicense>
<includedLicense>BSD-3-Clause</includedLicense>
<includedLicense>EPL-2.0</includedLicense>
</includedLicenses>
</configuration>
<executions>
<execution>
<id>check-third-party</id>
<goals>
<goal>add-third-party</goal>
</goals>
<phase>generate-resources</phase>
</execution>
</executions>
</plugin>
<!-- 检查源文件头部 -->
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>4.3</version>
<configuration>
<header>com/mycila/maven/plugin/license/templates/APACHE-2.txt</header>
<properties>
<owner>Example Corp.</owner>
<year>2024-2026</year>
</properties>
<excludes>
<exclude>**/README.md</exclude>
<exclude>**/NOTICE</exclude>
<exclude>**/LICENSE</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>11.6 嵌入式 Linux 产品(GPL 内核 + 自有应用闭源 + LGPL 库 + 商业固件)
这是最复杂的场景。典型架构:
product-firmware/
├── kernel/ # Linux kernel, GPL-2.0-only
│ └── (Linux 内核源码或补丁集)
├── bootloader/ # U-Boot, GPL-2.0-or-later
│ └── (U-Boot 源码或补丁集)
├── rootfs/
│ ├── lib/
│ │ ├── libc/ # glibc, LGPL-2.1-or-later
│ │ ├── libssl/ # OpenSSL 3.x, Apache-2.0
│ │ └── libcurl/ # curl, curl License(MIT 风格)
│ └── usr/
│ └── bin/
│ ├── my-app # 自有应用,闭源(专有软件)
│ └── busybox # BusyBox, GPL-2.0-only
├── third_party/ # 第三方组件 LICENSE 汇总
│ ├── linux/LICENSE
│ ├── u-boot/LICENSE
│ ├── glibc/COPYING
│ ├── glibc/COPYING.LESSER
│ ├── openssl/LICENSE
│ └── curl/COPYING
├── OPEN_SOURCE_NOTICES.txt # 发布物中必须包含
├── WRITTEN_OFFER.txt # GPL written offer 文本
└── build/
└── scripts/
└── check-licenses.sh
关键合规点:
Linux 内核(GPL-2.0-only):内核本身使用 GPL v2 only,不能升级到 v3。内核模块若分发,同样受 GPL v2 约束(内核模块加载时会检查
MODULE_LICENSE宏,不合规的模块会触发「tainted kernel」警告)。自有驱动以 kernel module 形式运行时,法律地位有争议——工程层面建议按 GPL 处理。glibc(LGPL-2.1-or-later):glibc 使用 LGPL,允许与闭源应用程序链接(动态链接),但 glibc 本身若被修改,修改部分须开源。
BusyBox(GPL-2.0-only):BusyBox 本身须开源。自有闭源应用不能与 BusyBox 静态链接(否则触发 GPL 传染);动态链接到 BusyBox 提供的 lib 没有问题,但大多数产品直接使用 BusyBox 的命令行工具,这本身不触发传染(使用工具 ≠ 衍生作品)。
商业固件(专有代码):只要不静态链接 GPL 库,可以以闭源形式分发。配置文件(如 JSON/YAML)一般不认为是衍生作品。
build/scripts/check-licenses.sh 示例:
#!/usr/bin/env bash
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 Example Corp.
set -euo pipefail
echo "=== Checking GPL components are present in source release ==="
GPL_DIRS=("kernel" "bootloader" "rootfs/usr/bin/busybox-src")
for d in "${GPL_DIRS[@]}"; do
if [ ! -d "$d" ]; then
echo "ERROR: GPL source directory missing: $d"
exit 1
fi
done
echo "=== Checking WRITTEN_OFFER.txt exists ==="
if [ ! -f WRITTEN_OFFER.txt ]; then
echo "ERROR: WRITTEN_OFFER.txt is required for GPL binary distribution"
exit 1
fi
echo "=== Checking OPEN_SOURCE_NOTICES.txt is up to date ==="
if [ ! -f OPEN_SOURCE_NOTICES.txt ]; then
echo "ERROR: OPEN_SOURCE_NOTICES.txt is missing"
exit 1
fi
echo "All license checks passed."OPEN_SOURCE_NOTICES.txt 结构:
Open Source Software Notices for MyProduct Firmware v1.0.0
===========================================================
This product includes the following open source software:
1. Linux Kernel 6.6.x
License: GPL-2.0-only
Source: https://kernel.org / https://opensource.example.com/source
Copyright: Linus Torvalds and contributors
2. U-Boot 2024.01
License: GPL-2.0-or-later
Source: https://opensource.example.com/source
Copyright: DENX Software Engineering and contributors
3. GNU C Library (glibc) 2.39
License: LGPL-2.1-or-later
Source: https://www.gnu.org/software/libc/
Copyright: Free Software Foundation, Inc.
4. BusyBox 1.36.1
License: GPL-2.0-only
Source: https://opensource.example.com/source
Copyright: Erik Andersen, Rob Landley, Denys Vlasenko, and contributors
5. OpenSSL 3.2.x
License: Apache-2.0
Source: https://openssl.org/
Copyright: The OpenSSL Project Authors
6. curl 8.6.x
License: curl (MIT-style)
Source: https://curl.se/
Copyright: Daniel Stenberg and contributors
Full license texts are available at:
https://opensource.example.com/licenses
or by written request to: opensource@example.com
十二、协议变更操作
12.1 从闭源转开源
操作序列:
# 第一步:确认版权持有人
# 检查所有文件的版权归属,确保公司或指定法人拥有所有代码的版权
git log --format='%aN <%aE>' | sort -u > all-contributors.txt
# 逐一确认每位贡献者是否已签署 IP 转让协议(员工劳动合同或外包合同)
# 第二步:批量添加 SPDX 头
go install github.com/google/addlicense@latest
addlicense -c "Example Corp." -l apache -y 2020-2026 \
-ignore "vendor/**" -ignore "third_party/**" \
./...
# 第三步:添加 LICENSE 文件
curl -o LICENSE https://www.apache.org/licenses/LICENSE-2.0.txt
# 第四步:创建 NOTICE 文件
cat > NOTICE <<'EOF'
My Project
Copyright 2020-2026 Example Corp.
EOF
# 第五步:审查依赖协议兼容性
go-licenses check ./... --allowed_licenses=MIT,Apache-2.0,BSD-2-Clause,BSD-3-Clause
# 第六步:创建 GitHub 仓库(设为 Public),推送
git add LICENSE NOTICE THIRD_PARTY_NOTICES.txt
git commit -m "chore: add open source license files (Apache-2.0)
Co-authored-by: Alice Wang <alice@example.com>"
git push origin main需要特别检查的清单: - 所有贡献者是否已通过劳动合同或 IP 协议把代码著作权转让给公司? - 代码中是否引用了公司内部商业服务的 API key、secret、内部域名? - 是否包含第三方商业 SDK(如地图 SDK、支付 SDK),这些 SDK 的协议允许二次分发吗? - 是否包含 GPL/LGPL 库?这些库的传染性会影响新项目的开源协议选择。
12.2 从 Apache-2.0 改为 AGPL-3.0(Elastic / Sentry 模式)
参考 AGPL、SSPL、BSL 详解 第三部分。
操作序列:
# 前提:所有贡献者已签 CLA,将著作权或足够的授权转让给项目持有人
# 第一步:记录变更点(commit hash + 日期)
git log --oneline -1 # 记录最后一个 Apache-2.0 提交
# 例如:abc1234 (2025-12-31) Last commit under Apache-2.0
# 第二步:创建变更说明文件
cat > LICENSE-CHANGE-NOTICE.md <<'EOF'
## License Change Notice
Effective [变更日期], the license for this project changes from
Apache License 2.0 to GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later).
Code committed prior to [变更日期] (up to and including commit abc1234)
remains available under Apache-2.0 at that git tag.
This change requires all contributors to have signed our CLA.
See the git tag "last-apache-release" for the last Apache-2.0 version.
EOF
# 第三步:打 tag 保留最后一个 Apache-2.0 版本
git tag last-apache-release abc1234
# 第四步:替换 LICENSE 文件
curl -o LICENSE https://www.gnu.org/licenses/agpl-3.0.txt
# 第五步:批量更新源文件头的 SPDX 标识符
find . -name "*.go" -not -path "*/vendor/*" | \
xargs sed -i 's/SPDX-License-Identifier: Apache-2.0/SPDX-License-Identifier: AGPL-3.0-or-later/g'
# 第六步:提交
git add -A
git commit -m "chore: change license from Apache-2.0 to AGPL-3.0-or-later
This change is effective [变更日期].
All contributors have signed the CLA.
The last Apache-2.0 release is tagged as 'last-apache-release'."贡献者追溯清单:
# 列出所有有 commit 的贡献者
git log --format='%aN <%aE>' | sort -u
# 按提交数量排序
git shortlog -sn
# 对照 CLA 签署记录,确认每位贡献者都已签署
# 如果某位贡献者无法联系或未签 CLA,其贡献的文件需要重写或移除12.3 从 GPL-2.0-only 改为 GPL-3.0-or-later
只有在原协议为「GPL-2.0 or
later」(GPL-2.0-or-later)时才能升级,GPL-2.0-only
的代码不能被单方面升级到 v3。
# 验证原协议是否为 "or later"
grep -r "either version 2 of the License, or" . --include="*.c" --include="*.h" | head
# 如果确认是 "or later",替换 LICENSE
curl -o LICENSE https://www.gnu.org/licenses/gpl-3.0.txt
# 更新 SPDX 头(从 GPL-2.0-or-later 到 GPL-3.0-or-later)
find . -name "*.c" -o -name "*.h" | \
xargs sed -i 's/SPDX-License-Identifier: GPL-2.0-or-later/SPDX-License-Identifier: GPL-3.0-or-later/g'
# 注意:所有模块的 MODULE_LICENSE 宏也需要更新(内核模块)
# MODULE_LICENSE("GPL v2") -> MODULE_LICENSE("GPL") # "GPL" 接受 v2 and later12.4 从开源双许可转为商业独占
这是「rug pull」操作,最敏感。前提:全体贡献者已签 CLA 并明确授权持有人可以更改许可证。
# 第一步:核查 CLA 完整性
# 确认每一位有代码贡献的人都签署了 CLA
# 对于只有小量贡献(如修错别字)的贡献者,可根据 de minimis 原则排除
# 第二步:打 tag 保留最后开源版本
git tag last-open-source-release
# 第三步:向社区公告(提前 90-180 天,参考 HashiCorp 的 BSL 切换时间表)
# 第四步:替换协议文件
# 将 LICENSE 替换为商业许可证文本(由法务起草)
# 或替换为 BSL(BUSL-1.1)
# 第五步:更新所有 SPDX 头
find . -name "*.go" | \
xargs sed -i 's/SPDX-License-Identifier: Apache-2.0/SPDX-License-Identifier: LicenseRef-Commercial/g'CLA 追溯清单模板:
## CLA 追溯检查清单
| 贡献者 | GitHub 用户名 | 首次提交日期 | CLA 签署日期 | 状态 |
|--------|-------------|------------|------------|------|
| Alice Wang | @alice | 2022-03-01 | 2022-02-28 | ✅ |
| Bob Chen | @bob | 2023-06-15 | 2023-06-10 | ✅ |
| Charlie Li | @charlie | 2024-01-20 | — | ⚠️ 待联系 |
对于未签 CLA 的贡献者,处理方案:
1. 联系贡献者补签。
2. 若无法联系,评估其贡献是否为 de minimis(通常 < 10 行非独创代码)。
3. 若贡献重要且无法联系,重写相关代码。十三、中国场景下的额外注意
13.1 出海项目的 LICENSE 语言问题
对外发布的开源项目(面向国际社区): - LICENSE 文件必须使用英文原文。 - 如有必要添加中文说明,以注释或附录形式附在英文全文之后,注明「以下为参考译文,如有歧义以英文为准」。
MIT License
Copyright (c) 2026 Example Corp.
Permission is hereby granted...(MIT 英文正文)
---
以上为 MIT 许可证英文原文。以下为参考中文译文(非正式,仅供理解参考,
法律约束力以英文原文为准):
中文译文:特此免费授予任何人获得本软件及相关文档文件("软件")副本的权限...
13.2 木兰协议项目的双语附注
木兰宽松许可证第2版(MulanPSL-2.0)官方提供中英双语版本,两个版本具有同等法律效力。
LICENSE 文件建议写法:
Mulan Permissive Software License,Version 2
木兰宽松许可证,第2版
(中英文双语版本,详见 https://license.coscl.org.cn/MulanPSL2/)
(以下粘贴双语正文)
面向国际社区的项目,SPDX 标识符 MulanPSL-2.0
已被 SPDX 列表收录(2020年起),可直接在 SPDX 头使用:
// SPDX-License-Identifier: MulanPSL-2.0开放原子开源基金会(openatom.org)托管的项目,建议在 README 里同时注明:
本项目由[开放原子开源基金会](https://www.openatom.org/)托管。13.3 涉密 / 国企项目的审批流程
对于涉及军工、国防、涉密信息系统的软件:
- 开源前审批:通常需要内部安全审查委员会批准,审查内容包括是否包含涉密算法、内部网络拓扑、身份信息等。
- 出口管制:涉及加密算法(如国密 SM2/SM3/SM4)的代码出海,参考 出海合规;这些算法在中国境内使用不受出口管制,但出口到特定国家需要申报。
- 国企项目版权归属:员工在职期间利用单位资源开发的代码,著作权通常由单位持有(《著作权法》第十八条)。建议在开源前明确所有相关代码的著作权归属。
13.4 公司内部 fork 公共库时的版权归属处理
场景:公司内部 fork 了一个 Apache-2.0 的开源库,并做了大量修改,现在想把修改部分以 Apache-2.0 开源。
操作步骤:
# 1. 确认修改部分的著作权归属(公司)
# 2. 维护一个 PATCHES/ 目录,记录所有相对于上游的修改
mkdir -p PATCHES
git diff upstream/main HEAD -- . > PATCHES/my-changes.patch
# 3. 在修改的文件头部添加 "此文件已被修改" 声明(Apache-2.0 第4条b款要求)
# 4. 更新 NOTICE 文件,保留上游 NOTICE 内容,追加自己的版权声明
cat >> NOTICE <<'EOF'
This file has been modified from the original Apache-2.0 project.
Modifications Copyright (c) 2024-2026 Example Corp.
EOF
# 5. 如果要提交 PR 给上游,检查上游的 CLA 要求版权归属清单:
| 代码来源 | 著作权持有人 | 处理方式 |
|---|---|---|
| 公司员工在职期间开发 | 公司法人 | 直接以公司名义声明版权 |
| 外包团队开发(有 IP 转让条款) | 公司法人 | 同上,保留合同备查 |
| 外包团队开发(无明确 IP 条款) | 风险:可能属于外包方 | 补签 IP 转让协议 |
| 上游开源项目(Apache-2.0) | 上游作者 | 保留原 copyright,在 NOTICE 中注明修改 |
| 贡献者自愿提交(已签 CLA) | 视 CLA 内容而定 | 通常转让给项目法人或授予足够权利 |
十四、工程坑点
坑一:minifier 剥掉了所有 LICENSE 注释
场景:前端项目用 Webpack/Rollup/esbuild
打包后,bundle.js 中所有 /*! License */
注释被剥除,MIT/Apache-2.0 的 copyright 保留义务未满足。
对策:
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
build: {
rollupOptions: {
output: {
// 保留以 @license 开头的注释
banner: '/*! See THIRD_PARTY_NOTICES.txt for third-party licenses. */',
}
}
}
});// webpack.config.js
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimizer: [new TerserPlugin({
terserOptions: {
format: {
// 保留 @license 或 @preserve 注释
comments: /^\s*(@license|@preserve)/,
},
},
extractComments: {
condition: /^\s*(@license|@preserve)/,
filename: 'LICENSES.txt', // 提取到单独文件
banner: (licenseFile) => `License information can be found in ${licenseFile}`,
},
})],
},
};坑二:Go vendor 目录里的 LICENSE 没有随二进制发布
场景:go mod vendor 后把
vendor 目录的 LICENSE 文件删掉了,或者 Docker 镜像
multi-stage build 时只复制了二进制,没有复制 LICENSE。
对策:
# 错误做法
FROM golang:1.22 AS builder
COPY . .
RUN go build -o /myapp ./cmd/server
FROM scratch
COPY --from=builder /myapp /myapp
# 没有复制 LICENSE 相关文件!
# 正确做法
FROM golang:1.22 AS builder
COPY . .
RUN go build -o /myapp ./cmd/server
RUN go-licenses save ./... --save_path=/third_party_licenses
FROM alpine:3.19
COPY --from=builder /myapp /myapp
COPY --from=builder /third_party_licenses /usr/share/doc/myapp/
COPY LICENSE /usr/share/doc/myapp/LICENSE
COPY NOTICE /usr/share/doc/myapp/NOTICE坑三:SPDX 头只写了 Apache-2.0,忘记更新 NOTICE 文件
场景:项目从 MIT 切换到 Apache-2.0 后,给源文件加了 SPDX 头,但忘记创建 NOTICE 文件。Apache-2.0 第4条明确要求有 NOTICE 文件时必须保留。
对策:在 CI 中检查 Apache-2.0 项目是否有 NOTICE 文件:
#!/usr/bin/env bash
# 检查 Apache-2.0 项目是否有 NOTICE 文件
if grep -q "Apache-2.0" LICENSE 2>/dev/null; then
if [ ! -f NOTICE ]; then
echo "ERROR: Apache-2.0 project must have a NOTICE file"
exit 1
fi
fi坑四:npm 包声明了错误的 SPDX 标识符
场景:package.json 中写的是
"license": "Apache 2" 而不是
"license": "Apache-2.0",导致工具扫描时无法识别为合规协议,CI
报错。
对策:严格使用 SPDX 标准标识符。常见错误写法 vs 正确写法:
| 错误写法 | 正确 SPDX 标识符 |
|---|---|
Apache 2 |
Apache-2.0 |
Apache 2.0 |
Apache-2.0 |
GPL v2 |
GPL-2.0-only 或
GPL-2.0-or-later |
MIT License |
MIT |
BSD |
BSD-2-Clause 或
BSD-3-Clause |
CC BY 4.0 |
CC-BY-4.0 |
LGPL |
LGPL-2.0-only / LGPL-2.1-only
/ LGPL-3.0-only |
坑五:GPL-2.0-only 和 GPL-2.0-or-later 混用
场景:Linux 内核代码是
GPL-2.0-only,不能和 GPL-3.0-only
的代码静态链接(不兼容)。有些工程师以为都是 GPL
就可以混,实际上 only 和 or-later
有本质区别。
对策: -
GPL-2.0-only:只允许 GPL v2,不允许升级到 v3。
- GPL-2.0-or-later:允许 v2 及更高版本,与 v3
兼容。 -
在代码头部明确写清楚:SPDX-License-Identifier: GPL-2.0-only
或
SPDX-License-Identifier: GPL-2.0-or-later,不要只写
GPL-2.0(SPDX 中 GPL-2.0
已被废弃,应使用 -only 或
-or-later 后缀)。
坑六:AGPL 项目通过网络提供 API 服务,未公开源码
场景:公司用 AGPL-3.0 的代码库部署了一个 SaaS 服务,对外提供 REST API,但没有公开修改后的源代码。
对策:AGPL-3.0 第 13 条明确,通过网络提供交互式服务也触发 copyleft 义务,必须向用户提供完整源码下载。如果不希望开源,有两条路: 1. 从上游购买商业许可证(如果上游提供双许可)。 2. 将 AGPL 依赖替换为兼容闭源的替代品。
参考 AGPL、SSPL、BSL 详解 的具体条款分析。
坑七:Python 的 classifiers 和 license 字段不一致
场景:pyproject.toml 里
license = {text = "MIT"} 但
classifiers 里写的是
"License :: OSI Approved :: Apache Software License",导致
PyPI 页面显示矛盾信息。
对策:保持 license 字段和
classifiers 严格一致,或只用
license 字段(新版 setuptools 会自动从 SPDX
标识符映射 classifiers)。
坑八:Docker 镜像 LABEL 里的 licenses 字段和实际 LICENSE 不一致
场景:Dockerfile 里
LABEL org.opencontainers.image.licenses="MIT"
但实际引用的依赖包含 LGPL 组件,没有触发任何警告。
对策:org.opencontainers.image.licenses
字段描述的是镜像中所有软件的综合协议情况,不只是你自己的代码。建议使用
syft 扫描镜像并从 SBOM 中汇总所有协议,再决定 LABEL
的值:
syft myimage:latest -o spdx-json | \
jq '[.packages[].licenseConcluded] | unique | join(", ")'如果镜像中有 GPL 组件(如 bash、glibc),LABEL 应该是
GPL-2.0-or-later AND Apache-2.0 AND MIT
这样的复合表达式,而不是只写自己代码的协议。
坑九:Rust crate 的双许可,Cargo.toml 写法错误
场景:Cargo.toml 里写
license = "MIT/Apache-2.0"(用斜杠分隔),但
SPDX 标准是用 OR
关键字:license = "MIT OR Apache-2.0"。斜杠写法在某些工具里不被识别。
对策:使用 SPDX
表达式语法:AND、OR、WITH
和括号。验证方法:
cargo metadata --format-version 1 | jq '.packages[0].license'
# 应输出 "MIT OR Apache-2.0"坑十:fork 上游 Apache-2.0 项目时,忘记在修改文件中添加修改声明
场景:直接 fork 并修改了 Apache-2.0 库的多个文件,但没有在文件头部声明「此文件已被修改」,违反了 Apache-2.0 第4条 (b) 款。
对策:在 CI 中检查修改文件是否有修改声明(针对已知 fork 的上游文件):
#!/usr/bin/env bash
# 检查相对于上游的修改文件是否包含修改声明
MODIFIED=$(git diff upstream/main HEAD --name-only -- '*.go' '*.java' '*.py')
for f in $MODIFIED; do
if ! grep -q "This file has been modified" "$f" 2>/dev/null; then
echo "WARNING: Modified file lacks modification notice: $f"
fi
done十五、参考资料
15.1 许可证官方文本
- SPDX License List, https://spdx.org/licenses/
- Open Source Initiative, Approved Licenses, https://opensource.org/licenses
- Apache License 2.0 官方文本, https://www.apache.org/licenses/LICENSE-2.0
- GNU GPL v2 官方文本, https://www.gnu.org/licenses/gpl-2.0.html
- GNU GPL v3 官方文本, https://www.gnu.org/licenses/gpl-3.0.html
- GNU LGPL v2.1 官方文本, https://www.gnu.org/licenses/lgpl-2.1.html
- GNU AGPL v3 官方文本, https://www.gnu.org/licenses/agpl-3.0.html
- Mozilla Public License 2.0, https://www.mozilla.org/en-US/MPL/2.0/
- 木兰宽松许可证第2版, https://license.coscl.org.cn/MulanPSL2/
- Business Source License 1.1, https://mariadb.com/bsl11/
15.2 规范与标准
- SPDX Specification 2.3, https://spdx.github.io/spdx-spec/v2.3/
- REUSE Specification v3.3, https://reuse.software/spec/
- OCI Image Spec(LABEL 字段规范), https://github.com/opencontainers/image-spec
- CycloneDX SBOM Specification, https://cyclonedx.org/specification/overview/
- NTIA Software Bill of Materials, https://www.ntia.doc.gov/sbom
15.3 工具文档
- addlicense(Google), https://github.com/google/addlicense
- go-licenses(Google), https://github.com/google/go-licenses
- license-checker(npm), https://github.com/davglass/license-checker
- pip-licenses, https://github.com/raimon49/pip-licenses
- cargo-about, https://github.com/EmbarkStudios/cargo-about
- cargo-deny, https://github.com/EmbarkStudios/cargo-deny
- reuse(FSFE)CLI, https://git.fsfe.org/reuse/tool
- syft(Anchore), https://github.com/anchore/syft
- OSS Review Toolkit(ORT), https://github.com/oss-review-toolkit/ort
- license-maven-plugin, https://www.mojohaus.org/license-maven-plugin/
- LicensePlist(iOS), https://github.com/mono0926/LicensePlist
- AboutLibraries(Android), https://github.com/mikepenz/AboutLibraries
15.4 中国相关资料
- 《中华人民共和国著作权法》(2020年修订版), https://www.gov.cn/guoqing/2021-10/29/content_5647633.htm
- 开放原子开源基金会, https://www.openatom.org/
- 中国开源云联盟(木兰协议托管), https://license.coscl.org.cn/
- 数字天堂诉柚子科技案((2021)粤0192民初16700号), 中国裁判文书网
- 软件成分分析国家标准 GB/T 42514-2023(在编)
15.5 延伸阅读
- FSF, “How to use GNU licenses for your own software”, https://www.gnu.org/licenses/gpl-howto.html
- Apache Software Foundation, “Apache License FAQ”, https://www.apache.org/foundation/license-faq.html
- GitHub, “Choose an open source license”, https://choosealicense.com/
- FOSSA Blog, “Open Source License Compliance for Enterprises”, https://fossa.com/blog/
- Linux Foundation, “Open Source Compliance in the Enterprise”, https://www.linuxfoundation.org/resources/open-source-guides/
本文为工程参考,不构成法律意见。涉及具体法律风险请咨询专业法律顾问。
上一篇:开源战略:什么时候开源、选哪个协议、如何构建商业壁垒
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
开源许可与版权工程
面向中国工程团队的开源许可、版权与合规系列。从 GPL、AGPL、Apache、木兰协议到中国真实案例、SCA/SBOM 工具链与出海合规,讲清楚开源在工程落地中的坑与方法。
【开源许可与版权工程】开源许可证全景:宽松、弱 Copyleft、强 Copyleft、网络 Copyleft
从 MIT 到 AGPL,从 SPDX 标识符到 OSI 认证:一篇讲清楚四类开源许可证的边界、兼容性矩阵、SSPL/BSL 的争议、Commons Clause 事件,以及工程里最常见的踩坑场景和选型建议。
【开源许可与版权工程】闭源项目如何选择开源依赖:公司内部合规实操
面向做闭源/商业产品的团队:逐一拆解 MIT、LGPL、GPL、AGPL、SSPL、BSL 在 SaaS、私有化部署、移动 App、嵌入式固件等形态下的许可边界,给出三级名单模板、CI 扫描配置、SBOM 存证方案与出海补充要求。
【开源许可与版权工程】MIT、BSD、Apache 2.0:宽松许可证的真实区别
深入对比 MIT、BSD 家族与 Apache 2.0 的条款差异:NOTICE 文件义务、专利授权、重新授权权利;BSD advertising clause 的历史与废除;ISC 许可证的关系;以及阿里、腾讯、字节内部为何强烈推荐 Apache 2.0 的工程原因。