编译
代码的编译过程
- 编译:把c语言翻译成0和1,工具是clang编译器 指令 cc -c 文件名.c ,编译成功生成.o文件
- 链接: 把我们的.o文件跟系统自带的函数库合并在一起,生成一个可执行文件.out
- 运行: ./a.out
编译过程可以分为四个步骤:预处理、编译、汇编、链接。
markdown
预处理:处理所有以#开头的代码,包括头文件、宏定义、条件编译
gcc -E hello.c -o hello.i
编译:语法检查以及将C语言编程汇编语言
gcc -S hello.i -o hello.s
汇编:将汇编语言变成二进制文件
gcc -c hello.s -o hello.o
链接:链接代码需要用到的其他文件(库文件等)
gcc hello.o -o hello1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
例如下面的这段代码,在预处理阶段
c
#import <stdio.h> //
int main(){
printf("main");
return 0;
}1
2
3
4
5
6
2
3
4
5
6
gcc的常见操作
| 指令 | 含义 |
|---|---|
| -c | 只是编译不链接,生成目标文件.0 |
| -S | 只是编译不汇编,生成汇编代码 |
| -E | 只进行预编译,不做其他处理 |
| -g | 在可执行程序中包含标准调试信息 |
| -o file | 把输出文件输出到file中 |
| -v | 打印编译器内部编译各过程的命令行信息和编译器的版本 |
| -l dir | 在头文件的搜索路径列表中添加dir目录 |
| -L dir | 在库文件的搜索路径列表中添加dir目录 |
| -static | 链接静态库,MAC电脑使用ar -r libperson.a person.o |
| -l library | 连接名为library的库文件 |
编译静态库
编译静态库分为两步
markdown
gcc -c xxx.c xxx.c
ar -crv libxx.a xxx.o xxx.o1
2
2
比如下面两个文件,f1.c和f2.c,hellow.c文件中引用它们的两个方法。 下面我们将f1、f2编译成静态库和动态库
c
// f1.c
#include <stdio.h>
void f1()
{
printf("this is f1 ...\n");
}
// f2.c
#include <stdio.h>
void f2()
{
printf("this is f2 ...\n");
}
// hello.c
#import <stdio.h>
void f1();
void f2();
int main(){
f1();
f2();
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- 通过
gcc -c f1.c f2.c编译成.o文件 - 通过
ar -r libxx.a f1.o f2.o将.o文件打包成静态库,静态库以lib开头,xx是静态库的名字 - 通过
gcc hello.c -o hello -L . -l xx, 大写的-L后是静态库路径,小写的-l是静态库名字
编译动态库
编译静态库分为两步
gcc -fPIC -shared -o libxxx.so xxx.c xxx.c
gcc hello.c -o hello -L . -l xxx1
2
2
拿上面的f1/f2/hello.c举例:
- 通过
gcc -fPIC -shared -o libxxx.so f1.c f2.c,生成动态库,xxx是动态库的名字,MAC中动态库的后缀是dyld - 通过
gcc hello.c -o hello -L . -l xxx链接到动态库,生成可执行文件
查看可执行文件链接的库
在某些编译的时候,会报找不到库文件的错误,我们可以通过查看可执行链接的库位置信息确定是否正确的包含了库文件。MAC电脑使用otool -L xxx进行查看,在Window中使用ldd xxx进行查看