GCC是在linux下使用的编译器,Clang是在mac上使用的编译器,两者的命令几乎一样
本文运行环境为mac
编译指令
gcc/clang -g -O2 -o test test.c -I... -L... -l...
-g 输出文件中的调试信息
-O 大写的O,对输出文件做指令优化,2表示对文件进行第二个级别的编译优化,更彻底,如果调试的话,则不需要-O
-o 输出文件
-I 指定头文件位置,使用第三方库或者自己创建,
-L 指定lib库位置
-l 意为link,指定使用哪个库,不一定所有都用
编译过程
vim main.c
创建一个main函数文件,c程序必须以main函数为入口点
# include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
预处理
gcc -E main.c -o main.i
-E 表示生成预处理文件
具体内容:
- 宏定义指令 #define xxxx
- 条件编译 #if #else #endif…
- 头文件包含指令 #include 将头文件和源代码拷贝到一起
- 特殊符号处理 例如对方法参数中的空格处理
常见问题:
不能在头文件中定义全局变量,因为在头文件中定义全局变量将会使所有包含该头文件的文件存在该段代码,也就是说这些文件将定义一个相同的全局变量,这样将不可避免的造成冲突
首先对源文件进行预处理,这个过程主要是处理一些#号定义的命令或语句(如宏、#include、预编译指令#ifdef等),生成*.i文件。即绑定头文件和宏判定等操作,将头文件和源代码拷贝到一起,以便编译器进行编译
编译
gcc -S main.i -o main.s
-S 让编译程序在生成汇编语言输出
具体内容:
编译环节是指对源代码进行语法分析,并优化产生对应的汇编代码的过程,通过词法分析和语法分析,将其翻译成等价的中间代码或汇编代码。局部优化、控制流分析和循环优化、数据流的分析和全局优化。
进行词法分析、语法分析和语义分析等,生成*.s的汇编文件
汇编
gcc -c main.s -o main.o
-c 表示编译、汇编指定的源文件(也就是编译源文件),但是不进行链接
将对应的汇编指令翻译成机器指令,生成可重定位的二进制目标文件.o
链接
vi add.c 创建一个add方法文件
#ifndef __MY_LIBRARY__
#define __MY_LIBRARY__
int add(int a, int b){
return (a+b);
}
#endif
然后编译,并使用libtool,生成一个静态库包含add.o
gensees-iMac:study gensee$ vi add.c
gensees-iMac:study gensee$ clang -g -c add.c
gensees-iMac:study gensee$ ls add.o
add.o
gensees-iMac:study gensee$ ./add.o
gensees-iMac:study gensee$ libtool -static -o libmylib.a add.o
生成了一个lib文件
Ex : 这里使用ar命令可以查看静态库的组成
gensees-iMac:study gensee$ ar -t /Users/gensee/Desktop/study/libmylib.a
__.SYMDEF SORTED
add.o
ar是linux命令,更多查看 https://www.runoob.com/linux/linux-comm-ar.html
创建一个main函数文件 main.c,并编译为.o
#include <stdio.h>
#include "add.h"
int main()
{
int sum = add(1,5);
printf("%d\n",sum);
return 0;
}
clang -g -c main.c
这里同样我们也需要创建一个add.h头文件以便引用
使用vi add.h
#ifndef __MY_LIBRARY__
#define __MY_LIBRARY__
int add(int a, int b);
#endif
然后我们进行链接
clang -o main main.o -L . -lmylib
gensees-iMac:study gensee$ clang -o main main.o -L . -lmylib
gensees-iMac:study gensee$ ./main
6
gensees-iMac:study gensee$
可以看到最后执行了add方法结果为6
一步执行方法
前提是编译好mylib
clang -g -o main mian.c -I . -L . -lmylib
-I . 表示当前目录头文件
-L . 表示当前目录lib
gensees-iMac:study gensee$ clang -g -o main main.c -I . -L . -lmylib
gensees-iMac:study gensee$ ./main
6
gensees-iMac:study gensee$
链接方式
链接系统的库,三方库,分为动态链接和静态链接
静态链接和动态链接两者最大的区别就在于链接的时机不一样,静态链接是在形成可执行程序前,而动态链接的进行则是在程序执行时。
静态链接:将源文件中用到的库函数与汇编生成的目标文件.o合并生成可执行文。每一个可执行程序对所有需要的目标文件有一份副本,浪费空间,而且更新需要重新编译形成可执行程序。
动态链接:解决了静态链接浪费空间,更新困难的问题,只需要加载一次,存在内存中,每个程序都可以使用。