GCC 运行时库例外条款的理由和常见问题解答

引言

2007 年 6 月 29 日,自由软件基金会发布了 GPLv3。它立即被 15 个 GNU 项目采用,并且在随后的几个月里有更多项目进行了切换。大多数 GCC 代码库在 4.2.2 版本中迁移到了新的许可证,现在我们正准备完成该过程。

一些随 GCC 发布的库的许可证尚未更改。这些库会被 GCC 生成的目标代码自动使用。因此,如果这些库只是根据 GPL 的条款进行分发,那么 GCC 生成的所有目标代码都必须按照相同的条款进行分发。然而,自由软件基金会很久以前就决定允许开发人员使用 GCC 的库来编译任何程序,无论其许可证如何。开发非自由软件对社会不利,我们没有义务使其更容易。我们决定允许这样做,因为禁止这样做似乎可能会适得其反,而且使用小型库来限制 GCC 的使用似乎是本末倒置。

因此,这些库一直都有许可证例外条款,允许人们在任何许可证下分发 GCC 生成的目标代码。我们现在正在将这些库迁移到 GPLv3,并更新其例外条款。我们的基本政策没有改变;新的许可证旨在允许之前允许的所有 GCC 用法。但是,我们已决定利用这次机会更新例外条款,以实现三个目标

  • 利用 GPLv3 的新规定。GPLv3 具有许多对所有软件有利的新条款。其中包括第 7 节,它为提供许可证例外条款建立了一个框架。为了使 GCC 从 GPLv3 中获得最大收益,我们需要更新例外条款以考虑这些新条款,并在第 7 节的参数范围内工作。

  • 为 GCC 中的插件基础设施奠定基础。一段时间以来,GCC 开发人员一直在考虑向编译器添加插件框架。这将使其他人更容易为该项目做出贡献,并加快 GCC 新编译技术的开发。然而,也有人担心,不择手段的开发人员可能会编写调用专有软件来转换编译代码的插件——有效地创建 GCC 的专有扩展,并破坏 GPL 的目的。更新后的例外条款可以防止此类滥用,使 GCC 团队能够期待插件的开发。

  • 使整个 GCC 代码库中的例外条款保持一致。多年来,随着需要携带此许可证例外条款的新文件添加到 GCC 中,我们审查并更新了语言,以帮助澄清它并解决新的问题。因此,现在 GCC 中有许多不同的例外文本提供了相同的基本权限。现在,所有这些文件都将能够使用我们准备的单个新例外文本,从而更容易对代码进行法律审查。

与 GPLv3 一样,我们在起草本文时努力倾听各种用户的担忧,并适当地解决这些问题。总而言之,我们在这个过程中花费了一年多的时间。自由软件基金会和 GCC 指导委员会要感谢软件自由法律中心的 Richard Fontana、Bradley Kuhn 和 Karen Sandler,感谢他们为例外条款付出的辛勤工作和帮助。这里的更改将加强 GCC 社区,我们期待它将实现的编译器开发。

由于 GCC 是开发人员生活中如此重要的一部分,我们预计会有很多关于这些更改的问题,我们希望确保这些问题得到解决。下面我们已经解决了我们预计用户会有的具体问题。如果您对这里没有提到的新例外条款有疑问,请随时通过 <[email protected]> 与我们联系。

例外条款如何运作

您需要的权限 - 在您自己的项目的许可证下传输来自这些 GCC 库的目标代码 - 主要包含在第 1 节中

您有权传播通过将运行时库与独立模块组合而形成的目标代码,即使这种传播方式在其他情况下会违反 GPLv3 的条款,前提是所有目标代码都是由合格的编译过程生成的。然后,您可以根据您选择的条款传输这种组合,这与独立模块的许可相一致。

本节使用了许多已定义的术语,它们的具体含义对于例外条款的工作方式至关重要。本节着眼于这些术语如何与常见场景相关。

当您编写软件时,它由一组源代码文件组成。只要不包含来自 GCC 库的任何源代码,每个文件都是一个“独立模块”。

当您编译这些源代码文件时,它们通常会经历一系列步骤:源代码生成、预处理、编译为低级代码、汇编和链接。并非所有项目都遵循所有这些步骤,这取决于您使用的语言以及它的编写方式,但它们将始终按照此顺序进行,并且所有使用 GCC 的人都将经历将高级代码编译为某种低级语言(例如汇编代码或 Java 字节码)的过程。在这个阶段,GCC 将您自己的代码与来自 GCC 库的代码组合或链接在一起。我们称之为“编译过程”。从其中获得的输出称为“目标代码”,只要该输出不用作编译器中间表示或创建这种中间表示。

为了利用此权限,您用来创建目标代码的编译过程必须是“合格的”,这意味着它不涉及 GCC 和与 GPL 不兼容的软件。请务必记住,当您将任何高级代码馈送到 GCC 时,编译过程就开始了,并且一旦它生成任何可以被视为目标代码的东西,它就结束了。因此,只要 GCC 没有写入中间表示,即使您将 GCC 与与 GPL 不兼容的汇编器、链接器或高级源生成器结合使用,您的编译过程仍然可以是合格的:这些程序不参与此处定义的编译过程。您不能将与 GPL 不兼容的软件与 GCC 一起使用的唯一位置是当它执行核心编译工作时。

因此,如果您使用 GCC(无论是否具有与 GPL 兼容的增强功能),那将是一个合格的编译过程。如果您仅使用与 GPL 不兼容的编译器工具,那么这也将是一个合格的编译过程。(对于为 GNU/Linux 构建软件的人来说,即使他们使用的是不同的编译器,链接到 GCC 库也很常见。)但是,如果您在将高级代码转换为低级代码的过程中将 GCC 与与 GPL 不兼容的软件结合使用,那将不是一个合格的编译过程。例如,如果您将 GCC 与专有插件一起使用,就会发生这种情况。

只要您使用合格的编译过程,那么您就有权在“您选择的条款下”传输 GCC 生成的目标代码。

如果您在编译过程中将与 GPL 不兼容的软件与 GCC 结合使用,您将无法利用此权限。由于 GCC 生成的所有目标代码都来源于这些 GPL 许可的库,这意味着您在传播任何目标代码时都需要遵守 GPL 的条款。您不能使用 GCC 来开发您自己的与 GPL 不兼容的软件。

常见问题解答

我正在使用标准版本的 GCC(例如由 FSF 提供或随我的操作系统提供的版本)来编译与 GPL 不兼容的软件。此更改如何影响我?

它应该根本不会影响您。除非您将 GCC 配置为输出中间表示(这种情况很少见),否则新的例外条款旨在确保您在执行此操作时没有许可义务,就像旧的例外条款一样。

此更改会影响谁?

目前正在使用 GCC 的任何人都不应受到此更改的影响。策略中的唯一更改旨在防止开发人员对 GCC 进行某些修改,这些修改在未来变得可行。FSF 一直与 GCC 开发人员密切合作,以了解更多关于人们今天使用 GCC 的许多不同方式,并确保他们都能够在新的例外条款下继续这些活动。

我将 GCC 与专有的预处理器和/或源生成器结合使用来编译我的程序。我仍然可以利用此例外条款吗?

可以。“完全以高级非中间语言表示的代码”可以开始编译过程。这包括由预处理器或其他专有软件生成的代码。因此,在这种情况下,编译过程不涉及任何专有软件;它符合合格标准,此例外条款适用于此程序。

我将 GCC 与专有的汇编器和/或链接器结合使用来编译我的程序。我仍然可以利用此例外条款吗?

可以。当编译器生成目标代码时,编译过程结束,其中包括“适合输入到汇编器、加载器、链接器和/或执行阶段”的输出。换句话说,在这种情况下,当您拥有来自 GCC 的汇编代码或未链接的目标文件时,编译过程就结束了,因此它不涉及任何专有软件。它符合合格标准,因此此例外条款适用于此程序。

我使用 GCC 来编译程序的一部分,而使用专有编译器来编译其他部分。这些部分在汇编或链接阶段之后组合在一起。我仍然可以利用此例外条款吗?

是的。在这种情况下,每个独立模块都通过合格的编译过程转换为目标代码。即使不同的模块会经过不同的过程,但此程序仍然可以使用该例外。

我使用一个不包含任何 GCC 部分的专有编译器工具链来编译我的程序,并将其与 libstdc++ 链接。我的程序本身不包含任何像 GCC 编译的程序那样包含的运行时库代码。我仍然可以利用该例外吗?

是的。虽然将 libgcc 与 GCC 编译的目标代码组合可能是最常见的例外使用方式,但 GPL 和 GCC 运行时库例外都没有在其条件中区分静态链接、动态链接和其他组合代码的方法。无论您使用哪种方法,您都可以在相同条款下获得相同的权限。

请注意,如果您将 libstdc++ 作为独立库分发,则在分发时需要遵守 GPL 的条款。例如,如果您以目标代码形式分发库本身,则需要使用 GPLv3 第 6 节中列出的方法之一向接收者提供源代码。但是,只要您有资格为自己的程序利用 GCC 运行时库例外的权限,GPL 的条款就不会扩展到它。

为什么编译器中间表示被排除在“目标代码”的定义之外?

当我们最初考虑向 GCC 添加插件基础设施时,我们非常担心有人会编写一个插件,该插件只是将 GCC 内部的低级编译数据结构保存到磁盘。完成后,其他软件将能够在不直接连接到 GCC 的情况下优化或改进该代码。我们可能很难辩称这些程序应受 GPL 的版权限制,因此我们想阻止此类安排。

我们通过将此类输出排除在目标代码的定义之外来实现这一点。因此,即使有人编写了一个将此信息保存到磁盘的插件,任何在 GCC 输出目标代码之前更改结构的程序都将参与编译过程。如果该程序是专有的,则该例外将不适用于使用它编译的任何软件;GCC 最终创建的目标代码必须根据 GPL 的条款分发。

如果我用汇编语言编写一些代码,我可以将其与其他正常编译的目标代码组合,并仍然利用该例外吗?

是的,只要所有目标代码都是通过合格的编译过程编译的。通过汇编器运行手写汇编的过程是一个编译过程,因为它“将完全以[一种]为人类编写代码而设计的非中间语言表示的代码...转换为目标代码。”

GCC 运行时库例外涵盖哪些库?

GCC 运行时库例外涵盖任何在其许可证标题中声明该例外适用的文件。这包括 libgcc、libstdc++、libfortran、libgomp、libdecnumber、libgcov 以及其他与 GCC 一起分发的库。

Classpath 会使用这个新的例外吗?

即使 Classpath 当前的例外具有类似的目的,我们目前也没有更新它。由于自由软件 Java 社区的最新发展,Classpath 的许可政策的优先级与其他 GCC 库不同,我们正在对其进行单独评估。