目录
1.gcc/g++
在我们学习c语言的时候,我们知道要想生成一个可执行程序需要四个步骤:预编译—编译—汇编—链接 Linux实现这些过程就需要借助gcc/g++编译器来实现。
预编译(gcc)
在预编译的过程中编译器会去掉注释内容、检查语法、对#define宏替换,头文件展开、条件编译... 生成一个.i的文件 在Linux中对应的命令:gcc -E test.c -o test.i 其中-E选项是让其停在预编译阶段。-o 是指定生成文件的名字。(此时还是C语言形式存在)。
编译
在编译阶段 编译器会进行一些语义分析、语法分析、词法分析、符号汇总...生成一个.s文件 在Linux中对应的命令:gcc -S test.c -o test.s 其中-S选项是让其停在编译阶段 此时经过编译后称为汇编语言代码。
汇编
在连接阶段 编译器会生成符号表、把汇编指令转化为二进制指令...... 生成一个.o文件 在Linux下的命令:gcc -c text.c -o test.o 其中-c选项是让其停在汇编阶段 此时文件内就是cpu可以执行的二进制命令。
链接
在链接阶段 编译器会合并段表、合并符号表和符号表的重定位(就是明确地址)......生成可执行程序 在Linux下命令:gcc text.c -o text这里gcc默认是执行完链接过程 此时生成了可执行程序或库文件
再贴一些常用选项:
-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
-S 编译到汇编语言不进行汇编和链接
-c 编译到目标代码
-o 文件输出到 文件
-static 此选项对生成的文件采用静态链接
-g 生成调试信息。
GNU 调试器可利用该信息。
-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
-O0 -O1 -O2 -O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
-w 不生成任何警告信息。
-Wall 生成所有警告信息。
3.动静态库的理解
函数库概念
在我写c语言代码的时候我有时候在想我用的一些库函数:printf scanf......这些我也没有实现啊虽然包了头文件 但是我看过里面不过是这些函数的声明罢了 那我用的这些函数的实现又在哪里呢?于是我开始搜索资料 我发现:原来这些函数的定义都放在libc.so.6这个库文件中 在没有特别说明的时候gcc会把这个库文件和汇编后的文件进行合并链接 这样我们就可以使用库中的函数了。
上面我们了解到我们所用的一些库函数其实它的定义是被写在一个库文件中 这个库文件又有静态库文件(.so)和动态库文件(.a)之别。gcc/g++默认动态链接 可以加 -static选项变成静态链接(通过指令:ldd+文件名 或 file + 文件名查看是什么链接)
静态链接
把库中方法真的拷贝到我们的程序中。但是程序会很大,会重复在内存中出现 但是不依赖库
动态链接
将库中我要的方法的地址填入可执行程序中,产生关联。程序较小,但是依赖库
2.Makefile的使用
make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
mytest:目标文件
test.c:依赖关系文件列表
最前面加tab + gcc test.c -o mytest :依赖方法
.PHONY是Make file中类似关键字 表示clean 是伪目标(总是被执行)
clean:依赖文件(无)
tab + 依赖方法
命令行输入 make 它自顶向下扫描 会默认去执行第一对目标文件。
如何理解上文中的”总是被执行呢“
从上面例子可以看出伪目标文件可以强制执行而目标文件会根据它的逻辑(这里会看目标文件的修改时间(通过stat查看)和依赖文件的修改时间对比 如果依赖文件修改时间新于目标文件或者目标文件不存在才会执行)判断是否需要执行。
多文件的makefile
从上面来看make 要执行第一个目标 但是没有依赖文件 那么makefile会向下扫描查后续依赖关系和方法帮你形成依赖文件 。