gcc中文参考大全.docx
《gcc中文参考大全.docx》由会员分享,可在线阅读,更多相关《gcc中文参考大全.docx(168页珍藏版)》请在冰豆网上搜索。
gcc中文参考大全
GCC技术参考大全
GCC(GNUCompilerCollection,GNU编译程序集合)是最重要的开放源码软件。
事实上,其他所有开放源码软件都在某种层次上依赖于它。
甚至其他语言,例如Perl和Python,都是由C语言开发的,由GNU编译程序编译的。
GCC编译程序的历史很有趣,远远不止是一个时间和事件的列表。
这个软件对于整个自由软件运动而言具有根本性的意义。
事实上,如果没有它或类似的软件,就不可能有自由软件运动。
GCC为Linux的出现提供了可能性。
本章概要介绍了GCC编译程序集合,以及它的相关工具。
这些编译中使用的工具可以跟踪源代码、编辑文件、控制编译过程、提供调试信息。
本章介绍的内容包括一个列表以及对处理过程的一些描述。
该列表描述了组成编译程序集合的文件和程序。
之后介绍了将源文件变成可连接和可执行程序的步骤。
1.1GNU
GCC是GNU项目的一个产品。
该项目始于1984年,目标是以自由软件的形式开发一个完整的类UNIX的操作系统。
像所有这种规模的软件一样,GNU项目也经历了一些波折,但目标最终还是实现了。
实际上现在一个功能完备的类UNIX操作系统——Linux,已经在世界上广为流传了,并被不计其数的公司、政府和个人成功应用。
而该系统及其所有工具和应用都是基于GCC的。
可用于Linux以及其他系统的自由软件的范围很广泛,并且还在日益增长。
作为整体GNU项目的一部分而开发的免费UNIX被列在http:
//www.gnu.org/directory中的自由软件目录(FreeSoftwareDirectory)中。
成千上万的程序员都在为各种GNU项目(及其他自由软件项目)作贡献,而实际上所有这些都在某种程度上依赖于GCC。
1.2测量编译程序
我们可以在编译的速度、生成代码的速度,以及生成代码的尺寸上对编译程序进行比较。
但是很难进行更深入的比较,因为虽然可以得出一些数字,却很难对这些数字赋予某种实际意义。
例如,源文件的数目(make程序的描述文件、配置文件、头文件、可执行代码,等等)显示共有超过15000个的各种文件。
源文件编译成的目标文件、库和可执行程序的数目成千增长。
代码的行数(这15000多个文件的行数)超过3700000。
从任何标准来看,这都是一个大程序。
代码的质量参差不齐——因为有如此之多的程序员参与开发过程,而且代码注释中也内嵌了大量的内部文档,所以文档的质量和数量也有变化。
所幸的是,有大量的程序员正在努力地提高代码和注释的质量。
而且,也不是必须阅读内嵌的注释才能使用编译程序。
但如果要对编译程序做些工作,你会发现还是要花些时间阅读代码中内嵌的注释。
测量编译程序的质量的惟一方法是询问它的用户。
全世界的用户数目很难估计(自由软件就有这样的特性),但一定是巨大的。
它被用于某些版本的UNIX,这些UNIX自带系统供应商提供的本地编译程序。
事实上,我知道一个很大的UNIX供应商就在自己内部的项目中使用GCC,即便该供应商也有自己的很优秀的编译程序。
GCC编译程序从未停止过改进。
如同第2章所描述的,通过下载某个特定版本的源代码便可安装已经发布的某个版本的GCC,也可以直接下载最新的(或测试中的)版本。
测试中的版本时刻都在改进。
有些更正是修改已有的bug,还有一些是为了加入新的语言和功能,还有一些是为了去掉某些不再应用的功能。
如果你曾经使用过GCC,隔一段时间再用最新版,一定会发现一些变化。
1.3命令行选项
每个命令行选项都以一个或一对连字号开始。
例如,下面的命令行会编译ANSI标准C程序muxit.c,再产生一个非连接的目标文件muxit.o:
gcc-ansi-cmuxit.c-omuxit.o
这些单字母选项后面跟着的名字可以和字母之间留有空格。
例如,选项-omuxit.o和-omuxit.o是一样的。
下面的命令用-v代表详细说明,而--help会打印可用的选项,而且会打印一个详细的包括所有命令行选项的列表,包括那些适用于特定语言的选项。
gcc-v--help
有可能构造一些实际不做任何事情的命令行。
例如,下面的命令将目标文件交给编译程序,然后指定-c选项防止激活连接程序:
gcc-cbrookm.o
所有的命令行选项大致可分为三类:
·指定语言GCC编译程序有能力编译多种语言,有些选项只可用于其中的一两种。
例如,-C89选项只应用于C语言,指定适用于1989年的标准。
·指定平台GCC编译程序可以为多种平台生成目标代码,而有些选项只能应用于为某个指定平台生成代码。
例如,如果输出平台是Intel386,那么-fp-ret-in-387选项可用来指出要将函数调用返回的浮点数保存在硬件的浮点寄存器中。
·普适很多选项对所有语言和平台都适用。
例如,-O选项指示编译程序要优化输出代码。
使用编译程序不知道的选项总会产生出错消息。
使用目标平台不适用的选项也会产生出错消息。
gcc程序能够自己处理所有已知的选项,而将未知其他选项传递下去来编译指定语言。
如果传递下去的选项对指定语言的处理器是未知的,就会报错。
选项可以指示gcc只执行特定的操作(例如连接或预处理)或什么都不做,这就是说有些标志没有什么特殊目的。
除非用-W选项产生特殊警告,否则这些标志可被识别但不采取任何动作,只简单忽略而已。
1.4平台
GCC编译程序集合可以在很多平台上运行。
平台是指特定计算机芯片及其运行的操作系统的组合。
尽管GCC已经被移植到数以千计的硬件/软件的组合上,但只有一些基本平台可以用来测试发布的正确性。
这些列在表1-1中的基本目标平台是最流行的,而且它们对GCC支持的其他平台具有代表性。
表1-1GCC应用的主要平台
硬件
操作系统
Alpha
RedHatLinux7.1
HPPA
HPUX11.0
Intelx86
DebianLinux2.2、RedHatLinux6.2和FreeBSD4.5
MIPS
IRIX6.5
(续表)
硬件
操作系统
PowerPC
AIX4.3.3
Sparc
Solaris2.7
要注意保证GCC可以在表1-1中列出的主要平台上正确运行,而且也要很好地处理其次列在表1-2中的平台。
表1-2GCC应用的次要平台
硬件
操作系统
PowerPC
Linux
Sparc
Linux
ARM
Linux
Intelx86
Cygwin
在这样少的主要和次要平台上测试的原因是人力问题。
即使你的平台没有被列在上面,编译程序还是可能在系统上能够良好运行的。
而且,完整的测试集合和编译程序的源代码一起提供,所以很容易验证编译程序是否工作正常。
另一种方法就是作为志愿者来测试你的平台,这样编译程序就可以在每次发布之前得到测试。
1.5编译程序的功能
编译程序是一个翻译器。
它读入一种语言格式的指令(通常是文本形式的编程语言),并将它们翻译成可在计算机上运行的指令集合(通常是二进制硬件指令的集合)。
大体上讲,编译程序可以分为两部分:
前端和后端。
前端读出程序的源代码,将找到的内容以树的形式转换到内存驻留表(memory-residenttable)中。
一旦构造了该树,编译程序的后端就会读出树中保存的信息,并将它们转换成目标机器上的汇编语言。
下面是关于将源文件翻译成可执行程序的大致步骤:
·词法分析是编译程序前端的最开始部分。
它从输入中读出字符,确定哪些是在一起的,形成符号、数字和标点符号。
·语法分析处理会读入来自词法浏览器的符号流,以及后面跟着的一个规则集合,确定它们之间的关系。
语法分析器的输出结果是树结构,会被传递给编译程序的后端。
·语法分析树结构会被翻译成伪汇编语言(psuedo-assemblylanguage),叫做寄存器传送语言(RegisterTransferLanguage,RTL)。
·编译程序的后端由分析RTL代码开始,然后执行一些优化操作。
代码中冗余和未被使用的部分会被去掉。
树中有些部分会被移动到其他位置以防止语句被不必要地多次执行。
总的说来,有十个以上的优化操作,而且有些优化操作会多次浏览代码。
·RTL被翻译成目标机器上的汇编语言。
·激活汇编器去将汇编语言翻译成目标文件。
该文件不是可执行格式——它包括可执行的目标代码,但并不是最终运行的形式。
另外,它更可能包括未解析的到其他模块例程和数据的引用。
·连接程序将来自汇编器的目标文件(其中有些可能保存在包含目标文件的库中)组合成可执行程序。
注意,前端和后端是完全分离开的。
任何语言都可用语法分析器产生树结构,而由GCC进行编译。
类似地,任何机器只要能将程序的树结构翻译成汇编语言,就能够编译由前端处理的所有语言。
实际操作过程绝对不像描述的那样简单,但这确实能够实现。
1.6语言
GCC可以编译多种语言,但所有这些语言之间有个基本关系。
语法分析器由于每种语言语法的惟一性而完全不同,但随着编译过程的前进,这些语言的代码就越来越相似。
如前所述,GNU编译集合可以接受任何形式编程语言的输入,产生的输出也可以在很多不同平台上运行。
1.6.1C是基本语言
GCC的基本语言是C语言。
整个编译系统由C编译程序开始,然后渐渐加了其他的语言进来。
幸运的是C语言是系统级的语言,能够直接处理计算机程序的基本元素,因此在它上面再创建其他语言的编译程序就相对容易得多。
如果你用其他语言而不是C语言编程,而你也对GCC很熟悉,你会发现很多东西都是以C语言的形式出现的。
可将C语言想成一种位于GCC编译程序的汇编语言之下的语言。
大多数编译程序本身都是由C语言实现的。
1.6.2C++:
第一个附加语言
C++语言是C语言的直接扩展(只有很小的改动),因此要向GCC加入其他语言,它是最佳首选。
C++能够完成的所有事情C语言都可以做到,所以没有必要修改编译程序的后端——只需要在前端载入一个新的语法语义分析器。
一旦产生中间语言,编译程序的其他部分就和C语言完全一样了。
1.6.3Objective-C
Objective-C并不像C语言或C++语言那样流行,但这是另一种源自(并基于)C语言的语言。
它被看作是“对象化的C语言”,事实上也是如此。
很大程度上,可以编写C程序,而被当作Objective-C编译并运行。
与基本C语法完全不同的特殊语法是用来定义对象的,所以它和纯粹的C代码没有什么混淆与冲突。
1.6.4Fortran
Fortran可以做到而C不能做到的事情就是:
科学计算。
标准Fortran函数库(这是Fortran的精髓,因为它就是语言的一部分)是一种扩展,已经趋于完美,而且也历经很多年了。
Fortran如今被用于科学计算是因为它的基本能力就是快速而准确地实现复杂计算。
Fortran甚至还将复杂的数字作为它的基本数据类型,而基本数值数据类型可具有很高的精确度。
这种语言的结构比其他的现代语言要麻烦一些,但它包含的一些基本函数和功能的实现是结构化编程所必需的。
最新的Fortran标准在这一点上有所扩展,无疑是一种非常现代的语言。
1.6.5Java
Java是包含进GCC的最年轻的语言。
Java语言和C++一样是基于C语言的,但它使用了一些不同的方法来实现类的语法。
C++更加灵活,Java则是通过限制对象的构造函数和析构函数去除了C++的不确定性,它继承的是一些严格无歧义的形式。
Java和GCC包含的其他语言有很大的区别,这是由它对象代码的形式决定的。
Java会编译成一种对象代码的特殊格式,作为字节码(bytecodes)被解释器(叫做Java虚拟机)执行。
所有Java程序都按照这种方式运行,直到GCC编译程序增加选项,通过挂接一个Java前端到已存在的GCC后端来产生本地可执行代码。
另外,还添加了一个前端来读出Java字节码,并作为源代码用来产生本地可执行的二进制代码。
1.6.6Ada
最新增加到GCC家族的是Ada。
它是作为一个功能完善的编译程序而加入的,最早是由AdaCoreTechnologies公司独立开发作为GNATAda95编译程序,在2001年10月捐赠给GCC。
Ada编译程序的前端和其他语言的不同,它是由Ada编写的。
一般来说,安装了Ada编译程序就可以了,但在一些系统中会需要特殊的引导过程。
而所有其他语言都是由C和C++编写的,因此几乎都可以普遍移植。
作为一种语言,Ada是专门为多个程序员编写大型程序而设计的。
在编译Ada程序的时候,它交叉引用程序其他部分的源代码来验证正确性。
这种语言的语法要求每个函数和过程都要被声明为包的一部分,而包的配置是和声明相匹配的。
C和C++语言用原型来声明外部引用函数,而Java使用文件命名规则定位包的成员,但这两种技术都不像Ada那样严格。
1.6.7不再支持Chill
GCC在3.0版之后不再支持Chill语言。
就在发布版本3.1之前,Chill语言的源代码也从GCC中移走了。
但GCC非常复杂,而Chill语言完整地作为其一部分已经存在一段时间了,所以还会从GCC在线文档中和源代码的各种不同位置中看到对Chill语言的引用。
本书是在这种转换过程中编写的,所以还会涉及到Chill编译程序选项和文件类型。
1.7部分列表
GCC是由许多组件组成的。
表1-3列出了GCC的各个部分,但它们也并不总是出现的。
有些部分是和语言相关的,所以如果没有安装某种特定语言,系统中就不会出现相关的文件。
表1-3GCC安装的各个部分
部分
描述
c++
gcc的一个版本,默认语言设置为C++,而且在连接的时候自动包含标准C++库。
这和g++一样
cc1
实际的C编译程序
cc1plus
实际的C++编译程序
collect2
在不使用GNU连接程序的系统上,有必要运行collect2来产生特定的全局初始化代码(例如C++的构造函数和析构函数)
configure
GCC源代码树根目录中的一个脚本。
用于设置配置值和创建GCC编译程序必需的make程序的描述文件
crt0.o
这个初始化和结束代码是为每个系统定制的,而且也被编译进该文件,该文件然后会被连接到每个可执行文件中来执行必要的启动和终止程序
cygwin1.dll
Windows的共享库提供的API,模拟UNIX系统调用
f77
该驱动程序可用于编译Fortran
f771
实际的Fortran编译程序
g++
gcc的一个版本,默认语言设置为C++,而且在连接的时候自动包含标准C++库。
这和c++一样
gcc
该驱动程序等同于执行编译程序和连接程序以产生需要的输出
(续表)
部分
描述
gcj
该驱动程序用于编译Java
gnat1
实际的Ada编译程序
gnatbind
一种工具,用于执行Ada语言绑定
gnatlink
一种工具,用于执行Ada语言连接
jc1
实际的Java编译程序
libgcc
该库包含的例程被作为编译程序的一部分,是因为它们可被连接到实际的可执行程序中。
它们是特殊的例程,连接到可执行程序,来执行基本的任务,例如浮点运算。
这些库中的例程通常都是平台相关的
libgcj
运行时库包含所有的核心Java类
libobjc
对所有Objective-C程序都必须的运行时库
libstdc++
运行时库,包括定义为标准语言一部分的所有的C++类和函数
表1-4列出的软件和GCC协同工作,目的是实现编译过程。
有些是很基本的(例如as和ld),而其他一些则是非常有用但不是严格需要的。
尽管这些工具中的很多都是各种UNIX系统的本地工具,但还是能够通过GNU包binutils得到大多数工具。
安装binutils的过程将在第2章中介绍。
表1-4GCC使用的软件工具
工具
描述
addr2line
给出一个可执行文件的内部地址,addr2line使用文件中的调试信息将地址翻译成源代码文件名和行号。
该程序是binutils包的一部分
ar
这是一个程序,可通过从文档中增加、删除和析取文件来维护库文件。
通常使用该工具是为了创建和管理连接程序使用的目标库文档。
该程序是binutils包的一部分
as
GNU汇编器。
实际上它是一族汇编器,因为它可以被编译或能够在各种不同平台上工作。
该程序是binutils包的一部分
autoconf
产生的shell脚本自动配置源代码包去编译某个特定版本的UNIX
c++filt
程序接受被C++编译程序转换过的名字(不是被重载的),而且将该名字翻译成初始形式。
该程序是binutils包的一部分
f2c
是Fortran到C的翻译程序。
不是GCC的一部分
gcov
gprof使用的配置工具,用来确定程序运行的时候哪一部分耗时最大
gdb
GNU调试器,可用于检查程序运行时的值和行为
GNATS
GNU的调试跟踪系统(GNUBugTrackingSystem)。
一个跟踪GCC和其他GNU软件问题的在线系统
(续表)
工具
描述
gprof
该程序会监督编译程序的执行过程,并报告程序中各个函数的运行时间,可以根据所提供的配置文件来优化程序。
该程序是binutils包的一部分
ld
GNU连接程序。
该程序将目标文件的集合组合成可执行程序。
该程序是binutils包的一部分
libtool
一个基本库,支持make程序的描述文件使用的简化共享库用法的脚本
make
一个工具程序,它会读makefile脚本来确定程序中的哪个部分需要编译和连接,然后发布必要的命令。
它读出的脚本(叫做makefile或Makefile)定义了文件关系和依赖关系
nlmconv
将可重定位的目标文件转换成NetWare可加载模块(NetWareLoadableModule,NLM)。
该程序是binutils的一部分
nm
列出目标文件中定义的符号。
该程序是binutils包的一部分
objcopy
将目标文件从一种二进制格式复制和翻译到另外一种。
该程序是binutils包的一部分
objdump
显示一个或多个目标文件中保存的多种不同信息。
该程序是binutils包的一部分
ranlib
创建和添加到ar文档的索引。
该索引被ld使用来定位库中的模块。
该程序是binutils包的一部分
ratfor
Ratfor预处理程序可由GCC激活,但不是标准GCC发布版的一部分
readelf
从ELF格式的目标文件显示信息。
该程序是binutils包的一部分
size
列出目标文件中每个部分的名字和尺寸。
该程序是binutils包的一部分
strings
浏览所有类型的文件,析取出用于显示的字符串。
该程序是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编译程序的范围很广——从简单的批处理工具程序到几百万行的规模的系统。
总的来说,当软件项目变得更大或者在某些方面变得特殊,在不能处理某些奇怪问题的时候,就会出现各种情况。
有些是bug,有些是特殊习惯,但有的不可避免地需要澄清——或者至少能够在正确的方向上引起注意。
所幸的是有帮助信息可供使用,而且可以找到关于GCC的一切信息。
信息的主要来源是邮件组。
开放的邮件组(所有的成员都可以收发邮件)的好处是可以立即展开讨论。
如果它有所帮助,我建议注册到gcc-help的邮件列表中。
开放邮件组上的对话会继续到情况被澄清或问题得到解决。
表1-5包括所有GCC开放邮件组的简要描述。
只读邮件组列在表1-6中。
表1-5GCC的开放邮件组
邮件组名
描述
gcc
这是开发GCC的基本讨论区。
如果只是要注册一个邮件组,这就是合适的选择。
它能够让你了解到最新的新闻和开发情况。
该邮件组信件很多
gcc-bugs
讨论bug和报告bug的邮件组。
这里的邮件也很多
gcc-help
该邮件组适用于那些寻找问题答案的人。
该邮件组信件很多
gcc-patches
源代码补丁和关于补丁的讨论会被提交到这个邮件组。
该邮件组信件很多
gcc-testresults
测试结果和对测试以及测试结果的讨论都会发到这里
java
关于GCC的Java前端的开发和维护的讨论列表,以及Java的运行时库的讨论列表
java-patches
关于Java前端和Java运行时库的源代码补丁被发布到该讨论组及gcc-patches邮件组
libstdc++
该讨论组用来讨论标准C++库的开发和维护
表1-6GCC的只读邮件组
邮件组名
描述
gccadmin
该邮件组收到的消息来自gcc.gnu.org的gccadmin账号运行的长时间任务
gcc-announce
该邮件列表信息较少,主要用来公布最新的版本发布,以及其他关于GCC的重要事件
gcc-cvs
每个登入到CVS仓库的人都会发消息到该邮件组
gcc-cvs-wwwdocs
每个登入到HTML文档的CVS仓库的人都会发消息到该邮件组
gcc-prs
每次当报告的问题进入GNATS数据库的时候都会向该邮件组发消息
gcc-regression
发送到这个邮件组的消息包含的是GCC回归测试的运行结果