GNU Compiler Collection linux版v4.7.0
GNU Compiler Collection(gcc编译器)是GNU计划的关键部分,也常被认为是跨平台编译器的事实标准。GCC不仅是GNU/Linux上的标准编译器,而且他也是嵌入式系统开发的标准编译器。这是因为GCC支持各种不同的目标架构。
GNU Compiler Collection是一套以GPL及LGPL许可证所发行的自由软件,也是GNU计划的关键部分,亦是自由的类Unix及苹果计算机Mac OS X 操作系统的标准编译器。GCC(特别是其中的C语言编译器)也常被认为是跨平台编译器的事实标准。
GCC原名为GNU C语言编译器(GNU C Compiler),因为它原本只能处理C语言。
GCC很快地扩展,变得可处理C++。之后也变得可处理Fortran、Pascal、 Objective-C、Java,以及Ada与其他语言。
【使用方法】
解压缩
拷贝gcc-4.1.2.tar.bz2(我下载的压缩文件)到/usr/local/src(根据自己喜好选择)下,根据压缩格式,选择下面相应的一种方式解包(以下的“%”表示命令行提示符):
% tar zxvf gcc-4.1.2.tar.gz
或者
% bzcat gcc-4.1.2.tar.bz2 | tar xvf -
新生成的gcc-4.1.2这个目录被称为源目录,用${srcdir}表示它。以后在出现${srcdir}的地方,应该用真实的路径来替换它。用pwd命令可以查看当前路径。
在${srcdir}/INSTALL目录下有详细的GCC安装说明,可用浏览器打开index.html阅读。
建立目标目录
目标目录(用${objdir}表示)是用来存放编译结果的地方。GCC建议编译后的文件不要放在源目录${srcdir]中(虽然这样做也可以),最好单独存放在另外一个目录中,而且不能是${srcdir}的子目录。
例如,可以这样建立一个叫 /usr/local/gcc-4.1.2的目标目录:
% mkdir /usr/local/gcc-4.1.2
% cd gcc-4.1.2
以下的操作主要是在目标目录 ${objdir} 下进行。
配置
配置的目的是决定将GCC编译器安装到什么地方(${destdir}),支持什么语言以及指定其它一些选项等。其中,${destdir}不能与${objdir}或${srcdir}目录相同。
配置是通过执行${srcdir}下的configure来完成的。其命令格式为(记得用你的真实路径替换${destdir}):
% ${srcdir}/configure --prefix=${destdir} [其它选项]
例如,如果想将GCC 4.1.2安装到/usr/local/gcc-4.1.2目录下,则${destdir}就表示这个路径。
在我的机器上,我是这样配置的:
% ../gcc-4.1.2/configure --prefix=/usr/local/gcc-4.1.2 --enable-threads=posix --disable-checking --enable--long-long --host=i386-redhat-linux --with-system-zlib --enable-languages=c,c++,java
将GCC安装在/usr/local/gcc-4.1.2目录下,支持C/C++和JAVA语言,其它选项参见GCC提供的帮助说明。
编译
% make
安装
执行下面的命令将编译好的库文件等拷贝到${destdir}目录中(根据你设定的路径,可能需要管理员的权限):
% make install
至此,GCC 4.1.2安装过程就完成了。
其它设置
GCC 4.1.2的所有文件,包括命令文件(如gcc、g++)、库文件等都在${destdir}目录下分别存放,如命令文件放在bin目录下、库文件在lib下、头文件在include下等。由于命令文件和库文件所在的目录还没有包含在相应的搜索路径内,所以必须要作适当的设置之后编译器才能顺利地找到并使用它们。
gcc、g++、gcj的设置
要想使用GCC 4.1.2的gcc等命令,简单的方法就是把它的路径${destdir}/bin放在环境变量PATH中。我不用这种方式,而是用符号连接的方式实现,这样做的好处是我仍然可以使用系统上原来的旧版本的GCC编译器。
首先,查看原来的gcc所在的路径:
% which gcc
在我的系统上,上述命令显示:/usr/bin/gcc。因此,原来的gcc命令在/usr/bin目录下。我们可以把GCC 4.1.2中的gcc、g++、gcj等命令在/usr/bin目录下分别做一个符号连接:
% cd /usr/bin
% ln -s ${destdir}/bin/gcc gcc412
% ln -s ${destdir}/bin/g++ g++412
% ln -s ${destdir}/bin/gcj gcj412
这样,就可以分别使用gcc412、g++412、gcj412来调用GCC 4.1.2的gcc、g++、gcj完成对C、C++、JAVA程序的编译了。同时,仍然能够使用旧版本的GCC编译器中的gcc、g++等命令。
库路径的设置
将${destdir}/lib路径添加到环境变量LD_LIBRARY_PATH中,例如,如果GCC 4.1.2安装在/usr/local/gcc-4.1.2目录下,在RH Linux下可以直接在命令行上执行
% export LD_LIBRARY_PATH=/usr/local/gcc-4.1.2/lib
最好添加到系统的配置文件中,这样就不必要每次都设置这个环境变量了,在文件$HOME/.bash_profile中添加下面两句:
LD_LIBRARY_PATH=/usr/local/gcc-4.1.2/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
重启系统设置生效,或者执行命令
% source $HOME/.bash_profile
测试
用新的编译命令(gcc412、g++412等)编译你以前的C、C++程序,检验新安装的GCC编译器是否能正常工作
编译警告
在编译时如果检测到一个错误,GCC就会退出编译过程,而警告信息就是显出了我们需要修正的潜在的问题,尽管也许仍会着生一个可执行文件。GCC提供了一个丰富的警告系统,但是为了利用可以检测到的警告范围,我们必须打开这些选项。
GCC最常用的用来检测警告信息就是-Wall选项。这会打开一个指定类型的所有警告信息,这由程序中最常遇到的问题组成。用法如下:
$ gcc -Wall test.c -o test
在-Wall选项中打开的警告选项如下:
选项 用途
unused-function 警告声明为静态但是却没有定义的函数
unused-label 警告声明但是却没有使用的标签
unused-parameter 警告没有使用的函数参数
unused-variable 警告没有使用的声明的局部变量
unused-value 警告计算但是却没有使用的值
format 验证printf中的格式字符串等基于指定的格式字符串的可用参数
implict-int 当声明没有指定类型时警告
implict-function- 函数的使用先于函数的声明时警告
char-subscripts 当使用字符作为数组的下标时警告
missing-braces 当初始集合没有被包含时警告
parentheses 如果()的省略引起误解时警告
return-type 警告函数的默认声明为int或是缺少返回值
sequence-point 代码元素可疑时警告
switch 在switch语句中缺少默认值,警告可以在switch参数中指定的缺少情况
strict-aliasing 对于变量转换使用严格的规则
unknown-pragmas 警告#pragma指令没有被识别
uninitilized 警告使用的变量没有进行初始化(只在-O2优化级别时可用)
-Wall是-all-warnings的同义。上表列出了在-Wall允许的各种警告选项。
在这里我们要注意大多数的选项都会有一个相反的形式,所以我们可以禁止他们。例如,如果我们希望打开-Wall选项,但是却要禁止没有用到的警告集合,我们可以使用下面的命令:
$ gcc -Wall -Wno-unused test.c -o test
下表列出在-Wall中没有打开的一些有用的选项
选项 用途
cast-align 当一个指针进行转换并且需要的赋值增加时警告
sign-compare 当一个有符号数与一个无符号数进行比较并产生一个不正确的值时警告
missing-prototypes 如果一个全局函数没有函数原型声明而使用时警告
packed 如果一个结构提供了打包属性而没有打包事件时警告
padded 如果一个结构进填补赋值时警告
unreachable-code 如果代码不会执行警告
inline 如果一个标记为内联但却不能实现内联时警告
disabled-optimization 当优化器不能执行指定的优化时警告
最后一个有用的警告选项是-Werror。这个选项指明当检测到错误时并不简单的显示错误,编译器会将警告当作错误对待并退出编译过程。这个选项对于生成高质量的代码是相当有用的。
调试选项
如果我们希望用一个符号链接调试器来调试我们的代码,我们可以指定-g选项来为GDB着生调用信息。-g选项可以指定一个参数来说明生成哪种格式。如果我们希望调试信息使用dwarf-2
格式来生成调试信息,我们可以使用下面的命令:
$ gcc -gdwarf-2 test.c -o test
其他的一些工具:
下面我们来看一些在我们的开发过程中有用的GNU工具。
首先,我们如何来知道可执行程序或是目标文件的大小?size实用程序可以使我们知道文本尺寸(指令条数)以及data和bss段。如下面的例子:
$ size test.o
text data bss dec hex filename
789 256 4 1049 419 test.o
在这里我们列出了目标文件test.o的文件大小。我们发现文本尺寸(指令和常量)是789字节,data段是256字节,bss段(初始时自动设置为0)是4字节。如果我们要知道更为详细的内容,我们可以使用objdump实用程序。我们可以使用-syms参数来知道可执行程序或是目标文件的符号表,如下面的例子:
$ objdump -syms test.o
这会产生一个目标文件中可用符号列表,他们的类型(text,bss,data),长度,偏移量等内容。我们也可以使用disassemble参数来反汇编程序,如下面的例子:
# objdump —disassemble test.o
这会产生一个目标文件中的函数列表,以及由GCC产生的指令。
最后,nm程序可以用来理解目标文件中的符号。这个程序不仅会列每一个符号以及符号类型的详细信息。还有一些其他的选项可用,我们可以从nm的主页中得到更为详细的内容。