关闭

关闭

关闭

封号提示

内容

首页 GCC编译器.pdf

GCC编译器.pdf

GCC编译器.pdf

上传者: 秋末 2012-04-02 评分 0 0 0 0 0 0 暂无简介 简介 举报

简介:本文档为《GCC编译器pdf》,可适用于IT/计算机领域,主题内容包含SeptNeusoftConfidentialLinux应用程序开发环境课程体系Linux基础Linux应用程序开发环境Linux系统管理及应用Li符等。

SeptNeusoftConfidentialLinux应用程序开发环境课程体系Linux基础Linux应用程序开发环境Linux系统管理及应用Linux网络编程Linux系统编程Linux设备驱动嵌入式Linux系统构建嵌入式Linux应用开发(初级)Linux应用开发(初级)嵌入式Linux设备驱动开发DNS服务Apache服务及配置Postfix详解Linux网络配置及管理CVSGITSVN配置管理QT图形开发DFBGTK图形开发GTK图形开发Mysql数据库管理文件系统服务及搭建wxWidgets图形开发SDL应用开发MINIGUI图形开发嵌入式基础开发开发开发系统管理系统管理系统管理Linux系统下的线程开发Mysql数据库开发初级层初级层初级层进入层进入层进入层高级层高级层高级层专家层专家层专家层LinuxShell高级编程防火墙配置及管理Linux系统日志管理及维护CocoaObjectiveC开发Oracle数据库环境构建课程结构内容课时(H)第一章:GCC编译器第二章:Makefile写法及自动化工具第三章:GDB调试器及调试方法第六章:Shell编程(可选)第四章:GCC编译器目标:本章使学员掌握Linux操作系统下GCC编译器的使用:)了解gcc必要参数)掌握如何利用gcc编译c程序时间:学时教学方法:讲授PPT上机操作实例演示gnugcc简介z目前Linux下最常用的C语言编译器是GCC(GNUCompilerCollection)它是GNU项目中符合ANSIC标准的编译系统z是Linux的基石,操作系统内核和大部分程序都是gcc编译的,是Linux下最重要开发工具之一zgcc早期是c的编译器,后来发展能支持c,c和objectC,它可以通过不同的前端模块来支持各种语言如Java、Fortran、Pascal、Modula和Ada等。zgcc是一个交叉平台的编译器,目前支持几乎所有主流CPU的处理器平台gcc支持的文件格式zgcc支持源码格式–cC源程序–C,cc,cxx,cppC源程序–mObjectiveC源程序–i预处理后的C文件–ii预处理后的C文件–s汇编语言源程序–S汇编语言源程序–h预处理器文件z其它格式–o目标文件(Objectfile)–a归档库文件(Archivefile)GCC组成zgcc一般安装在usrbinzgcc是一组编译工具的总称,包含如下工作–C编译器cc,cc,ccplus,gcc–C编译器c,ccplus,g–源码预处理程序cpp,cpp–库文件libgcca,libgcceha,libgccsso,ibibertya,libstdc,libsupcagcc的起步z生成一个hello,world程序–gcchellocohello#把helloc编译成一个可执行程序hello–gcchelloc#不指定输出名,生成一个aout#include<stdioh>#defineMYNUMBERintmain(void){printf("Hellod,theWorld!n",MYNUMBER)return}SeptNeusoftConfidential可执行程序的构造z任何一个可执行程序从源代码到可执行的二进制程序之中都要经过固定的几步–预编译(PreProcessing)•这一步完成对预编译代码的处理–编译(Compiling)•将源代码编译成汇编代码–汇编(Assembling)•将汇编代码汇编成目标文件–链接(Linking)•将目标代码和所需要库的链成一个完整的应用程序z集成开发环境(IDE)自动协助开发完成这几步,如VCz在Linux下,如果使用命令行开发工具(gcc,ld,ar)等,需要用户手工调用这一些命令来完成这几步骤gcc在构建程序的作用zgcc在构建应用程序里,会调用不同的应用程序完成每一步因此在开发中,gcc处于一个核心地位大部分开发只需要调用gcc即可。zgcc所做操作–gcc调用cpp进行预处理–gcc调用cc进行编译,会生成汇编代码–gcc调用as对汇编代码,生成扩展名为o的目标文件–gcc调用ld来完成对所有目标文件的链接为什么要用gccz随着Linux的GUI改进,也出现了越来越多的IDE开发环境象VC,自动完成各个开发流程z但很多IDE基本上是基于gcc编译z而且大部分项目,包括嵌入式开发,都提供gcc命令行开发模式z因此用gcc开发是Linux和嵌入式开发的必须使用的工具也是基本功之一zGCC是免费的。z大家都用GCC易于发现问题。hello编译过程分析注意:gcc编译时是对输入文件扩展名是敏感的,即c一定会当做C代码编译,cpp,C…一定会当成C代码编译,这一点跟大部Linux程序不一样gcc的结果输出是后缀名不相关的只与输出参数相关这跟一般Linux程序是一样gcchellocohelloo#虽然后缀名是o,但实际是一个应用程序•预处理(PreProcessing)#gccEhellocohelloior#cpphellocohelloi•编译(Compiling)#gccShelloiohellosor#cchelloiohellos•汇编(Assembling)#gccchellosohellooor#ashellosohelloo•链接(Linking)#gcchellooohelloor#ldhellooohello预处理编译汇编链接可执行源文件gcc各个编译步骤多文件gcc的处理z在采用模块化的设计思想进行软件开发时通常整个程序是由多个源文件组成的相应地也就形成了多个编译单元使用GCC能够很好地管理这些编译单元。假设有一个由fooc和fooc两个源文件组成的程序为了对它们进行编译并最终生成可执行程序foo可以使用下面这条命令:–gccfoocfoocofooz在编译一个包含许多源文件的工程时若只用一条GCC命令来完成编译是非常浪费时间的。假设项目中有个源文件需要编译并且每个源文件中都包含行代码如果像上面那样仅用一条GCC命令来完成编译工作那么GCC需要将每个源文件都重新编译一遍然后再全部连接起来。很显然这样浪费的时间相当多尤其是当用户只是修改了其中某一个文件的时候完全没有必要将每个文件都重新编译一遍因为很多已经生成的目标文件是不会改变的。要解决这个问题关键是要灵活运用GCC同时还要借助像Make这样的工具。用gcc构造程序()z如果可执行程序只由一个源代码文件构造出来那么只需要用到如下形式–gcchellocohello•表示将helloc一次做完四步,构造出可执行程序hello,–gcchelloc•将helloc构造一个可执行程序,有缺省名aout,但不建议这样做–gccchellocohello•这一步骤是初学者常犯错误以为等于在一次性构造应用程序hello•但实际上这只是在编译c并生成一个目标文件hello,即便是没有o的后缀这个用file命令可以很容易查看,这个hello是无法执行用gcc构造程序()z使用多个源码的项目,如项目中包含个以上的源代码,一般要先将源代码编译成目标代码最后一次链接成可执行程序z以链表测试程序为例整个项目由三个c代码(testlinkc和dllistc和dlfilec)和一个头文件(dllisth)组成–头文件是包含在源代码里,由预处理程序处理,不需要编译–首先各自己编译成目标文件•gcccdllistc#将dllistc编译成dllisto•gcccdlfilec#将dlfilec编译成dlfileo•gccctestlinkc#将testlinkc编译成testlinko–然后将各个目标文件链接成一个文件•gccdllistodlfileotestlinkootestlink•#生成可执行文件testlinkz也可以直接把两个文件在一句里编译,但强烈建议不要这样做–gccdllistcdlfilectestlinkcotestlink编译testlink实例用gcc构造程序()z对于有头文件在多个目录时,需要在编译时多次使用用I参数加入头文件所在目录–例如testlinkc需要用到usrinclude,当前目录(),homehxy目录下的头文件则如下编译–gccIIusrincludeIhomehxyctestlinkcgcc构造复杂程序z一个大型项目,一个可执行程序可能拥有多个位于不同目录的头文件,多个源码文件,还可能链接一些静态库或动态库,这一些都需要用到gcc的一些扩展选项–gcc的参数参见下一节z可能调用gcc很多次,如果完全手工编写,将是一个浩大的工程–需要写一个类似Shell脚本的Makefile来调用gcc构造SeptNeusoftConfidentialgcc完整使用格式zgcc使用格式–gccoption|filename–goption|filename–其中option为gcc使用时的选项(后面会再详)而filename为欲以gcc处理的文件z总体选项(OverallOption)–cSEofilepipevxlanguagegcc选项()zxlanguage–明确指出后面输入文件的语言为language(而不是从文件名后缀得到的默认选择)这个选项应用于后面所有的输入文件,直到遇着下一个`x‘选项language的可选值有`c’,`objectivec‘,`cheader’,`c‘,`cppoutput’,`assembler‘,和`assemblerwithcpp’。–gccxchelloc•强制用c来编译zxnone–关闭任何对语种的明确说明,因此依据文件名后缀处理后面的文件(就象是从未使用过`x‘选项)。gcc选项()zc–编译或汇编源文件,但是不作连接编译器输出对应于源文件的目标文件–缺省情况下,GCC通过用`o'替换源文件名后缀`c',`i',`s',等等,产生目标文件名可以使用o选项选择其他名字–GCC忽略c选项后面任何无法识别的输入文件(他们不需要编译或汇编)–gcc–chellocgcc选项()zS–对于每个输入的非汇编语言文件,输出文件是汇编语言文件缺省情况下,GCC通过用`s'替换源文件名后缀`c',`i',等等,产生目标文件名可以使用o选项选择其他名字GCC忽略任何不需要编译的输入文件–相当于编译源码,只生汇编代码–gcc–Shelloc–ohellosgcc选项()zE–生成预处理后的文件默认后缀为i–gcc–Ehelloc–ohelloizv–显示编译器驱动程序,预处理器,编译器的版本号–gccvgcc选项()zofile–指定输出文件为file该选项不在乎GCC产生什么输出,无论是可执行文件,目标文件,汇编文件还是预处理后的C代码–由编译阶段决定,输入的格式•gccEhellocohelloi•gccchelloiohelloo•gcchelloc–ohello–只能输出一个文件关于宏(macro)的选项zDmacro–定义宏macro,宏的内容定义为字符串`'–gcctestmc–DDEBUG–otestmzDmacro=defn–定义宏macro的内容为defn命令行上所有的`D'选项在`U'选项之前处理–gcctestmc–DDBGNAME=hello–otestmzUmacro–取消宏macro`U'选项在所有的`D'选项之后处理,但是优先于任何`include'gcc警告提示功能()zWall–打开所有编译警告–gccWallillcodecoillcodezWerror–视警告为错误出现任何警告即放弃编译–gccWallWerrorillcodecoillcodezw–禁止输出警告信息调试分析选项zg–产生调试信息–GDB能够使用这些调试信息,是进行gdb调试必备条件–和大多数C编译器不同,GNUCC允许结合使用`g‘和`O’选项,但一般不建议一起使用–gcchellocgohelloz所有调试选项会使用最终输出文件尺寸急剧增加,在最后发布,需要使用strip命令把调试信息去掉,–striphelloSeptNeusoftConfidential使用第三方库z在Linux下开发软件时完全不使用第三方函数库的情况是比较少见的通常来讲都需要借助一个或多个函数库的支持才能够完成相应的功能。z从程序员的角度看函数库实际上就是一些头文件(h)和库文件(so或者a)的集合。虽然Linux下的大多数函数都默认将头文件放到usrinclude目录下而库文件则放到usrlib目录下但并不是所有的情况都是这样。正因如此GCC在编译时必须有自己的办法来查找所需要的头文件和库文件。zGCC采用搜索目录的办法来查找所需要的文件I选项可以向GCC的头文件搜索路径中添加新的目录。例如如果在homehxyupgradeinclude目录下有编译时所需要的头文件为了让GCC能够顺利地找到它们就可以使用I选项:–gccfoocIhomexiaowpincludeofooz在一个gcc命令中可以用多个I两大类库形式zCC可以使用两种库一种是静态库,另外一种是动态库–静态库在链接时会把库目标代码与最终的可执行程序一起链接到一个文件,这样相对尺寸较大但处理简单–而动态库是可执行程序在运行,动态加载到进程内存中去动态库与可执行程序是分离的两部分文件–两者在作用是完全等效,主要是使用方法不同由开发者根据项目情况自行评估使用哪种形式zWindows下的静态库是以lib为后缀名的文件,而动态库是以DLL为后缀名的文件zLinux下的动态链接库是so为后缀,和静态链接库以a为后缀名Linux的库的命名zlinux库的命名有一个特殊的要求,即要以lib打头,以so或a结尾–libcso#标准C库,动态链接库–libpthreada#线程库,的静态链接库版本–在一般使用时,为防止不同版本库互相覆盖,一般还在系统库名后加入版本号•libmso#math库ver版本•Libcso#标准Cver动态库•但为方便gcc使用,通常都对这一些带版本名的库作一个符号链接,链接名则是标准形式,如libcso–linux一般把系统库放在lib下–这是大部分库命名的习惯,也可以不遵守,如果强行做一个叫mystda的库,但使用起来很不方便,如不能使用l参数等,所以建议不要这样做gcc链接库zgcc是在链接时,把库加入可以程序中z一个特殊静态链接库方式把库完整名字加入–gccohellohelloolibmya•链接helloo,和库libmya到某一个程序hello中–gccohellohelloolibmyso•链接helloo,和库libmyso到某一个程序hello中,注意这里没有直接把libmyso代码加入hello中–这一方法主要用于链接不标准库名称,或混和链接(即一部分库用于静态版本,一部分库用动态版本)但不是正规用法,强烈建议不要使用这一方法gccl参数的使用zgccl参数用来链接库标准表达式方式zl接的库名,是去掉lib和后缀名(so,a)剩下的部分,–gccfooclpthreadofoo•构造foo,链接库pthreadlpthread表示链接libpthreadsoz去掉后缀名,gcc–l是如何知道链接是动态库还是静态库的,gcc有如下规则:–如果gcc所能找到库目录同时有两种版本,优先链接动态链接库版本–如果gcc所能找到库目录只有静态版本,则采用静态版本–如果加上static参数,gcc则强制链接静态版本•gccfoocstaticlpthreadofoo–lpthread表示链接libpthreada一个使用线程库的例子testthreadcgccL参数的使用zgcc所编译的目标文件和库通常不是在同一个目录下因此必须强制指明gcc要从哪一个目录加载库zgcc在链接时采用L参数来指明从哪一个目录加载库–例如如果在homehxylib目录下有链接时所需要的库文件libfooso•gccfoocLhomehxyliblfooofoo–一个gcc语句可以包含多个L参数–在编译时目标文件时使用L无效–标准库,gcc能自行找到,无需使用L参数z在一些应用中,链接多个库是有顺序的,大部分无所谓–如在系统中libaa使用libpthreada中的函数,而可执行程序同时使用两个库,则使用者libaa的链接语句放在被使用者libpthreada的前面,•gccfoocLhomehxylib–lalpthreadofoogccI参数的使用z库的头文件通常也跟源文件不在同一个目录之下,为了让gcc找到头文件,可以用I<头文件目录>来加入头目录–gcc是在编译时使用I,在链接时无效这跟L参数刚好相反–一个gcc语句中可以使用多个ISeptNeusoftConfidential关于库的演示代码z在随后的演示中,将采用如下演示代码–Strlenc,Strnlenc分别实现了两个自定义示字符串长度函数–这两个函数的声明在Stringh中–mainc分别用静态链接,隐式动态链接来测试使用了Strlenc,Strnlenc的函数,并使用–maindlc用显示动态链接来调用库代码z在随后的例子里把Strlenc,Strnlenc分别编译成静态库libstra,隐式动态库libstrso,显示动态库libstrdlso,z库名中最好不用出现大写字母,gcc是按小写字母来查找的MaincMaindlcStringhStrlencStrnlenc关于静态链接库z在LINUX下静态函数库是以a作后缀的,类似于Windows的libz在链接后,静态库的函数都会链接到最终的可执行程序里这样可执行程序的尺寸比动态链接要大z静态链接的好处是不需要外部文件的支持,独立运行在嵌入式环境下,如果尺寸影响不大,最好用静态编译创建静态链接库zgcc不能直接创建静态库必须要用归档命令ar来创建zar用于建立、修改、提取档案文件(archive)。archive是一个包含多个被包含文件的单一文件(也称之为库文件)其结构保证了可以从中检索并得到原始的被包含文件(称之为archive中的member)。zar可以把任何文件归在一起,但通常是用来把gcc编译的目标文件(o),合在一个静态库中z静态库创建–$gccWallcfilecfilecfilec#一次性编译三个o–$arrvlibNAMEafileofileofileo#把三个o合在一起ar参数z{dmpqrtx}中的操作选项在命令中只能并且必须使用其中一个。但实际最多参数只有r:在库中插入模块(替换)。当插入的模块名已经在库中存在则替换同名的模块。默认的情况下新的成员增加在库的结尾处也可以使用其他选项来改变增加的位置。–#arrvReplaceverbose–#arrcvReplaceCreateverbose创建一个静态库的脚本gcccStrlencgcccStrnlencarrvlibstraStrlenoStrnlenogcccmaincIgccmainoLlstromaina#标准用法Buildash#把两个目标文件装入静态库libstra中#链接maina时,一并链接libstra#gccmainolibmyaomaina#非标准用法,用全名动态链接库的创建z动态链接库的创建分为两步:–编译目标文件,必须带上fpic标志,使输出的对象模块是按照可重定位地址方式生成的。•gcccStrlencfpic•gcccStrnlencfpic–将加入动态库的目标文件合并在一起,必须带上shared,明确表示是动态链接库•gccsharedStrlenoStrnlenoolibstrsoz两步可以合并成一步,但一般不建议这样做–gccfpicsharedStrlencStrnlencolibstrsozso是SharedObject的缩写动态链接库的创建#gccfpicsharedStrlencStrnlencolibstrsogcccfpicStrlencgcccfpicStrnlencgccsharedStrlenoStrnlenoolibstrsogcccmaincI#gccmainolibstrsoomainso#非标准链接方式gccmainoLlstromainso#生成动态链接库#编译测试程序#链接主程序和动态库运行中使用动态链接库z一个使用动态链接库的程序运行时,要做一下设置否则应用程序会报找不到动态库的错误z隐式调用和显式调用两种调用方法:–隐式调用是不采用特殊系统调用,只是在gcc链接时采用l,L链接。这样对代码影响不大。–显式调用是在代码中加入一些特殊代码,表示要调用哪个动态库程序。具有灵活的特点,缺点就是必须使用特定的,不可移植的系统调用来编写。过程比较复杂。z一个程序运行后,可以用命令ldd来检查它使用了哪一些动态库–lddhello隐式调用动态方法z如果让程序运行时能找动态链接库,Linux有如下几种方法–把库所在路径加入etcldsoconf,程序加载时首先到这里路径查找–设置环境变量LDLIBRARYPATH,把库所在路径加入这个变量中,这是最常用的方法•演示代码将采用这一方法运行,写一个脚本runsosh#!binshexportLDLIBRARYPATH=$PWD:$LDLIBRARYPATHmainsolddmainso#用ldd查看用了哪些动态库隐式动态库的执行结果RunsoshSeptNeusoftConfidentialGcc代码优化()z代码优化指的是编译器通过分析源代码找出其中尚未达到最优的部分然后对其重新进行组合目的是改善程序的执行性能。GCC提供的代码优化功能非常强大它通过编译选项On来控制优化代码的生成其中n是一个代表优化级别的整数。对于不同版本的GCC来讲n的取值范围及其对应的优化效果可能并不完全相同比较典型的范围是从变化到或。z编译时使用选项O可以告诉GCC同时减小代码的长度和执行时间其效果等价于O。通常来说数字越大优化的等级越高同时也就意味着程序的运行速度越快。许多Linux程序员都喜欢使用O选项因为它在优化长度、编译时间和代码大小之间取得了一个比较理想的平衡点。Gcc代码优化()z不带优化–gccWalloptimizecooptimizez做了优化–gccWallOoptimizecooptimizeztime–借助Linux提供的time命令可以大致统计出该程序在运行时所需要的时间,比较两次时间–#timeoptimize代码优化实例z一个做了大量浮点数除法的程序#include<stdioh>intmain(void){doublecounterdoubleresultdoubletempfor(counter=counter<**counter=()){temp=counterresult=counter}printf("Resultislfn",result)return}Optimizec代码优化的结果比较Gcc代码优化()zOOzO–多优化一些除了涉及空间和速度交换的优化选项,执行几乎所有的优化工作和O选项比较,这个选项既增加了编译时间,也提高了生成代码的运行效果zO–优化的更多zO不优化z如果指定了多个O选项,不管带不带数字,最后一个选项才是生效的选项Gcc代码优化()z避免优化代码场合:–程序开发的时候优化等级越高消耗在编译上的时间就越长因此在开发的时候最好不要使用优化选项只有到软件发行或开发结束的时候才考虑对最终生成的代码进行优化。–资源受限的时候一些优化选项会增加可执行代码的体积如果程序在运行时能够申请到的内存资源非常紧张(如一些实时嵌入式设备)那就不要对代码进行优化因为由这带来的负面影响可能会产生非常严重的后果。–跟踪调试的时候在对代码进行优化的时候某些代码可能会被删除或改写或者为了取得更佳的性能而进行重组从而使跟踪和调试变得异常困难。常见错误或警告zdllisth:::warning:nonewlineatendoffile–这个通常是由于源码里最后一行不是UNIX文本字符要求的空行,造成,这不影响最终编译结果,如果想去掉,直接在源码中加入一个空行即可ztestlinko(textx):Infunction`test'::undefinedreferenceto`dlsavetofile‘–表示在最终链接时,没有找到dlsavetofile这个函数的目标代码,原因有多种,如没有把这个源码包含进来,系统函数的笔误找不到对应链接库zmainc:::Stringh:Nosuchfileordirectory–某个头文件找不到,很大可能性是没有用I参数把Stringh所有在目录加入进来zmain:errorwhileloadingsharedlibraries:libstrso:cannotopensharedobjectfile:Nosuchfileordirectory–应用程序找不到自己链接的动态库libstrso,需要把libstrso加入到环境变量LDLIBRARYPATH中课堂作业•请开发一个程序,使用结构定义structstudent{intno*学号*charname*名称*floatheight*身高*}–要求创建个学生定义,并给三个学生的三个成员都赋上值,–用一个printf把一个学生的三个值打印出来,依次把所有学生信息显示–要求用vi编辑,并用gcc在Linux下编译,测试通过课堂练习•开发一个库函数,要求能对字符串的进行转大写转换•要求把库函数,编译成静态和动态链接库各一个,取名libtua,libtuso•编写一个测试程序,要求能测试libtu测试库函数谢谢!Copyright版权所有东软集团Linux应用程序开发环境课程体系课程结构第四章:GCC编译器gnugcc简介gcc支持的文件格式GCC组成gcc的起步可执行程序的构造gcc在构建程序的作用为什么要用gcchello编译过程分析gcc各个编译步骤多文件gcc的处理用gcc构造程序()用gcc构造程序()编译testlink实例用gcc构造程序()gcc构造复杂程序gcc完整使用格式gcc选项()gcc选项()gcc选项()gcc选项()gcc选项()关于宏(macro)的选项gcc警告提示功能()调试分析选项使用第三方库两大类库形式Linux的库的命名gcc链接库gccl参数的使用一个使用线程库的例子gccL参数的使用gccI参数的使用关于库的演示代码关于静态链接库创建静态链接库ar参数创建一个静态库的脚本动态链接库的创建动态链接库的创建运行中使用动态链接库隐式调用动态方法隐式动态库的执行结果Gcc代码优化()Gcc代码优化()代码优化实例代码优化的结果比较Gcc代码优化()Gcc代码优化()常见错误或警告课堂作业课堂练习Copyright版权所有东软集团

用户评论(0)

0/200

精彩专题

上传我的资料

每篇奖励 +2积分

资料评价:

/12
仅支持在线阅读

意见
反馈

立即扫码关注

爱问共享资料微信公众号

返回
顶部