【精选】gcc编译流程、参数实例详细(总结)

您所在的位置:网站首页 gcc编译器工作流程 【精选】gcc编译流程、参数实例详细(总结)

【精选】gcc编译流程、参数实例详细(总结)

2023-11-17 18:24| 来源: 网络整理| 查看: 265

一、简介

本文主要讲解gcc命令的参数以及动态库和静态库的制作,通过程序的编译过程运行具体的实例进行阐述。

二、编译过程

GCC即GNU Compiler Collection,编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和链接(Linking),gcc可以理解为编译管理工具,它会具体调用相关的工具进行执行,具体如下图: 在这里插入图片描述

2.1预处理

[root@localhost /]# gcc -E test.c -o test.i 或 gcc -E test.c

可以输出到test.i文件中存放着test.c经预处理之后的代码。打开test.i文件,看一看,就明白了。后面那条指令,是直接在命令行窗口中输出预处理后的代码. gcc的-E选项,可以让编译器在预处理后停止,并输出预处理结果。在本例中,预处理结果就是将stdio.h 文件中的内容插入到test.c中了。 2.2编译为汇编代码(Compilation) 预处理之后,可直接对生成的test.i文件编译,生成汇编代码:

[root@localhost /]# gcc -S test.i -o test.s

gcc的-S选项,表示在程序编译期间,在生成汇编代码后,停止,-o输出汇编代码文件。 2.3汇编(Assembly) 对于上一小节中生成的汇编代码文件test.s,as汇编器负责将其编译为目标文件,如下:

[root@localhost /]# gcc -c test.s -o test.o

2.4链接(Linking) gcc连接器是gas提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。附加的目标文件包括静态连接库和动态连接库。 对于上一小节中生成的test.o,将其与C标准输入输出库进行连接,最终生成程序test

[root@localhost /]# gcc test.o -o test gcc参数详解 编译参数详细说明-o指定编译的⽬标,否则会⽣成的⽬标⽂件名是a.out; gcc main.c -o main-S把源文件编译成汇编代码-E只执行预处理-include包含头文件,功能如同在源码的语句#include -I(大写i)指定程序包含头文件的路径,一般用于指定第三方库的头文件。-L编译时,用于指定程序第三方库的查找路径。-l链接时,指定程序需要进行链接的库。注:一般库文件名是libxxx.so,-I指定xxx即可。如-Ixxx-rpath程序执⾏需要指定动态库的路径,但是可以⽤-rpath参数在编译时指定程序运⾏时需要加载的库的路径。-D程序编译阶段可以定义一些宏,该方法可以让程序有选择性的运行代码。-0n这是程序的优化等级。n的范围是0-3。n越大优化等级越高,程序运行的越快。否则越慢,n==0时是关闭优化。利于程序的调试,一般程序调试阶段会关闭优化等级,发布程序会把优化等级设为-O2。-O0:不进行优化处理。-O 或 -O1:优化生成代码。-O2:进一步优化。-O3 比 -O2 更进一步优化,包括 inline 函数。-g打印程序的调试信息,如果需要使⽤gdb⼯具进⾏调试程序,程序编译的时候,需要加上该参数。-share编译的时候尽量使用动态库。(除非只有静态库,没有动态库)-static禁止使用动态库,编译的时候只加载静态库,这会导致执行件很大。-w不生成任何的警告信息。-Wall生成所有的警告信息。-fpic使输出的对象模块可重定位地址方式行成的。-shared把对应的源文件形成对应的动态链接库。 四、实例讲解

动态库和静态库 静态库 当程序与静态库连接时,库中目标文件所含的所有将被程序使用的函数的机器码被copy到最终的可执行文件中。这就会导致最终生成的可执行代码量相对变多,相当于编译器将代码补充完整了,优点是这样运行起来相对就快些。 不过会有个缺点:占用磁盘和内存空间。静态库会被添加到和它连接的每个程序中,而且这些程序运行时,都会被加载到内存中。无形中又多消耗了更多的内存空间。 动态库 与共享库连接的可执行文件只包含它需要的函数的引用表,而不是所有的函数代码,只有在程序执行时, 那些需要的函数代码才被拷贝到内存中。

**优点:**这样就使可执行文件比较小,节省磁盘空间,更进一步,操作系统使用虚拟内存,使得一份共享库驻留在内存中被多个程序使用,也同时节约了内存。 **缺点:不过由于运行时要去链接库会花费一定的时间,执行速度相对会慢一些,总的来说静态库是牺牲了空间效率,换取了时间效率,共享库是牺牲了时间效率换取了空间效率,没有好与坏的区别,只看具体需要了。 另外,一个程序编好后,有时需要做一些修改和优化,如果我们要修改的刚好是库函数的话,在接口不变的前提下,使用共享库的程序只需要将共享库重新编译就可以了,而使用静态库的程序则需要将静态库重新编译好后,将程序再重新编译一遍。这也是使用过程当中的差别,以现在的项目举例,在远程更新的时候,如果只是.so动态库封装内容变化了,那么只需要更新.so即可。 动态库生成:

#同静态库一样编译成目标文件: [root@localhost /]# gcc –c a.c b.c #生成共享库: [root@localhost /]# gcc –fPIC –shared –o libshared.so a.o b.o

静态库的生成:

#在程序编译时,会全部代码加载到可执行程序中。 [root@localhost /]# ar rcs libstatic.a fun.o

静态库的链接方法:

[root@localhost /]# gcc –o staticcode –L. –lstatic main.c –static(默认库在当前文件夹)

动态库的链接方法:

[root@localhost /]# gcc –o sharedcode -L. –lshared main.c(默认库在当前文件夹)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3