First,GCC时LINUX开发的两大基础,另一个是Makefile。在所有LINUX开发中,GCC占有主要地位。因此在服务器,桌面和嵌入式领域开发都要对GCC开发比较相当熟悉。
Second,目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中符合ANSIC标准的编译系统。是Linux的基石,操作系统内核和大部分程序都是gcc编译的,是Linux下最重要开发工具之一。
gcc早期是c的编译器,后来发展能支持c/c++和object C,它可以通过不同的前端模块来支持各种语言,如Java、Fortran、Pascal、Modula-3和Ada等。
gcc是一个交叉平台的编译器,目前支持几乎所有主流CPU的处理器平台,包括中国设计的龙芯之类都是把GCC作为唯一的编译器来使用。
Thirdly,gcc支持的文件格式
gcc支持源码格式
- .c C源程序;
-.C,.cc,.cxx,.cpp C++源程序;
-m Objective-C源程序;
- .i 预处理后的C文件;
- .ii 预处理后的C++文件;
- .s 汇编语言源程序;
-.S 汇编语言源程序;
- .h 预处理器文件;
其它格式
- .o 目标文件(Object file)
- .a 归档库文件(Archive file)
gcc组成
1,gcc一般安装在/user/bin,gcc是一组编译工具的总称,包括:
– C 编译器 cc,cc1,cc1plus,gcc
– C++ 编译器 c++,cc1plus,g++
– 源码预处理程序 cpp,cpp0
– 库文件 libgcc.a,libgcc_eh.a,libgcc_s.so,ibiberty.a,libstdc++,libsupc++.a
示例编译一个hello过程分析
l 第一步是进行预编译,使用-E参数可以让GCC在预处理结束后停止编译过程:
– # gcc -E hello.c -o hello.i
l 下一步是将hello.i编译为目标代码,这可以通过使用-c参数来完成 , 。
– # gcc -c hello.i -o hello.o
l 最后一步是将生成的目标文件链接成可执行文件
– # gcc hello.o -o hello
l 注意:
– gcc编译时是对输入文件扩展名是敏感的,即.c一定会当做C代码编译,.cpp,.C ¡一定
会当成C++代码编译,这一点跟大部分Linux程序不一样
– gcc的结果输出是后缀名不相关的.只与输出参数相关.这跟一般Linux程序是一样
l gcc hello.c -o hello.o#虽然后缀名是.o ,但实际是一个应用程序
Finally,如果是多个源文件,一般先将源代码编译成目标代码。最后一次链接成可执行程序。
首先各自己编译成目标文件
l gcc -c link_list.c #将link_list.c编译成link_list.o
l gcc -c test_link.c #将test_link.c编译成test_link.o
– 然后将各个目标文件链接成一个文件
l gcc link_list.o test_link.o -o test_link
l #生成可执行文件test_link
NOTE:一个大型项目,一个可执行程序可能拥有多个位于不同目录的头文件,多个源码文件,还可能链接一些静态库或动态库,这一些都需要gcc的一些扩展选项。可能调用gcc很多次,需要写一个类似shell脚本的Makefile来调用gcc构造。
gcc 使用格式
-gcc 【option|filename】option为gcc使用时的选项
-g++【option|filename 】filename为欲以gcc处理的文件
gcc -x language 示例gcc -x c++ hello.c 强制用c++来编译
gcc-x none 关闭任何对语种的明确说明,因此依据文件名后缀处理后面的文件
gcc -c编译或汇编源文件,但是不做连接,编译器输出对应源文件的目标文件。
缺省情况下,GCC通过'.o'替换源文件名后缀'.c','.i''.s',等等,产生目标文件名可以使用-o选项选择其他名字。
-S编译后即停止,不进行汇编,对于每个输入的非汇编语言文件,输出文件是汇编语言文件。缺省条件下,GCC通过'.o'替换源文件后缀'.c','.i'等等,产生目标文件名。可以使用-o选项选择其他名字。GCC忽略任何不需要编译的输入文件。
-gcc -S hello.c -hello.s
-E
预处理后即停止,不进行编译,预处理后的代码送往标准输出,gcc忽略任何不需要预处理输入文件
-v
– ( 在标准错误) 显示执行编译阶段的命令. 同时显示编译器驱动程序, 预处理器, 编
译器的版本号.
– gcc -v
-pipe
– 在编译过程的不同阶段间使用管道而非临时文件进行通信.
– 在将源代码变成可执行文件的过程中,需要经过许多中间步骤,包含预处理、编译、
汇编和连接。这些过程实际上是由不同的程序负责完成的。大多数情况下GCC可以
为Linux程序员完成所有的后台工作,自动调用相应程序进行处理。
– 是GCC在处理每一个源文件时,最终都需要生成好几个临时文件才能完成相应的工
作,从而无形中导致处理速度变慢。例如,GCC在处理一个源文件时,可能需要一
个临时文件来保存预处理的输出、一个临时文件来保存编译器的输出、一个临时文件
来保存汇编器的输出,而读写这些临时文件显然需要耗费一定的时间。当软件项目变
得非常庞大的时候,花费在这上面的代价可能会变得很沉重。
– 解决的办法是,使用Linux提供的一种更加高效的通信方式--管道。它可以用来同时连
接两个程序,其中一个程序的输出将被直接作为另一个程序的输入,这样就可以避免
使用临时文件,但编译时却需要消耗更多的内存。
– gcc -pipe foo.c -o foo
gcc警告提示功能
l GCC包含完整的出错检查和警告提示功能, 它们可以帮助Linux程序员写出更加专业和优
美的代码。
l 编译警告代码
– -pedantic
l 打开完全服从ANSI C标准所需的全部警告诊断,如里出现非标准扩展,则拒绝编译,
所以叫书呆子pedant.
– -ansi
l 支持符合ANSI标准的C程序.
l 这样就会关闭GNU C中某些不兼容ANSI C的特性,例如asm, inline和 typeof关
键字,以及诸如unix和vax这些表明当前系统类型的预定义宏.同时开启 不受欢迎
和极少使用的ANSI trigraph特性,以及禁止`$'成为标识符的一部分.
与pedantic区别在于,只是警告,如果需要停止编译,仍然需要打开-pedantic
-Wall
– 打开所有编译警告
– gcc -Wall illcode.c -o illcode
l -Werror
– 视警告为错误; 出现任何警告即放弃编译.
– gcc -Wall -Werror illcode.c -o illcode
l -w
– 禁止输出警告信息
调试分析选项
l -g
– 以操作系统的本地格式(stabs, COFF, XCOFF,或DWARF).产生调试信息.
– GDB能够使用这些调试信息,是进行gdb调试必备条件
– 和大多数C编译器不同, GNU CC允许结合使用`-g¡®和`-O¡¯选项,但一般不建议一起
使用
– gcc hello.c -g -o hello
l -pg
– 产生额外代码,用于输出profile信息,供分析程序gprof使用.
l 所有调试选项会使用最终输出文件尺寸急剧增加,在最后发布,需要使用strip 命令把调试
信息去掉,
– strip hello
gprof 演示
l gprof 被用来测量程序的性能. 它记录每个函数被调用的次数以及相应的执行时间. 这样
就能锁定程序执行时花费时间最多的部分, 对程序的优化就可集中于对它们的优化.
– gcc -Wall -pg -o collatz collatz.c
l 生成 collatz 可执行文件后,先执行它,结果与一般程序的执行无疑。但此时在 PWD 目
录生成一个名为“gmon.out”的文件,gprof 通过它来分析程序的执行
– ./collatz #先执行一次生成 gmon.out
l 注意这一步运行不能用 Ctrl-C 中止执行,否则 gmon.out 生成不正常
– gprof ./collatz #分析结果