gcc介绍及编译过程

一、GCC介绍

GCC 原来代表“GNU C Compiler”的意思。自从面世后,GCC 逐渐扩充、发展,现在不仅仅支持C语言,还支持其他很多语言,包括 C++、Ada、Objective-C、Fortran 和 Java 等。因此,GCC 的意思被重新定义为“GNU Compiler Collection”,也即“GUN 编译器套件”。但是只有接触到linux平台下的开发,才能真正了解gcc的编译流程。

常见的GCC命令

选项

解释

-E

仅作预处理,不进行编译、汇编和链接。

-S

仅编译到汇编语言,不进行汇编和链接

-c

编译并汇编生成机器语言代码。

-I(大写的i)

指定额外的头文件搜索路径DIRECTORY。

-L

指定库文件所在的路径。

-l(小写的L)

需要链接的库名称。即链接库文件去掉lib前缀和.so后的部分。

-o

生成指定的输出文件。

-Wall

生成所有警告信息。

-Werror

不区分警告和错误,遇到任何警告都停止编译

-w

不生成任何警告信息。

-static

静态链接,不使用动态链接

-shared

生成共享目标文件。通常用在建立共享库时。

-g

编译生成可执行文件包含gdb调试信息,可被gdb调试

gcc使用到的一些软件和工具

ar

这是一个程序,可通过从文档中增加、删除和析取文件来维护库文件。通常使用该工具是为了创建和管理连接程序使用的目标库文档。生成静态库时使用

gdb

GNU 调试器,可用于检查程序运行时的值和行为

make

它会读 makefile 脚本来确定程序中的哪个部分需要编泽和连接

gcc常见的文件后缀名:

.c文件是c程序文件

.i文件已经过预处理(gcc -E)的C程序

.s文件是编译(gcc -S)处理后的汇编程序

.S文件是预处理加编译处理后的汇编程序

.h文件是头文件

.o文件是汇编(gcc -c)处理生成的目标文件,需要链接之后才能生成可执行文件

.a/.so文件是编译后的库文件

二、GCC编译流程

可分为以下几个大的部分

1.预处理(Preprocessing)

2.编译(Compilation)

3.汇编(Assembly)

4.链接(Linking)

1.预处理

预处理对其中的伪指令(以#开头头文件或宏定义)和特殊符号进行“替代”处理;经过此处理,生成一个没有(define)宏定义、没有条件编译(ifdef)指令、添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号、没有注释的输出文件。

2.编译

在这个阶段中,Gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,Gcc把代码翻译成汇编语言。

3.汇编

汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。把编译阶段生成的.s汇编文件转成.o目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。

4.链接

汇编程序生成的目标文件需要链接之后才能生成可执行文件。因为程序中可能调用了某个库文件中的函数,需要将相关的库链接进来才可以。

链接可分为两种:

1.静态链接

2.动态链接

静态链接是在编译时将所有的函数都编译进了程序,而动态链接是在程序运行时由操作系统帮忙把动态库调入到内存空间中使用。所以使用静态链接生成可执行程序之后,删掉静态库也没关系,程序还能运行,但是使用动态链接生成可执行程序的话,删除掉动态库,程序就不能被执行了。如果动态库和静态库同时存在时,链接器优先使用动态库。

 

静态链接

静态库的生成需要用到刚才提到过的ar工具

ar命令可以用来创建、修改库,也可以从库中提出单个模块

-c 选项表示 创建一个库。不管库是否存在,都将创建

-r 选项表示 将模块插入库,如果库中有对应的模块,那么进行更新

如果把多个.o文件插入库.a里,只需要在后面用空格分开写出来

格式:

ar -cr 静态库libname.a  name1.o name2.o

生成静态库需要.o目标文件:

gcc -c(编译并汇编) 你需要生成静态库的.c文件 -o(输出的目标文件) .o文件

生成静态库的.c文件通常是没有main函数的c程序只是提供函数实现某项功能。

使用静态库:

gcc main.c -o myapp -L lib_path  -static -lname

 

动态链接

动态库需要使用-shared 选项以及-fPIC选项

格式:

gcc -shared -fPIC -o libname.so file1.c file2.c ... fileN.c

-fPIC表示代码是和地址无关的,不需要被不同模块重定位

使用动态库:

gcc main.c -o myapp -L libpath -lname

编译过程中如果提示找不到相对应的头文件则需要加-I(大写的i)选项后面加对应头文件的路径

编译成功后执行文件可能会提示说没有加载到库,这是因为生成的库不在系统路径下

1. 将所需要的.a/.so库文件拷贝到/usr/lib路径下,当然这需要root权限;

2. 使用export命令在LD_LIBRARY_PATH环境变量中添加该动态库所在的路径,注意该命令只是临时生效,重启后失效。另外指定的路径必须是绝对路径;例如你生成的库在当前目录:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd` (~键对应的`)

gcc使用静态库链接时搜索路径顺序

1. ld会去找GCC命令中的参数-L

2. 再找gcc的环境变量LIBRARY_PATH

3. 再找内定目录 /lib /usr/lib /usr/local/lib

使用动态链接时、执行时搜索路径顺序:

1. 编译目标代码时指定的动态库搜索路径-L

2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径

3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径

4. 默认的动态库搜索路径/lib

5. 默认的动态库搜索路径/usr/lib

有关环境变量:

LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径

LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径

猜你喜欢

转载自blog.csdn.net/caijiwyj/article/details/88806916