一、gcc编译过程
- 预处理 (引入库,以及对程序进行预处理,即#include,#define等转换)
gcc -E -o main.i main.c
- 编译 (将c语言转换成汇编语言)
gcc -S -o main.s main.i
- 汇编(将汇编语言转换成机器语言)
gcc -c -o main.o main.s
- 链接 (将机器语言转换成可执行文件)
gcc -o main main.c
- 执行方式
./main
二、预处理的使用
#include 包含头文件
#define 宏 宏体 (不进行语法检查)
#include <stdio.h>
#define ABC 5+3
#define ABCD(x) 5+x //宏函数
int main()
{
printf("%d\n",ABC*5); //会被替换成5+3*5 输出为20
printf("%d\n",ABCD(3));//输出为8
return 0;
}
故我们需要在宏定义时,最好有出现运算的,加上(),避免歧义
三、预定义宏的作用
预定义宏(系统定义宏,系统已经定义好了)
__FUNCTION__:函数名
__LINE__ :行号
__FILE__ :文件名
可以通过以下代码进行调试代码:
printf("the %s,%s,%d\n",__FUNCTION__,__FILE__,__LINE__);
其输出为:该行代码所在的函数,以及文件名,以及文件内所在的行数
四、条件预处理的使用
#ifdef Log
需要打印的调试信息
#endif
如果需要打开调试信息,就在文件最前面增加一句 #define Log
如果不想修改到源文件,即不想添加这个#define Log,可以通过gcc编译的修改
gcc -DLog -o main main.c
这里的 -DLog 等同于在文件开头添加了 #define Log
五、#include < >和include " "的区别
- #include <>
会去系统文件的地方找 - #include “”
可以通过自定的目录来找,如"./study/Log.h"
当如果我们要通过#include <Log.h>来,我们就得临时添加系统文件里面的目录
即可以通过 -I 来寻找
即 当我们在main.c 里面有#include <Log.h>
gcc -c -o main.o main.c -I ./
以上的命令会让编译的时候会先去我们临时添加的系统文件目录./找Log.h
六、编译汇编链接的问题
静态库
-
生成汇编文件
gcc -c -o Log.o Log.c
gcc -c -o main.o main.c
-
生成静态库
ar crs libLog.a Log.o
-
链接静态库
gcc -o build_static main.o libLog.a
动态库
- 生成动态库
gcc -shared -o libLog.so Log.o
- 链接动态库
gcc -o build_dynamical main.o libLog.so
gcc -o build_dynamical main.o -lLog
(可能会出现找不到动态库文件路径)
// 链接库文件是-l,链接库文件的目录是-L - 在当前目录下查找动态库
gcc -o build_dynamical main.o -L ./ -lLog
(解决找不到动态库文件的问题)
七、运行可执行文件的问题
当我们需要需要运行可执行文件时,链接 静态库的可执行文件可以直接执行,
但是链接 动态库的可执行文件 却会因为找不到动态库文件,而 执行不了 。
链接和运行是完全不同的。
解决的第一个方法
可以将libLog.so文件,即将动态库文件放在板子或者pc里的/lib目录或者/usr/lib目录这类共享库
sudo mv ./libLog.so /lib
解决的第二个方法
LD_LIBRARY_PATH 是Linux系统下的 环境变量名,类似于windows里的环境变量PATH
故我们可以将存放了自己的动态库放在我们建立的目录里面,
然后将该目录添加在 LD_LIBRARY_PATH(环境变量) 里
-
临时修改(重启后失效)
格式为export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:加上自己自定义的动态库目录
eg:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/study/002
生效需要重新打开新的终端,从而使配置生效 -
永久修改
可以在 ~/.bashrc 文件里面加入以上语句,那样每次开机都会自动执行一次该命令