我开发了一个基于 Beancount 的账本托管服务 HostedBeans,欢迎大家来了解纯文本复式记账并试用我的服务。
标签 #开源

自由软件和开源许可证

本文整理自 彩排 中的一期播客。

什么是自由软件

我总结了三点自由:

  • 出于任何目的、以任何方式 使用该软件的自由(包括商业用途,一些商业软件限制你不得进行破解、不能用于犯罪活动就是在限制你使用的方式或目的)。
  • 修改软件的自由,当然修改软件的前提是你要能够得到源代码。
  • 重新分发的自由,不仅是分发原始版本,你也可以分发修改后的版本。

只有符合这三条才可以算自由软件,有一些只开源代码(可能是为了安全审计,或者只限非商业用途)的软件并不能算自由软件。

我们经常看到的 GPL、Apache、MIT 都属于自由软件许可证,这些许可证会在前面的三项自由之外附加一些限制条款,但这些限制条款与自由软件中的自由并不冲突。

Copyleft 的 GPL 家族

在自由软件许可证中,有一类特殊的被称为 Copyleft 的许可证(Copyleft 是一个与 Copyright 相对的词,代表着一种具有「传染性」的自由),其中最知名的就是 GPL 家族了,我们接下来会聊到其中的 GPL、LGPL 和 AGPL。

Copyleft 的特点在于它有一种理想主义的野心 —— 它希望这个世界上所有的软件都是自由的,因此这些许可证都是具有「传染性」的。它们在自由软件的基础上附加了一个最主要的限制条款:在重新分发 Copyleft 的软件时,必须授予用户同等的自由、也必须附加同等的限制条款。在实践中一般就是说,你修改一个 GPL 的软件后,你再发布的时候也必须是 GPL,其他人修改了你修改后的软件,也必须是 GPL,这就是所谓的传染性。

自由软件社区中有很多使用 GPL 许可证的软件,例如我们熟知的 Linux、WordPress 等等。说到 WordPress,现在有很多公开出售 WordPress 主题或插件的社区,但按照 GPL 的许可证,主题或插件中的 PHP 代码显然属于衍生作品,必须使用 GPL 许可证来发布(而 CSS 和 JavaScript 可以通过单独以其他协议发布来规避),所以理论上,任何一个人购买了 WordPress 主题,那么他都可以随意地再次出售这个主题(这是 GPL 授予他的权利),在 2013 年我便就此话题写过一篇 文章

GPL 中的衍生作品

我们再来看 GPL 的限制条款,即「再分发衍生作品时必须授予用户同等的自由」,这里有两个词可以单独拿出来讨论一下,「分发」和「衍生作品」。

所谓 分发 就是说你把这个软件(包括修改后的版本)发送给其他人使用,例如你开发了一个桌面软件,当你给用户提供下载时,这就是一种分发行为;当你提供一个库(无论是源代码还是二进制版本)也是一次分发行为;甚至包括浏览器中的 JavaScript 也算分发行为 —— 因为用户的浏览器需要从你的服务器下载 JavaScript.

GPL 为了保证用户有修改软件的自由,要求你在进行分发时同时提供源代码。而分发可能是公开的,也可能是小范围的,如果你在网络上公开发布一个软件,那么你也必须公开发布源代码;但如果你只是私下发给一个朋友,或在公司内部分发一个内部软件,那么你只需要向这个朋友,或者在你的公司内部提供源代码。所以说「分发」和「提供源代码」的行为是挂钩的,你向谁分发就向谁提供源代码。

所谓 衍生作品,GPL 认为只要你的项目中用到了 GPL 的代码,都可以算衍生代码,无论你是把 GPL 代码作为一个主要功能,还是用来做一个非常细枝末节的功能。而且 GPL 感染的对象是你的整个软件,也就是说只要你的项目用了 GPL,那么整个项目都被感染成了 GPL,你在进行发布时需要提供整个项目的源代码。

这样听起来 GPL 的确很流氓,那么具体到条款上,GPL 什么情况下会感染你的项目呢?我总结了一下,除非你采用以下三种隔离方法中的一种,将 GPL 代码与你的项目进行了隔离,否则都会被 GPL 感染:

  • 内存地址空间隔离,即如果你的代码和用到的 GPL 代码不共享内存地址空间,例如分别属于两个进程(操作系统帮你做了内存地址空间隔离),或者分别属于内核态和用户态那么就不算衍生作品,例如 Linux 并不会感染运行在 Linux 上的程序。
  • 代码和数据隔离,即如果你的代码和 GPL 的代码是分别作为代码和数据被看待的,那么不算衍生作品。例如用 GCC 编译你的程序是不会感染的,因为在编译时,你的程序是作为数据被看待的;同理,用 Emacs 编写代码也不会感染被编写的代码。
  • 指令计数器隔离,这个是针对虚拟机的一种例外,像 JVM 这样的运行环境,实际上是虚拟了一个 CPU 去执行其上的 Java 操作码,这个虚拟的 CPU 实际上有着和物理 CPU 不同的指令计数器(即 CPU 用来记录当前执行位置的寄存器),因此 JVM 不会感染运行在其上的 Java 代码。

注意这里的例外并不包括静态链接和动态链接,因此如果你静态链接一个 GPL 的库也是会感染你的整个项目的;至于动态链接则目前还存在争议,GNU 极力认为动态链接也在感染的范围内。

LGPL

除了 GPL 还有一个叫 LGPL 的许可证,它是一个比 GPL 宽松一些的许可证,LGPL 中将衍生作品的范围减少到「同一个编译单元」,允许用户在使用了 LGPL 的静态链接库时,仅将 LGPL 代码所属的编译单元开源,所谓编译单元在 C 这样的语言里就是一个文件,若干个编译单元会在最后被链接到一起,形成一个可执行文件。

但如果推广到一些并没有明确区分编译和链接环节的基于虚拟机的语言(例如 Java 或 JavaScript)中,则还有一些争议,一般是认为一个包属于一个编译单元。

LGPL 被广泛地使用在依赖库中,例如 Qt 和 FFmpeg 都使用 LGPL 许可证,但实际上作为 GNU 之父的 Richard 后来并不建议大家使用 LGPL,而是建议大家直接使用原版的 GPL。

他在一篇题为「Why you shouldn’t use LGPL for your next library」的文章中说,非自由软件的开发者往往都有很多金钱上的优势,我们这些自由软件的开发者必须团结起来以便得到某种优势来和他们对抗。如果我们发布的库都使用原版的 GPL,那么我们这些自由软件开发者将获得一种巨大的优势 —— 我们可以使用这些库,但那些非自由软件开发者却不能。

所以后来 Richard 将 LGPL 的全称从 GNU Library License 改为了 GNU Lesser License,并且不建议大家在新的项目中使用。

GPL 在法律上的现状

GPL 在法律上的现状并不乐观,很多时候 GPL 是一种君子协定,很多人经常是基于道德,或者很多公司是基于声誉的考量才去遵守 GPL。虽然 GPL 许可证本质上是一种合同,将代码的使用权有限制地授予愿意遵守这个限制的人。但 GPL 的主要诉求是「开源代码」,而即使赢得诉讼,(至少在中国)法院也不会帮你强制执行「开源代码」这一判决;因为通常法院只能强制执行经济类的判决,如果你要求经济上的赔偿的话,因为 GPL 中并没有写明不遵守许可证的情况下的罚金,因此你可能需要证明被告不开源这一行为给他带来了多大的利益或者给你造成了多大损失,注意并不是他使用你的代码得到的利益,而仅仅是不开源这一行为的利益。

尤其很多开源项目并没有精力去打官司,一部分开源软件可能只是会在网站上登出一个「耻辱柱」的页面,列出哪些项目或公司使用了他们的代码却没有遵守 GPL 许可证,例如 FFmpeg 的网站

AGPL

接下来我们来介绍 GPL 家族的另一位成员 AGPL,AGPL 是一个更严格的 GPL 协议,代表性的项目是 MongoDB —— 一个非常知名的非关系型数据库。考虑到现在是互联网时代,很多公司会将 MongoDB 之类的开源软件进行一些修改或封装,然后提供基于 MongoDB 的云服务来盈利。于是就有了 AGPL 许可证,AGPL 将分发的行为扩展到了「通过网络提供服务」,之前的 GPL 对于服务器端应用是没有什么约束的,因为服务器端应用并不会发布给最终用户,但如果你使用了 AGPL 来通过网络提供服务,那么你也需要开源你对其的修改。

就在发文前,MongoDB 宣布新版本将会切换到 SSPL,这个协议是对 AGPL 的进一步细化,规定了若提供主要价值来自于 MongoDB 的云服务,就必须开源能够让用户运行起来这个服务所需的所有组件,包括用户界面、API、自动化、监控、备份等组件。

非 Copyleft 许可证

前面花了很多篇幅去介绍 GPL 家族,的确他们是自由软件中最有趣也最优代表性的部分。但现在一些新的开源软件往往会选择一个非 Copyleft 的许可证,例如 Apache、BSD、MIT 等等,不过这些协议的条款相对简单,一句话便可概括。

其中 MIT 许可证仅仅要求用户进行署名,所谓署名是你必须将用到的自由软件代码的许可证附带在你分发的每份软件中,并且让用户能够看到,例如在很多软件的某个隐蔽的角落,你可以看到一个叫「开源许可证」或「法律信息」的按钮,点开可以看到它用到的所有自由软件的许可证。

当然你也就可以连署名都不要求的话,你可以选择直接将你的作品释放到共有领域,例如 SQLite(一个嵌入式关系型数据库)就直接被发布到了共有领域,你可以用它的代码做任何事情,连署名都不需要。

BSD 会稍微严格一些,除了要求署名之外还要求用户不得使用其名字用作宣传的用途,例如你基于一个 BSD 协议的软件发布了一个修改后的版本你必须为它起一个新的名字,和原有项目做出明确的区分,以免误导其他用户。

而 Apache 许可证在 BSD 的基础上还要求你在发布修改后的版本时明确注明对哪些文件、做了什么修改。

这里需要注意的一点是这些许可证的授权往往是 不可撤销 的,一旦你曾经以某个许可证发布了一个项目,那么任何人都可以按照你当时发布的那个版本的许可证去使用你当时发布的那个版本的代码。当然你可以从某个时间点开始以新的许可证来发布代码,但其他人依然可以选择遵守旧的许可证去使用旧的版本。这一点是写在大部分自由软件许可证中的条款,是出于保护自由软件代码的使用者的考虑,否则如果你可以随时收回你的授权,是没有任何人敢去用你的代码的。

Creative Commons

前面我们提到的的都是针对于代码的许可证,但有的时候我们也希望授予文本作品的读者一些自由。我接下来介绍的这个「创作共用许可证」就是这样的一种许可证,通常缩写为 CC.

CC 许可证将文本作品的作者常见的几种诉求总结成了四点:

  • BY 署名
  • SA 相同方式共享,所有的衍生作品都必须使用同样的许可证,类似于 GPL 的要求,但因为文本作品的衍生关系相对简单,所以可能并没有太多人关注它的传染性
  • NC 禁止商业使用
  • ND 禁止演绎

这四种诉求可以被组合到一起,例如我的博客选用了 CC 署名、非商业使用、相同方式共享发布。也就是说你可以非商业的目的自由地使用和分发这篇文章,需要提供指向 caipai.fm 的链接,如果你修改了文章则必须也允许其他人以相同的方式转载和修改。

CLA

我们还会看到一些软件同时是自由软件(比如 Qt 和 MySQL),也提供了商业授权,如果你购买了他们的商业授权,那么你并不需要遵守自由软件的许可证,这是如何做到的呢?

首先,一个作品的作者是有权决定如何把这个作品的使用权授予其他人的,他可以即发布一个面向所有人的自由软件许可证的版本,当然这个自由软件版本其实也是有限制的;他也可以以单独的、有着完全不同的限制的方式来把使用权授予其他人,商业授权就是这样实现的。

但很多社区开发的自由软件,例如 Linux,一旦有来自社区的贡献者参与了进来之后,最初的发起者就没有权利去修改许可证或发行商业版本了,因为这时已经没有人拥有这个软件的所有的代码的所有权利了,因为这个软件的不同的部分的代码来自不同的贡献者,他们只是以这个项目的自由软件许可证发布他们的代码,所有人都必须遵守这个自由软件许可证,而显然将一个 GPL 许可证的自由软件改为其他非 Copyleft 许可证是不行的,因为这违反了 GPL 许可证的要求。

所以在实践上,很多社区开发的软件会要求贡献者在提交代码之前签署一份协议(通常缩写为 CLA),这份协议的主要内容有两点:

  • 贡献者授予软件的维护者有关此次贡献的代码的永久的、无限制的使用权(而不仅仅是按照自由软件许可证授权)。
  • 贡献者声明自己拥有所贡献的代码的相关权利(而不是从另外一个不兼容的许可证的项目、或非开源项目中拷贝的)。

如果一个社区开发的软件一开始就这么做,那么第一条保证了软件的维护者始终拥有对所有代码的没有限制的使用权,这样项目的维护者才有可能修改许可证或者发行商业授权;而第二点我个人认为只是为了在出现著作权纠纷时,规避一些法律上的问题。

拓展阅读:

1

精子生于 1995 年,英文 ID jysperm.

订阅推送

通过 Telegram Channel 订阅我的博客日志、产品和项目的动态:

王子亭的博客 @ Telegram


通过邮件订阅订阅我的博客日志、产品和项目的动态(历史邮件):

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-ND  授权发布。最后生成于 2023-12-20.