编译流程
- 预处理
- 编译
- 汇编
- 连接
预处理
完成宏替换,文件引入,去除空行和注释
gcc -E test.c -o test.i
编译
转换成汇编代码;
gcc -S test.i -o test.s
汇编
转成目标文件
gcc -c test.i -o test.o
连接
转成可执行目标文件
gcc test.o -o test
./test
静态库
静态库实际上是一些目标文件的集合(.o),静态库是以".a"结尾的。只用于生成可执行文件阶段。
在连接阶段,连接器将从库中取出所需要的代码,复制到可执行文件中。这种库成为静态库。其特点是可执行文件中包含了库代码的一份完整的拷贝,在编译过程中,就被加载到程序。缺点:重复,且牵一发而动全身。
#首先生成目标文件
gcc -c test.c -o test.o
#打包成静态库
ar rcs libtest.a test.o
# 查看静态库的内容
ar t libtest.a
动态库
运行时,加载的库
gcc -c test.c -o test.o
gcc -shared -fPIC
makefile走读与语法基础
makefile定义了一些规则,哪些文件先编译,哪些文件重新编译,如何进行连接
makefile就是“自动化编译”,告诉make命令如何编译和连接。
makefile 包含的内容
- 显示规则
- 隐晦规则
- 变量的定义
- 文件指示
- 注释 (用#进行单行注释)
makfile的规则
a. target 要生成的目标文件
b. prerequisites 依赖文件,即生成target所需要的文件或者其他target
c. command make需要执行的命令
使用方式一:
target: prerequistes ... ; command
使用方式二:
target: prerequistes ...
command
案例
假设当前的目录下存在 main.c tools.c tools.h等三个文件,下面是makefile的内容:
//.o 文件会make自动推导出来
main: main.o tools.o
gcc main.o tools.o -o main
.PHONY:clean //显示的声明一个“伪目标”
clean: //该标签不会生成‘clean’文件,这样的target被称为‘伪目标’
-rm main *.o //通过clean 删除可执行文件和中间的目标文件。 // -表示不会终止
make的工作原理
1.make会在当前目录下查找名为“Makefile”或者“makefile”的文件
2.如果找到,它会把该文件中的第一个target,作为最终的target生成。
3.如果main文件不存在或者main依赖的o文件比较新,则它会重新生成main文件。
4.如果main所依赖的o文件也存在,那么make会在当前文件中,查找该o文件对应的依赖,若找到,则根据规则生成。
5.make再用.o文件生成 终极任务的可执行文件。
makefile中的变量的使用
objects = main.o tools.o //声明变量
main: $(objects) #使用变量
gcc $(objects) -o main
.PHONY:clean
clean:
-rm main $(objects)
引入其他的makefile
使用include关键字可以将其他makefile引入
include<filename>
bar = z.mk y.mk
include foo.make *.mk $(bar)
-include foo.make *.mk // '-'表示如果文件找不到,make不会终止,会继续执行
makefile中的预定义变量
| 变量名称 | 描述 | 默认值 |
|---|---|---|
| CC | C语言编译器 | cc |
| CPP | C语言预处理器 | $(CC) -E |
| CXX | C++语言编译器 | g++ |
| RM | 删除文件程序的名称 | rm -f |
| CFLAGS | C语言编译器编译选项 | 无 |
| CPPFLAGS | C语言预处理器编译选项 | 无 |
| CXXFLAGS | C++语言编译器编译选项 | 无 |
makefile中的自定变量
| 自定变量名称 | 描述 |
|---|---|
| $* | 目标文件的名称,不包含扩展名 |
| $@ | 目标文件的名称,含扩展名 |
| $+ | 所有依赖文件,以空格隔开,可能包含重复文件 |
| $^ | 所有依赖文件,以空格隔开,不包含重复文件 |
| $< | 依赖项中第一个依赖文件的名称 |
| $? | 依赖项中所有比目标文件新的文件 |
makefile中的函数
-
无参函数
define FUNC $(info echo "hello") endef $(call FUNC) -------------- 输出: hello -
带参函数
define FUNC $(info echo $(1) $(2)) endef $(call FUNC,hello,world) -------------- 输出: hello world
make的工作流程
1.读取所有的makefile文件
2.读入被include的makefile文件
3.初始化文件中的变量
4.推导隐晦规则,并分析所有规则
5.为所有的目标文件创建依赖关系链
6.根据依赖关系,决定哪些目标需要重新生成
7.执行生成命令