gcc编译流程解析

gcc编译流程解析

[TOC]

1、预处理

1
2
3
4
5
6
#include<stdio.h>
int main()
{

printf("Hello! This is our embedded world!\n");
return 0;
}

在该阶段,对包含的头文件(#include)和宏定义(#define#ifdef等)进行处理。

可以通过gcc -E选项进行查看。该选项的作用是让gcc 在预处理结束后停止编译过程。

gcc -E hello.c -o hello.i

-o是指目标文件。 .i文件为经预处理后的C程序。

2、编译阶段

gcc -S hello.i -o hello.s
上述命令只进行编译不进行汇编,结果生成汇编代码。

在编译阶段,gcc首先要检查代码的规范性、是否有语法错误。

3、汇编阶段

汇编阶段把编译阶段生成的.s文件转成目标文件。

gcc -c hello.s -o hello.o

把汇编代码转为二进制目标代码。

4、链接阶段

链接时gcc会到系统默认的搜索路径/usr/lib下进行查找动态库。

函数库用动态库和静态库两种。

静态库是指编译链接时,将库文件的代码全部加入到可执行文件中。生成文件比较大。在运行时也就不再需要库文件了。后缀名通常为.a

动态库与之相反,在编译链接时并没有将库文件的代码加入可执行文件中,而是在程序执行时加载库。这样可以减轻系统的开销。一般动态库的后缀名为.so .

gcc编译时默认使用动态库。

完成了链接之后,gcc就可以生成可执行文件。

gcc hello.o -o hello

./hello

gcc编译选项分析

gcc 常用选项列表

选 项 含 义
-c 只编译不链接,生成目标文件“ .o
-S 只编译不汇编,生成汇编代码
-E 只进行预编译,不做其他处理
-g 在可执行程序中包含标准调试信息
-o file 将 file 文件指定为输出文件
-v 打印出编译器内部编译各过程的命令行信息和编译器的版本
-I dir 在头文件的搜索路径列表中添加 dir 目录

-I dir选项可以在头问价的搜索路径列表中添加dir目录。

Linux中默认头文件都放到了“/usr/include/”目录下。因此如果用户希望添加放置在其他位置的头文件时,就可以通过“-I dir”选项来指定。

gcc hello.c -I /home/rayu/cstudy/ -o hello

### gcc 库选项列表

选 项 含 义
-static 进行静态编译,即链接静态库,禁止使用动态库
-shared 1.可以生成动态库文件
2.进行动态编译,尽可能地链接动态库,只有当没有动态库时才会链接同名的静态库(默认选项,即可省略)
-L dir 在库文件的搜索路径列表中添加 dir 目录-lname链接称为 libname.a(静态库)或者 libname.so(动态库)的库文件。若两个库都存在,则根据编译方式( -static 还是-shared)而进行链接
-fPIC(或-fpic) 生成使用相对地址的位置无关的目标代码( Position Independent Code)。然后通常使用gcc 的-static 选项从该 PIC 目标文件生成动态库文件

静态库的创建和使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* unsgn_pow.c:库程序 */
unsigned long long unsgn_pow(unsigned int x, unsigned int y)
{

unsigned long long res = 1;
if (y == 0)
{
res = 1;
}
else if (y == 1)
{
res = x;
}
else
{
res = x * unsgn_pow(x, y - 1);
}
return res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<stdio.h>
#include<stdlib.h>

int main(int argc,char *argv[])
{

unsigned int x,y;
unsigned long long res;
if((argc<3) || (sscanf(argv[1],"%u",&x)!=1) || (sscanf(argv[2],"%u",&y))!=1)
{
printf("Usage: pow base exponent\n");
exit(1);
}
res = unsgn_pow(x,y);
printf("%u ^ %u = %u\n",x,y,res);
exit(0);
}
1
2
3
4
gcc -c unsgn_pow.c
ar rcsv libpow.a unsgn_pow.o
gcc -o pow_test pow_test.c -L. -lpow
./pow_test 2 10

动态库的创建和使用

首先使用 gcc -fPIC选项为动态库构造一个目标文件

gcc -fPIC -Wall -c unsgn_pow.c

接下来,使用-shared选项和已创建的位置无关目标代码,生成一个动态库libpow.so

gcc -shared -o libpow.so unsgn_pow.o

下面编译主程序,它将会链接到刚刚生成的动态库libpow.so

gcc -o pow_test pow_test.c -L. -lpow

在运行可执行程序之前,需要注册动态库的路径名。其方法有几种:修改/etc/ld.so.conf文件,或者修改LD_LIBRARY_PATH环境变量,或者将库文件直接复制到/lib或者/usr/lib目录下(这两个目录为同的默认的库路径名)

1
2
cp libpow.so /lib
./pow_test 2 10

告警和出错选项

gcc 的告警和出错选项。

gcc 警告和出错选项选项列表

选 项 含 义
-ansi 支持符合 ANSI 标准的 C 程序
-pedantic 允许发出 ANSI C 标准所列的全部警告信息
-pedantic -error 允许发出 ANSI C 标准所列的全部错误信息
-w 关闭所有告警
-Wall 允许发出 gcc 提供的所有有用的报警信息
-Werror 把所有的告警信息转化为错误信息,并在告警发生时终止编译过程

gcc –Wall –O -g –c kang.c -o kang.o

-Wall 是打开警告开关,
-O代表默认优化,可选:-O0不优化,-O1低级优化,-O2中级优化,-O3高级优化,-Os代码空间优化。
-g是生成调试信息,生成的可执行文件具有和源代码关联的可调试的信息。

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器