1、GCC 技术参考大全GCC ( GNU Compiler Collection , GNU 编译程序集合)是最重要的开放源码软件。事实上,其他所有开放源码软件都在某种层次上依赖于它。甚至其他语言,例如 Perl 和 Python ,都是由 C 语言开发的,由 GNU 编译程序编译的。 GCC 编译程序的历史很有趣,远远不止是一个时间和事件的列表。这个软件对于整个自由软件运动而言具有根本性的意义。事实上,如果没有它或类似的软件,就不可能有自由软件运动。 GCC 为 Linux 的出现提供了可能性。 本章概要介绍了 GCC 编译程序集合,以及它的相关工具。这些编译中使用的工具可以跟踪源代码、编辑文
2、件、控制编译过程、提供调试信息。 本章介绍的内容包括一个列表以及对处理过程的一些描述。该列表描述了组成编译程序集合的文件和程序。之后介绍了将源文件变成可连接和可执行程序的步骤。 1.1 GNUGCC 是 GNU 项目的一个产品。该项目始于 1984 年,目标是以自由软件的形式开发一个完整的类 UNIX 的操作系统。像所有这种规模的软件一样, GNU 项目也经历了一些波折,但目标最终还是实现了。实际上现在一个功能完备的类 UNIX 操作系统 Linux ,已经在世界上广为流传了,并被不计其数的公司、政府和个人成功应用。而该系统及其所有工具和应用都是基于 GCC 的。 可 用于 Linux 以及其
3、他系统的自由软件的范围很广泛,并且还在日益增长。作为整体 GNU 项目的一部分而开发的免费 UNIX 被列在 http:/www.gnu.org/directory 中的自由软件目录( Free Software Directory )中。 成千上万的程序员都在为各种 GNU 项目(及其他自由软件项目)作贡献,而实际上所有这些都在某种程度上依赖于 GCC 。 1.2 测量编译程序 我 们可以在编译的速度、生成代码的速度,以及生成代码的尺寸上对编译程序进行比较。但是很难进行更深入的比较,因为虽然可以得出一些数字,却很难对这些数字 赋予某种实际意义。例如,源文件的数目( make 程序的描述文件、
4、配置文件、头文件、可执行代码,等等)显示共有超过 15 000 个的各种文件。源文件编译成的目标文件、库和可执行程序的数目成千增长。代码的行数(这 15 000 多个文件的行数)超过 3 700 000 。从任何标准来看,这都是一个大程序。 代码的质量参差不齐因为有如此之多的程序员参与开发过程,而且代码注释中也 内嵌了大量的内部文档,所以文档的质量和数量也有变化。所幸的是,有大量的程序员正在努力地提高代码和注释的质量。而且,也不是必须阅读内嵌的注释才能使 用编译程序。但如果要对编译程序做些工作,你会发现还是要花些时间阅读代码中内嵌的注释。 测量编译程序的质量的惟一方 法是询问它的用户。全世界的
5、用户数目很难估计(自由软件就有这样的特性) ,但一定是巨大的。它被用于某些版本的 UNIX ,这些 UNIX 自带系统供应商提供的本地编译程序。事实上,我知道一个很大的 UNIX 供应商就在自己内部的项目中使用 GCC ,即便该供应商也有自己的很优秀的编译程序。 GCC 编译程序从未停止过改进。如同第 2 章所描述的,通过下载某个特定版本的源代码便可安装已经发布的某个版本的 GCC ,也可以直接下载最新的(或测试中的)版本。测试中的版本时刻都在改进。有些更正是修改已有的 bug ,还有一些是为了加入新的语言和功能,还有一些是为了去掉某些不再应用的功能。如果你曾经使用过 GCC ,隔一段时间再用
6、最新版,一定会发现一些变化。 1.3 命令行选项 每个命令行选项都以一个或一对连字号开始。例如,下面的命令行会编译 ANSI 标准 C 程序 muxit.c ,再产生一个非连接的目标文件 muxit.o : gcc -ansi -c muxit.c -o muxit.o 这些单字母选项后面跟着的名字可以和字母之间留有空格。例如,选项 -omuxit.o 和 -o muxit.o 是一样的。 下面的命令用 -v 代表详细说明,而 -help 会打印可用的选项,而且会打印一个详细的包括所有命令行选项的列表,包括那些适用于特定语言的选项。 gcc -v -help 有可能构造一些实际不做任何事情的命
7、令行。例如,下面的命令将目标文件交给编译程序,然后指定 -c 选项防止激活连接程序: gcc -c brookm.o 所有的命令行选项大致可分为三类: 指定语言 GCC 编译程序有能力编译多种语言,有些选项只可用于其中的一两种。例如,-C89 选项只应用于 C 语言,指定适用于 1989 年的标准。 指定平台 GCC 编译程序可以为多种平台生成目标代码,而有些选项只能应用于为某个指定平台生成代码。例如,如果输出平台是 Intel 386 ,那么 -fp-ret-in-387 选项可用来指出要将函数调用返回的浮点数保存在硬件的浮点寄存器中。 普适 很多选项对所有语言和平台都适用。例如, -O 选
8、项指示编译程序要优化输出代码。使用编译程序不知道的选项总会产生出错消息。使用目标平台不适用的选项也会产生出错消息。 gcc 程序能够自己处理所有已知的选项,而将未知其他选项传递下去来编译指定语言。如果传递下去的选项对指定语言的处理器是未知的,就会报错。 选项可以指示 gcc 只执行特定的操作(例如连接或预处理)或什么都不做,这就是说有些标志没有什么特殊目的。除非用 -W 选项产生特殊警告,否则这些标志可被识别但不采取任何动作,只简单忽略而已。1.4 平台 GCC 编译程序集合可以在很多平台上运行。平台是指特定计算机芯片及其运行的操作系统的组合。 尽管 GCC 已经被移植到数以千计的硬件 / 软
9、件的组合上,但只有一些基本平台可以用来测试发布的正确性。这些列在表 1-1 中的基本目标平台是最流行的,而且它们对 GCC 支持的其他平台具有代表性。 表 1-1 GCC 应用的主要平台 硬件 操作系统 Alpha Red Hat Linux 7.1 HPPA HPUX 11.0 Intel x86 Debian Linux 2.2 、 Red Hat Linux 6.2 和 FreeBSD 4.5 MIPS IRIX 6.5 (续表) 硬件 操作系统 PowerPC AIX 4.3.3 Sparc Solaris 2.7 要注意保证 GCC 可以在表 1-1 中列出的主要平台上正确运行,而且
10、也要很好地处理其次列在表 1-2 中的平台。 表 1-2 GCC 应用的次要平台 硬件 操作系统 PowerPC Linux Sparc Linux ARM Linux Intel x86 Cygwin 在 这样少的主要和次要平台上测试的原因是人力问题。即使你的平台没有被列在上面,编译程序还是可能在系统上能够良好运行的。而且,完整的测试集合和编译程序 的源代码一起提供,所以很容易验证编译程序是否工作正常。另一种方法就是作为志愿者来测试你的平台,这样编译程序就可以在每次发布之前得到测试。 1.5 编译程序的功能 编译程序是一个翻译器。它读入一种语言格式的指令(通常是文本形式的编程语言) ,并将它
11、们翻译成可在计算机上运行的指令集合(通常是二进制硬件指令的集合) 。 大体上讲,编译程序可以分为两部分:前端和后端。前端读出程序的源代码,将找到的内容以树的形式转换到内存驻留表( memory-resident table )中。一旦构造了该树,编译程序的后端就会读出树中保存的信息,并将它们转换成目标机器上的汇编语言。 下面是关于将源文件翻译成可执行程序的大致步骤: 词法分析是编译程序前端的最开始部分。它从输入中读出字符,确定哪些是在一起的,形成符号、数字和标点符号。 语法分析处理会读入来自词法浏览器的符号流,以及后面跟着的一个规则集合,确定它们之间的关系。语法分析器的输出结果是树结构,会被传
12、递给编译程序的后端。 语法分析树结构会被翻译成伪汇编语言( psuedo-assembly language ) ,叫做寄存器传送语言( Register Transfer Language , RTL ) 。 编译程序的后端由分析 RTL 代码开始,然后执行一些优化操作。代码中冗余和未被使用的部分会被去掉。树中有些部分会被移动到其他位置以防止语句被不必要地多次执行。总的说来,有十个以上的优化操作,而且有些优化操作会多次浏览代码。 RTL 被翻译成目标机器上的汇编语言。 激活汇编器去将汇编语言翻译成目标文件。该文件不是可执行格式 它包括可执行的目标代码,但并不是最终运行的形式。另外,它更可能包
13、括未解析的到其他模块例程和数据的引用。 连接程序将来自汇编器的目标文件(其中有些可能保存在包含目标文件的库中)组合成可执行程序。 注意,前端和后端是完全分离开的。任何语言都可用语法分析器产生树结构,而由 GCC 进行编译。类似地,任何机器只要能将程序的树结构翻译成汇编语言,就能够编译由前端处理的所有语言。 实际操作过程绝对不像描述的那样简单,但这确实能够实现。1.6 语言 GCC 可以编译多种语言,但所有这些语言之间有个基本关系。语法分析器由于每种语言语法的惟一性而完全不同,但随着编译过程的前进,这些语言的代码就越来越相似。如前所述, GNU 编译集合可以接受任何形式编程语言的输入,产生的输出
14、也可以在很多不同平台上运行。 1.6.1 C 是基本语言 GCC 的基本语言是 C 语言。整个编译系统由 C 编译程序开始,然后渐渐加了其他的语言进来。幸运的是 C 语言是系统级的语言,能够直接处理计算机程序的基本元素,因此在它上面再创建其他语言的编译程序就相对容易得多。 如果你用其他语言而不是 C 语言编程,而你也对 GCC 很熟悉,你会发现很多东西都是以 C 语言的形式出现的。可将 C 语言想成一种位于 GCC 编译程序的汇编语言之下的语言。大多数编译程序本身都是由 C 语言实现的。 1.6.2 C+ :第一个附加语言 C+ 语言是 C 语言的直接扩展(只有很小的改动) ,因此要向 GCC
15、 加入其他语言,它是最佳首选。 C+ 能够完成的所有事情 C 语言都可以做到,所以没有必要修改编译程序的后端只需要在前端载入一个新的语法语义分析器。一旦产生中间语言,编译程序的其他部分就和 C 语言完全一样了。 1.6.3 Objective-C Objective-C 并不像 C 语言或 C+ 语言那样流行,但这是另一种源自(并基于) C 语言的语言。它被看作是“对象化的 C 语言”,事实上也是如此。很大程度上,可以编写 C 程序,而被当作 Objective-C 编译并运行。与基本 C 语法完全不同的特殊语法是用来定义对象的,所以它和纯粹的 C 代码没有什么混淆与冲突。 1.6.4 For
16、tran Fortran 可以做到而 C 不能做到的事情就是:科学计算。标准 Fortran 函数库(这是 Fortran 的精髓,因为它就是语言的一部分)是一种扩展,已经趋于完美,而且也历经很多年了。 Fortran 如今被用于科学计算是因为它的基本能力就是快速而准确地实现复杂计算。Fortran 甚至还将复杂的数字作为它的基本数据类型,而基本数值数据类型可具有很高的精确度。 这种语言的结构比其他的现代语言要麻烦一些,但它包含的一些基本函数和功能的实现是结构化编程所必需的。最新的 Fortran 标准在这一点上有所扩展,无疑是一种非常现代的语言。 1.6.5 Java Java 是包含进 G
17、CC 的最年轻的语言。 Java 语言和 C+ 一样是基于 C 语言的,但它使用了一些不同的方法来实现类的语法。 C+ 更加灵活, Java 则是通过限制对象的构造函数和析构函数去除了 C+ 的不确定性,它继承的是一些严格无歧义的形式。 Java 和 GCC 包含的其他语言有很大的区别,这是由它对象代码的形式决定的。 Java 会编译成一种对象代码的特殊格式,作为字节码( bytecodes )被解释器(叫做 Java 虚拟机)执行。所有 Java 程序都按照这种方式运行,直到 GCC 编译程序增加选项,通过挂接一个 Java 前端到已存在的 GCC 后端来产生本地可执行代码。另外,还添加了一
18、个前端来读出 Java 字节码,并作为源代码用来产生本地可执行的二进制代码。 1.6.6 Ada 最新增加到 GCC 家族的是 Ada 。它是作为一个功能完善的编译程序而加入的,最早是由 Ada Core Technologies 公司独立开发作为 GNAT Ada 95 编译程序,在 2001 年 10 月捐赠给 GCC 。 Ada 编译程序的前端和其他语言的不同,它是由 Ada 编写的。一般来说,安装了 Ada 编译程序就可以了,但在一些系统中会需要特殊的引导过程。而所有其他语言都是由 C 和 C+ 编写的,因此几乎都可以普遍移植。 作 为一种语言, Ada 是专门为多个程序员编写大型程序
19、而设计的。在编译 Ada 程序的时候,它交叉引用程序其他部分的源代码来验证正确性。这种语言的语法要求每个函数和过程都要被声明为包的一部分,而包的配置是和声明相匹配的。 C 和 C+ 语言用原型来声明外部引用函数,而 Java 使用文件命名规则定位包的成员,但这两种技术都不像 Ada 那样严格。 1.6.7 不再支持 Chill GCC 在 3.0 版之后不再支持 Chill 语言。就在发布版本 3.1 之前, Chill 语言的源代码也从 GCC 中移走了。但 GCC 非常复杂,而 Chill 语言完整地作为其一部分已经存在一段时间了,所以还会从 GCC 在线文档中和源代码的各种不同位置中看到
20、对 Chill 语言的引用。本书是在这种转换过程中编写的,所以还会涉及到 Chill 编译程序选项和文件类型。1.7 部分列表 GCC 是由许多组件组成的。表 1-3 列出了 GCC 的各个部分,但它们也并不总是出现的。有些部分是和语言相关的,所以如果没有安装某种特定语言,系统中就不会出现相关的文件。 表 1-3 GCC 安装的各个部分 部分 描述 c+ gcc 的一个版本,默认语言设置为 C+ ,而且在连接的时候自动包含标准 C+ 库。这和 g+ 一样 cc1 实际的 C 编译程序 cc1plus 实际的 C+ 编译程序 collect2 在不使用 GNU 连接程序的系统上,有必要运行 co
21、llect2 来产生特定的全局初始化代码(例如 C+ 的构造函数和析构函数) configure GCC 源代码树根目录中的一个脚本。用于设置配置值和创建 GCC 编译程序必需的 make 程序的描述文件 crt0.o 这个初始化和结束代码是为每个系统定制的,而且也被编译进该文件,该文件然后会被连接到每个可执行文件中来执行必要的启动和终止程序 cygwin1.dll Windows 的共享库提供的 API ,模拟 UNIX 系统调用 f77 该驱动程序可用于编译 Fortran f771 实际的 Fortran 编译程序 g+ gcc 的一个版本,默认语言设置为 C+ ,而且在连接的时候自动包
22、含标准 C+ 库。这和 c+ 一样 gcc 该驱动程序等同于执行编译程序和连接程序以产生需要的输出 (续表) 部分 描述 gcj 该驱动程序用于编译 Java gnat1 实际的 Ada 编译程序 gnatbind 一种工具,用于执行 Ada 语言绑定 gnatlink 一种工具,用于执行 Ada 语言连接 jc1 实际的 Java 编译程序 libgcc 该库包含的例程被作为编译程序的一部分,是因为它们可被连接到实际的可执行程序中。它们是特殊的例程,连接到可执行程序,来执行基本的任务,例如浮点运算。这些库中的例程通常都是平台相关的 libgcj 运行时库包含所有的核心 Java 类 libo
23、bjc 对所有 Objective-C 程序都必须的运行时库 libstdc+ 运行时库,包括定义为标准语言一部分的所有的 C+ 类和函数 表 1-4 列出的软件和 GCC 协同工作,目的是实现编译过程。有些是很基本的(例如 as 和 ld ) ,而其他一些则是非常有用但不是严格需要的。尽管这些工具中的很多都是各种 UNIX 系统的本地工具,但还是能够通过 GNU 包 binutils 得到大多数工具。安装 binutils 的过程将在第 2 章中介绍。 表 1-4 GCC 使用的软件工具 工具 描述 addr2line 给出一个可执行文件的内部地址, addr2line 使用文件中的调试信息
24、将地址翻译成源代码文件名和行号。该程序是 binutils 包的一部分 ar 这是一个程序,可通过从文档中增加、删除和析取文件来维护库文件。通常使用该工具是为了创建和管理连接程序使用的目标库文档。该程序是 binutils 包的一部分 as GNU 汇编器。实际上它是一族汇编器,因为它可以被编译或能够在各种不同平台上工作。该程序是 binutils 包的一部分 autoconf 产生的 shell 脚本自动配置源代码包去编译某个特定版本的 UNIX c+filt 程序接受被 C+ 编译程序转换过的名字(不是被重载的) ,而且将该名字翻译成初始形式。该程序是 binutils 包的一部分 f2c
25、 是 Fortran 到 C 的翻译程序。不是 GCC 的一部分 gcov gprof 使用的配置工具,用来确定程序运行的时候哪一部分耗时最大 gdb GNU 调试器,可用于检查程序运行时的值和行为 GNATS GNU 的调试跟踪系统( GNU Bug Tracking System ) 。一个跟踪 GCC 和其他 GNU 软件问题的在线系统 (续表) 工具 描述 gprof 该程序会监督编译程序的执行过程,并报告程序中各个函数的运行时间,可以根据所提供的配置文件来优化程序。该程序是 binutils 包的一部分 ld GNU 连接程序。该程序将目标文件的集合组合成可执行程序。该程序是 bin
26、utils 包的一部分 libtool 一个基本库,支持 make 程序的描述文件使用的简化共享库用法的脚本 make 一个工具程序,它会读 makefile 脚本来确定程序中的哪个部分需要编译和连接,然后发布必要的命令。它读出的脚本(叫做 makefile 或 Makefile )定义了文件关系和依赖关系 nlmconv 将可重定位的目标文件转换成 NetWare 可加载模块( NetWare Loadable Module , NLM ) 。该程序是 binutils 的一部分 nm 列出目标文件中定义的符号。该程序是 binutils 包的一部分 objcopy 将目标文件从一种二进制格
27、式复制和翻译到另外一种。该程序是 binutils 包的一部分 objdump 显示一个或多个目标文件中保存的多种不同信息。该程序是 binutils 包的一部分 ranlib 创建和添加到 ar 文档的索引。该索引被 ld 使用来定位库中的模块。该程序是 binutils 包的一部分 ratfor Ratfor 预处理程序可由 GCC 激活,但不是标准 GCC 发布版的一部分 readelf 从 ELF 格式的目标文件显示信息。该程序是 binutils 包的一部分 size 列出目标文件中每个部分的名字和尺寸。该程序是 binutils 包的一部分 strings 浏览所有类型的文件,析取
28、出用于显示的字符串。该程序是 binutils 包的一部分 strip 从目标文件或文档库中去掉符号表,以及其他调试所需的信息。该程序是 binutils 包的一部分 vcg Ratfor 浏览器从文本文件中读取信息,并以图表形式显示它们。而 vcg 工具并不是 GCC 发布中的一部分,但 -dv 选项可被用来产生 vcg 可以理解的优化数据的格式 windres Window 资源文件编译程序。该程序是 binutils 包的一部分 1. 8 联系方式 GNU 的主页是 http:/www.gnu.org ,而 GCC 项目的主页是 http:/gcc.gnu.org 。 GCC 编译程序的
29、范围很广从简单的批处理工具程序到几百万行的规模的系统。总的来说,当软件项目变得更大或者在某些方面变得特殊,在不能处理某些奇怪问题的 时候,就会出现各种情况。有些是 bug ,有些是特殊习惯,但有的不可避免地需要澄清或者至少能够在正确的方向上引起注意。所幸的是有帮助信息可供使用,而且可以找到关于 GCC 的一切信息。 信息的主要来源是邮件组。开放的邮件组(所有的成员都可以收发邮件)的好处是可以立即展开讨论。如果它有 所帮助,我建议注册到 gcc-help 的邮件列表中。开放邮件组上的对话会继续到情况被澄清或问题得到解决。表 1-5 包括所有 GCC 开放邮件组的简要描述。只读邮件组列在表 1-6
30、 中。 表 1-5 GCC 的开放邮件组 邮件组名 描述 gcc 这是开发 GCC 的基本讨论区。如果只是要注册一个邮件组,这就是合适的选择。它能够让你了解到最新的新闻和开发情况。该邮件组信件很多 gcc-bugs 讨论 bug 和报告 bug 的邮件组。这里的邮件也很多 gcc-help 该邮件组适用于那些寻找问题答案的人。该邮件组信件很多 gcc-patches 源代码补丁和关于补丁的讨论会被提交到这个邮件组。该邮件组信件很多 gcc-testresults 测试结果和对测试以及测试结果的讨论都会发到这里 java 关于 GCC 的 Java 前端的开发和维护的讨论列表,以及 Java 的
31、运行时库的讨论列表 java-patches 关于 Java 前端和 Java 运行时库的源代码补丁被发布到该讨论组及 gcc-patches 邮件组 libstdc+ 该讨论组用来讨论标准 C+ 库的开发和维护 表 1-6 GCC 的只读邮件组 邮件组名 描述 gccadmin 该邮件组收到的消息来自 gcc.gnu.org 的 gccadmin 账号运行的长时间任务 gcc-announce 该邮件列表信息较少,主要用来公布最新的版本发布,以及其他关于 GCC 的重要事件 gcc-cvs 每个登入到 CVS 仓库的人都会发消息到该邮件组 gcc-cvs-wwwdocs 每个登入到 HTML
32、 文档的 CVS 仓库的人都会发消息到该邮件组 gcc-prs 每次当报告的问题进入 GNATS 数据库的时候都会向该邮件组发消息 gcc-regression 发送到这个邮件组的消息包含的是 GCC 回归测试的运行结果 java-announce 这个邮件组信息很少,它是用来发布关于 Java 前端或者 Java 运行时基本函数的消息的 java-cvs 每次登入到 Java 编译程序和 CVS 仓库运行时部分的时候,都会向该邮件组(以及 gcc-cvs 邮件组)发送消息 java-prs 每次报告的与 Java 有关的问题进入 GNATS 数据库的时候,都会向该邮件组(以及 gcc-prs
33、 邮件组)发送消息 libstdc+-cvs 每次登入到 CVS 仓库的 libstc+ 部分时,都会向该邮件组发送消息 有的邮件组都可在网站 http:/www.gnu.org/software/gcc/lists.html 中访问到。在该页面中可以订阅和退订这些邮件组。每个邮件组都有自己的网站,可用来查找并浏览该邮件组收到的消息。该邮件组的名字以 gcc.gnu.org/ml/ 开头是网站的名字。例如,要定位 gcc-announce 的文档网站,就要访问 http:/gcc.gnu.org/ml/gcc-announce 。 GCC 编译程序是在 GNU 通用公共许可证(也被叫做 GNU
34、 GPL ,或就叫做 GPL )之内的。由 GPL 保证的这种许可叫做 copyleft (版权所无) 。简单的说,这就意味着任何人都有权利复制并使用该软件,但如果它被集成进产品,该产品就必须也是 GPL 许可证的。就是说,不能使用 GPL 软件将它转换成专有的软件。然而,并不限制任何人用 GCC 作为工具创建自己需要形式的软件。变成生成程序中的二进制位以及片断不要求该程序得到 GPL 许可。 GPL 的另一种方案是弱通用公共许可证( Lesser General Public License , LGPL ) 。该许可证以前叫做库 GPL ,但这个名字由于可能产生误导就改变了它满足一些库,但
35、不会是所有库。 LGPL 允许专有程序使用的库例程以及共享的和非静态连接的库。例子就是标准 C 库的 GNU 版本。 下面是 GPL 的文本。它用非常清楚的语言描述了许可的细节。文档的末尾是对处理过程的描述,遵照此过程可以将自己的软件放在 GPL 下。 GNU GPL Version2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston , MA 02111-1307 USA 允许所有人复制和发布这一许可证原始文档的副本,但绝对不允许对它进行任
36、何修改。 导言 大 多数软件许可剥夺你共享和修改软件的自由。相比之下, GNU 通用公共许可力图保证你共享和修改自由软件的自由保证软件对所有用户是自由的。通用公共许可适用于大多数自由软件协会的软件,以及由使用这些软件而承 担义务的作者所开发的软件。 (自由软件协会的其他软件受 GNU 库通用公共许可的保护) 。你也可以将它应用到你的程序中。 当 我们谈到自由软件( free software )时,我们指的是自由而不是价格。 GNU 通用公共许可保证你有发布自由软件的自由(如果你愿意,可以对此项服务收取一定的费用) ;保证你能收到源程序或者在你需要时能得到它;保证你能修改软件或 将它的一部分用
37、于新的自由软件;而且还保证你知道你能做这些事情。 为了保护你的权利,我们作出规定:禁止任何人不承认你的权利,或者要求你放弃这些权利。如果你修改了自由软件或者发布了软件的副本,这些规定就转化为你的责任。 例如,如果你发布了这样一个程序的副本,不管是收费的还是免费的,你必须将你具有的一切权利给予你的接受者;你必须保证他们能收到或得到源程序;并且将这些条款给他们看,使他们知道他们有这样的权利。 我们采取两项措施来保护你的权利。 ( 1 )给软件以版权保护。 ( 2 )给你提供许可证。它给你复制、发布和 / 或修改这些软件的法律许可。 同 样,为了保护每个作者和我们自己,我们需要清楚地让每个人明白,自
38、由软件没有担保( no warranty ) 。如果由于其他某个人修改了软件,并继续加以传播。我们需要它的接受者明白:他们所得到的并不是原来的自由软件。由其他人引入的任何问题,不应损害原作 者的声誉。 最后,所有自由软件都不断受到软件专利的威胁。我们希望避免这样的风险,自由软件的再发布者以个人名义获得专利许可证,也就是将软件变为私有。为防止这一点,我们必须明确:任何专利必须以允许每个人自由使用为前提,否则就不准许有专利。 下面是有关复制、发布和修改的确切的条款和条件。 GNU 通用公共许可证 有关复制、发布和修改的条款和条件 0. 凡著作权人在其软件或其他著作中声明,该软件或著作得在通用公共许
39、可证条款下才能发布,本许可对其均适用。以下所称的“程序”,是指任何一种适用通用公共 许可的程序和著作;“基于本程序的著作” ,则指程序或任何基于著作权法所产生的衍生著作,换言之,是指包含本程序全部或部分的著作,不论是否完整或经过修 改的程序,以及(或)翻译成其他语言的程序(以下“修改”一词包括但不限于翻译行为) 。被许可的人则称为“您”。 本许可不适用于复制、发布及修改以外的行为;这些行为不在本许可范围内。执行本程序的行为并不受限制,而本程序的输出只有在其内容构成基于本程序所生的著 作(而非只是因为执行本程序所造成)时,是受到本许可约束的。至于程序输出的内容是否构成本程序的衍生著作,则取决于本
40、程序的具体用途。 1. 您可以对所收受的本程序源码,无论以何种媒介,复制与发布其完整的复制品,然而您必须符合以下条件:以显著及适当的方式在每份复制品上发布适当的著作权标 示及无担保声明;维持所有有关本许可以及无担保声明的原貌;并将本许可的副本连同本程序一起交付其他任一位程序收受者。 您可对授让复制品的实际行为请求一定的费用,也可自由决定是否提供担保作为收费的代价。 2. 您可以修改程序的一个或多个复制品或者程序的任何部分,以此形成基于本程序所生成的著作,并依前所述第一条规定,复制与发布修改过的程序或著作,但必须满足以下条件:a )您必须在所修改的文件上附加显著的标示,说明您修改过该文件,以及修
41、改日期。 b )必须就您所发布或发行的著作,无论是包含程序的全部还是部分的著作,或者是自程序或其他任何部分所衍生的著作,整体授权所有第三人可根据本许可规定使用,且不得因此项授权行为收取任何费用。 c )若经过修改的程序在执行时通常以互动方式读取命令时,您必须在最常用的方式下,于开始进入互动方式时,列出或展示以下宣告:适当的著作权标示以及无担保 声明(或声明由您提供担保) 、使用者可以根据这些条件再发布此程序,以及告知使用者如何浏览本许可的副本。 (例外:若程序本身是以交互方式执行的,然而通 常却不回列出该宣告时,那您基于本程序所生成的著作便无需列出该宣告。 ) 这些要求对修改过的著作是整体适用
42、的。如果著作中可识别的一部分并非衍生自本程序,并且可合理地认为是一个独立、个别的著作,则当您将其作为个别著作加以 发布时,本许可及其条款将不适用于该部分。当然当您将上述部分作为基于程序所生的著作的一部分而发布时,整个著作的发布就必须符合本许可条款的规定,而不 管这些部分的作者是谁。 因此,本条规定的意图不在于主张或剥夺您对完全由您所完成的著作的权利;应该说,本条规定意在行使对于基于程序的衍生著作或集合著作的发布行为的控制权。 此外,非基于本程序所生的其他著作与本程序(或基于本程序产生的著作)在同一存储或发布媒介上的单纯聚集行为,并不会使该著作因此受到本许可条件的约束。3. 可根据前面第一、二条
43、规定,复制和发布程序(或第二条所述基于程序产生的著作)的目标代码或可执行形式,但必须符合以下条件: a )附上完整的相对机器可读的源码,而这些源码必须依前面第一、二条规定在经常作为软件交互的媒介上发布;或 b )附上至少三年有效的书面报价文件,提供任何第三人在支付不超过实际发布源码所需成本的费用下,取得相同源码的完整的机器可读的复制品,并依照前面第一、二条规定在经常用以作为软件交互的媒介上发布该复制品;或 c )附上所收受的有关发布相同源码的报价信息。 (本项选择仅在非营利发布、且只在您依照前面 b 项方式自该书面报价文件收受程序目标代码或可执行形式时,才能适用。 ) 著 作的源码是指对著作进
44、行修改时适用的形式。对于可执行的著作而言,完整的源码是指著作中包含所有模式的全部源码,加上相关接口定义文件,还有用以控制该著 作编译及安装的描述。然而,特别的例外情况是,所发布的源码并不需包括任何通常会随着所执行操作系统的主要组成部分(编译程序、核心等)而发布的软件(无 论以源码或二进制格式) ,除非该部分本身就附加在可执行程序中。 如果可执行代码或目标代码的发布方式,是以指定的地点存取,供人复制,则提供可自相同地点复制源码的使用机会,看作是对源码的发布,然而第三人并不因此而负有将目标代码连同源码一起复制的义务。 4. 除本许可所明示的方式外,不得对程序加以复制、修改、再授权或发布。任何企图以
45、其他任何方式进行复制、修改、再授权或发布程序的行为均为无效行为,并将自 动终止您基于本许可所享有的权利。但依照本许可规定,从您手中收受复制品或权利的人,只要遵守本许可规定,他们所获得的许可并不会因此终止。 5. 因为您并未在本许可上签名,所以无需接受本许可。但除此之外,别无其他方式可以修改或发布程序或其衍生作品的授权许可。如不接受本许可,则这些行为在法律 上都是被禁止的。因此对程序(或任何基于本程序所生成的著作)的修改和发布行为,表示已经接受了本许可,以及接受了所有关于复制、发布及修改程序(或基于 程序生成著作)的条款和条件。 6. 每当再次发布程序(或任何基于程序所生成的著作)时,收受者就自
46、动获得原授权人所有的关于复制、发布或修改程序的权利。不得就本授权所赋予接收者行使的权利附加任何进一步的限制。对于第三人是否履行本许可,无须负责。 7. 如果法院判决、专利侵权主张或其他任何理由(不限于专利争议)的结果,使得加诸于您的条件(无论是由法院命令、协议或其他方式造成)与本许可规定有所冲 突,他们并不免除您必须遵守本许可的规定。如果无法同时符合本许可条件所生成的义务及其他相关义务而进行发布,那么后果就是不得发布该程序。例如,如果专 利授权不允许直接或间接通过您而取得复制品的人,以免付权利金的方式再发布该程序时,惟一能够同时满足该义务及本许可的方式就是彻底避免发布本程序。 如果本条任何一部
47、分在特殊情况下被认定无效或无法执行时,本条其余部分仍应适用,且本条全部内容在其他情况下仍然应该适用。 本条的目的并不是诱使您侵害专利或其他财产权的权利主张,或就此类主张的有效性加以争执;本条的惟一目的是保障公共授权惯例所执行的自由软件发布系统的完 整性。许多人信赖该系统一贯使用的应用程序,而对经由此系统发布的大量软件有相当多的贡献;作者 / 贡献者有权决定他或她是否希望经由其他系统发布软件,而被授权人则无该种选择权。 本条的用意在于将本许可其他不确定部分彻底解释清楚。 8. 如果因为专利或版权保护的接口问题,而使得本程序的发布与 / 或使用局限于某些国家时,则将本程序置于本许可规范之下的原著作
48、权人得增加明确的发布地区限制条款,将一些国家排除在外,而使发布的许可只限制在未排除的 国家之内。在该情况下,将限制条款如同以书面方式订定于本许可内容中,而成为本许可的条款。 9. 自由软件协会可以随时发布通用公共许可的修正版和 / 或新版本。新版本在精神上将近似于目前的版本,但在细节上有所不同以满足新的问题或状况。 每个版本都有单独的版本编号。如果程序指定授权版本编号,表示其适用于该版本或是“任何新版本”时,得选择遵循该版本或任何由自由软件协会日后所发布的更新版本的条款或条件。如果程序没有指出授权版本编号,便要选择任一自由软件协会所发布的版本。 10. 如果想要将部分程序纳入其他自由程序,而其
49、发布的条件有所不同时,请写信取得作者的许可。如果是自由软件协会享有著作权的软件,请写信到自由软件协会;我 们有时会以特殊方式予以处理。我们的决定取决于两项目标:确保自由软件的所有衍生著作均维护在自由状态,并广泛地促进软件的共享或再利用。 无担保声明 11. 由于本程序是无偿授权的,因此在法律许可范围内,本许可对程序不负担责任。非经书面声明,著作权人和 / 或其他提供程序的人,无论显式或隐式,均是依照“现状”提供程序而并无任何形式的担保责任,其包含并不限于,就适售性以及特定目的的使用性为默认性担保。 有关程序品质与效能的全部风险都由自己承担。如果程序被证明有瑕疵,您应该承担所有服务、修复或改正的费用。 12. 非经法律要求或书面同意,任何著作权人或任何可能依前述方式修改和 / 或发布程序的人,对于您因为使用或不能使用程序所造成的一般性、特殊性、意外性或间接性损失,不负任何责任(包括但不限于数据损失、数据执行不精确、或应 由您或第三人承担的损失,或程序无法与其他程序运作等) ,即便前述的著作权人或其他团体已被告知这种损失的可能性。 条款结束 如何将这些条款用于你的新程序 如果你开发了新程序,而且希望它得到公众最大限度的利用。最好的办法就是将它变为