GCC 和 Clang 编译器浅谈
GCC 是 Linux 上使用的编译器, Clang 是 Mac 上使用的编译器, 两者命令格式基本相同, 这里笔者对编译器做一个浅谈 (笔者使用的是 MacBook, 所以代码以 MacBook 上的命令为例).
首先写一个编译的语句:
gcc/clang -g -O2 -o test test.c -I... -L... -l
这是一条对 test.c 进行编译最终的到可执行文件的语句, 下面逐个解释一下语句中各个命令的用法.
-g: 输出文件中的调试信息. 我们的程序在执行中如果出现问题, 我们就可以用调试器对其进行调试.
-O2: 对输出的文件做指令优化. 对应默认的 O1, 我们在不写的情况下默认是 O1, 这样我们在调试的时候, 每一步的临时变量是可以显示出来的. 但是, 如果设置成了 O2, 那么就不会显示出来. 一般 O2 应用在上线版本, 可以让编译器自己选择优化掉一些不必要的信息, 这样能更快速的执行程序; 而 O1 一般用于未上线的代码, 让我们可以进行调试.
-o: 输出文件. 后面接要编译成的文件名和被编译的文件名.
-I: 指定头文件位置. 在使用第三方库或者我们写的头文件时, 就要告诉编译器头文件的目录.
-L: 指定库文件位置.
-l: 指定使用哪个库. 比 - L 更具体.-L 好比给了一堆库,-l 指定用哪个.
编译过程
预编译: 将头文件和源代码联系在一起, 并未编译, 只是为编译做准备.
编译: 将代码编译成. o 文件. 不是可执行文件, 只是一个中间文件, 还需要进行链接.
链接 (动态链接 / 静态链接): 与系统或者第三方库进行链接.
静态链接: 将所有的库链接在一起, 形成一个特别大的文件.
动态链接: 在代码执行过程中进行链接.
举个例子: 我们将自己写的一个. c 程序编程一个库文件, 然后在 main 函数中调用这个库文件 (比较类似于 java 中调用另一个类的方法, 只不过 C 语言中没有类的概念, 并且调用方式比 java 复杂一些).
具体步骤:
1. 将我们自己的. c 文件编译成. o 中间文件,
2. 将. o 文件编译成一个库文件.
3. 在 main 函数中调用这个库文件.
1. add.c 代码
- #ifndef __MYLIBRARY__
- #define __MYLIBRARY__
- int add(int a, int b){
- return a+b;
- }
- #endif //__MY_LIBRARY__
add.h 代码
- #ifndef __MY_LIBRARY__
- #define __MY_LIBRARY__
- int add(int a, int b)
- #endif
然后我们在控制台执行 "clang -g -c add.c" 得到 add.o 中间文件.
2. 使用语句 "libtool -static -o libmylib.a add.o" 将 add.o 编译成 mylib.a 库文件.
-static: 意思是编译成一个静态库
libmylib: 这里需要注意的一点是 "mylib" 其实是我们的名字, 但是根据规则, 在我们起的名字前面必须加上一个 "lib" 作为前缀.
3. 我们写一个带 main 函数的代码 test.c 调用这个 mylib 库
- #include <stdio.h>
- #include "add.h"
- int main(int argc, char* argv[]){
- printf("add = %d\n", add(3, 3));
- return 0;
- }
然后在控制台使用我们最上面的语句编译这段代码:
clang -g -o test test.c -I . -L . -lmylib
"." 代表当前目录
最后在控制台调用 "./test" 就可以得到输出的结果.
来源: http://www.jianshu.com/p/3f1e9a36785a