精通GCC编译器content•GCC概论•GCC深入探索•GCC的编译选项•GCC的应用技巧01.GCC是何物?Linux系统下的gcc(GNUCCompiler)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作品之一。gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%~30%。gcc编译器能将C、C++语言源程序、汇程式化序和目标程序编译、连接成可执行文件,如果没有给出可执行文件的名字,gcc将生成一个名为a.out的文件。在Linux系统中,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件。而gcc则通过后缀来区别输入文件的类别,下面我们来介绍gcc所遵循的部分约定规则。DEMOGCC的几个版本•请问GCC和cc有啥区别?•怎样在linux下查看GCC的版本信息?查看版本信息安装路径:相关文件类型:c为后缀的文件,C语言源代码文件;.a为后缀的文件,是由目标文件构成的档案库文件;.C,.cc或.cxx为后缀的文件,是C++源代码文件;.h为后缀的文件,是程序所包含的头文件;.i为后缀的文件,是已经预处理过的C源代码文件;.ii为后缀的文件,是已经预处理过的C++源代码文件;.m为后缀的文件,是Objective-C源代码文件;.o为后缀的文件,是编译后的目标文件;.s为后缀的文件,是汇编语言源代码文件;.S为后缀的文件,是经过预编译的汇编语言源代码文件。gcc编译的4个过程:•预处理(也称预编译,Preprocessing):–命令gcc首先调用cpp进行预处理,在预处理过程中,对源代码文件中的文件包含(include)、预编译语句(如宏定义define等)进行分析。•编译(Compilation):–接着调用cc1进行编译,这个阶段根据输入文件生成以.o为后缀的目标文件。•汇编(Assembly):–汇编过程是针对汇编语言的步骤,调用as进行工作。•连接(Linking):–当所有的目标文件都生成之后,gcc就调用ld来完成最后的关键性工作,这个阶段就是连接参考:《深入透析》演示:•DEMO•基本的用法是∶gcc[options][filenames]1、没有任何选项:gcchelloworld.c结果会在和helloworld.c相同的目录下产生一个a.out的可执行文档。2、-o选项,指定输出文档名:gcc-ohelloworldhelloworld.c-o意思是Output即需要指定输出的可执行文档的名称。这里的名称为helloworld。3、-c选项,只编译,不汇编连接:gcc-chelloworld.c-c意思就是Compile,产生一个叫helloworld.o的目标文档4、-S选项,产生汇编源文档:gcc-Shelloworld.c-S意思就是aSsemble,产生一个叫helloworld.s的汇编源文档5、-E选项,预处理C源文档:gcc-Ehelloworld.c-E意思就是prEprocess。输出不是送到一个文档而是标准输出。当然能够对他进行重定向:gcc-Ehelloworld.chelloworld.txt优化选项-O选项,基本优化:gcc-Ohelloworld.c-O意思就是Optimize,产生一个经过优化的叫作a.out的可执行文档。也能够同时使用-o选项,以指定输出文档名。如:gcc-O-otesthelloworld.c即会产生一个叫test的经过优化的可执行文档。-O2选项,最大优化:gcc-O2helloworld.c产生一个经过最大优化的叫作a.out的可执行文档。调试选项-g选项,产生供gdb调试用的可执行文档:gcc-ghelloworld.c产生一个叫作a.out的可执行文档,大小明显比只用-o选项编译汇编连接后的文档大。-pg选项,产生供gprof剖析用的可执行文档:gcc-pghelloworld.c产生一个叫作a.out的执行文档,大小明显比用-g选项后产生的文档还大。02.GCC快速入门•第一个实例hello!•DEMOGCC常用编译开关•-w禁止输出警告消息•-Werror将所有警告转换为错误•-Wall显示所有的警告消息•-v显示编译程序的当前版本号•-static连接器将忽略动态连接库,同时通过将静态目标文件直接包含到结果目标文件完成对所有引用的解析。•-shared-fPCI连接器将生成共享目标代码,•-pipe使用管道而不是临时文件一个阶段到另一个阶段交换输出的方式,可以加快编译速度。建议使用。•-ofilename指定输出文件,对各种输出皆有效。•-Idir指定搜索系统头文件的目录,可以重复使用多个该选项指定多个目录•-Dmacro:相当于C语言中的#definemacro•-UMACRO取消对MACRO宏的定义•-c/-C:只激活预处理,编译,和汇编,也就是他只把程序做成obj文件•-o:指定目标名称•-On(0,1,2,3):•-S:只激活预处理和编译,就是指把文件编译成为汇编代码•-E:只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面.•-Idir:使用-I制定了目录,先在你所制定的目录查找,然后再按常规的顺序去找头文件.•-M:生成文件关联的信息。包含目标文件所依赖的所有源代码。•-llibrary:指定编译的时候使用的库•-Ldir:指定编译时搜索库的路径•-g:指示编译器在编译时产生调试信息。•-static:此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么动态连接库,就可以运行.建立自己的GCC编译环境•一个系统上如何同时存在并使用多个版本的GCC编译器?•建立目标目录:–在gcc源代码同一级目录下(与源目录${srcdir}是同级目录)–%mkdirgcc-build–%cdgcc-build•配置环境:–%../gcc-3.4.0/configure--prefix=/usr/local/gcc-3.4.0--enable-threads=posix--disable-checking--enable--long-long--host=i386-redhat-linux--with-system-zlib--enable-languages=c,c++,java–将GCC安装在/usr/local/gcc-3.4.0目录下,支持C/C++和JAVA语言•编译安装:–%make&&makeinstall•其它配置:–GCC3.4.0的所有文件,包括命令文件(如gcc、g++)、库文件等都在${destdir}目录下分别存放,如命令文件放在bin目录下、库文件在lib下、头文件在include下等。由于命令文件和库文件所在的目录还没有包含在相应的搜索路径内,所以必须要作适当的设置之后编译器才能顺利地找到并使用它们。–用符号连接的方式实现,这样做的好处是我仍然可以使用系统上原来的旧版本的GCC编译器。–%ln-s${destdir}/bin/gccgcc34–库路径的设置:exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:{destdir}/lib–setenvLD_LIBRARY_PATH/usr/local/gcc-3.4.0/lib:$LD_LIBRARY_PATH03.GCC的编译环境•工具:–gccc编译器,它在链接时使用c库–cc1实际的c编译器–cc1plus实际的c++编译器–collect2使用collect2产生特定的全局初始化代码,后台处理是传递参数给ld完成实际的链接工作。–crt0.o初始化和结束代码–libgcc平台相关的库•binutils相关工具:–as:gnu汇编工具–gprof:性能分析工具–ld:gnu链接器,链接器可以读写各种目标文件中的信息,通过BFD(binaryfiledescriptor)提供的工具实现,BFD定义了类似a.out,elf,coff等目标文件的格式–make:–objcopy:目标文件从二进制格式翻译或复制到另一种–objdump:显示目标文件的各种信息–strings:显示文件的字符串–strip:去除符合表–readelf:分析elf并显示信息•gcc预处理相关–#defineTEST(ARGTERM)printf(“theterm“#ARGTERM“isastring\n”)–#defineerr(...)fprintf(stderr,_VA_ARGS__)err(%s%d\n,errorcodeis,48);//实现可变参数宏的定义.–error和warning指令–if,elif,else,endif指令•gcc预定义宏–__BASE_FILE__完整的源文件名路径–__cplusplus测试c++程序–__DATE__日期–__FILE__源文件名–__func__替代__FUNCTION__,__FUNCTION__以被GNU不推荐使用–__TIME__日期–__LINE__行数–__VERSION__gcc版本•gas汇编工具(AT&T的风格)•ld:–ld把一定量的目标文件跟档案文件连接起来,并重定位它们的数据,连接符号引用.一般在编译一个程序时,最后一步就是运行ld。•autoscanfautomake等工具•运行环境变量路径的问题•makefile+make+configure脚本–Makefile包含了所有的规则和目标,而make则是为了完成目标而去解释Makefile规则的工具。–根据源码包中Makefile.in文件的指示,configure脚本检查当前的系统环境和配置选项在当前目录中生成Makefile文件(还有其它本文无需关心的文件),然后make程序就按照当前目录中的Makefile文件的指示将源代码编译为二进制文件,最后将这些二进制文件移动(即安装)到指定的地方(仍然按照Makefile文件的指示)。•autoconf–主要根据程式员提供的configure.in,生成能够自动检测系统配置的脚本configure。而后再由configure根据各目录下的Makefile.in自动生成Makefile。这样,程式员就能够直接使用具备丰富功能的Makefile了。•autoconf产生makefile的过程:–运行autoscan命令–将configure.scan文档重命名为configure.in,并修改configure.in文档–在project目录下新建Makefile.am文档,并在core和shell目录下也新建makefile.am文档–在project目录下新建NEWS、README、ChangeLog、AUTHORS文档–将/usr/share/automake-1.X/目录下的depcomp和complie文档拷贝到本目录下–运行aclocal命令–运行autoconf命令–运行automake-a命令–运行./confiugre脚本•automake–由于Makefile.in仍然可能比较复杂,automake能够根据程式员编写的Makefile.am自动生成Makefile.in。–在调用automake时,往往要使用-a选项,该选项将自动建立一些项目需要的文档(以建立符号连接的形式),他们是:install-sh、missing、mkinstalldirs、doc/mdate-sh等等。–假如在除了使用-a选项外,还使用-c选项,则不是在项目目录中制作到系统相应文档的连接,而是将文档复制到项目目录中。03.GCC编译优化•优化原理:–从运行时的依赖关系来看,对性能有较大影响的组件有kernel和glibc,经过正确的版本选择、合理的配置、优化编译的内核与C库将对提高系统的性能起着基础性的作用。–从被编译的软件包来看,每个软件包的configure脚本都提供了许多配置选项,其中有许多选项是与性能息息相关的。比如,对于Apache