Linux - Makefile
为什么使用?
Makefile:编译器的辅助工具,是一个脚本语言(编译脚本)。
为什么使用Makefile?
因为大型的项目,源程序文件非常多,我们不可能一个个的去编译,所以有了这个工具进行管理。
注意
100+源文件用Makefile,否则用IDE即可。
前置知识
-
Linux相关简单命令:clear清屏、cd切换当前工作目录(进入某个目录)、ls查看当前工作目录(文件夹)、mkdir创建文件夹
-
linux系统只有一个盘符( / :叫做根目录),windows有C、D、E等盘符
-
共享文件夹:可以在windows下写代码,linux下编译。
-
在linux中,预处理,C的编译器叫GCC、C++的编译器叫G++。
GCC编译C语言
-
gcc *.c -o *(一个文件)
-
gcc 1.c 2.c 3.c 4.c 5.c ……(多个文件(但是必须在同一路径))
编译链接一步到位:
输入:gcc *.c(比如:gcc test.c )
输入:ls
回车输出:a.out test.c(linux下默认生成a.out,windows下是.exe)(a.out就是可执行程序)
执行可执行程序:./a.out
一个程序从源文件到可执行文件不是一步到位的,有很多步骤(简单理解为3步 .c -> .exe ):预处理、编译(预编译(只做简单的语法检查)、编译(做一些优化,生成中间文件(目标文件)))、链接
预处理-E
-
把.h.c展开形成一个文件,宏定义直接替换,头文件、库文件直接打开,形成一个 .i文件 gcc -E *.c
-
所生成的文件不会自动保存,需要手动保存。一般把它重定向到一个文件里面去gcc -E *.c > *.txt (比如:gcc -E test.c > test.txt,ls后会发现多了一个test.txt的文件)
-
预处理一般做预编译指令:头文件引入、宏的展开、指令的处理
gcc -E *.c -o *.i 把*.c这个文件预处理然后得到*.i(回车会发现得到一个 *.i 的文件)
汇编-S
- 把.i文件生成一个汇编代码文件*.S(回车会发现得到一个 *.S 的文件)
gcc -S *.i -o *.S
编译-c
-
目的:把.S文件生成一个目标文件(*.o、windows生成目标文件 *.obj)
-
gcc -c *.c(不指定的话默认生成 *.o , *.o 是一个二进制文件,是机器码)
gcc -c *.S -o *.o
链接-o
-
目的:把多个目标文件,包括动态库、静态库,链接到一起,生成最终的可执行文件。
-
把.o链接为(windows *.exe、linux *.elf文件)。
gcc *.o -o *
多文档编程
-
新建一个叫 makefile 的文本文档(无后缀)再去编写代码。
-
在Makefile中, # 表示注释。
- 显示规则(格式)
目标文件:依赖文件
[TAB]指令
Ex. 我们想要由 .c -> .i 文件:
hello:hello.o (第一个目标文件是我的最终目标(递归思想),希望得到hello这个可执行文件)
gcc hello.o -o hello (链接阶段)
hello.o:hello.S
gcc -c hello.S -o hello.o (编译阶段)
hello.S:hello.i
gcc -S hello.i -o hello.S (汇编阶段)
hello.i:hello.c
gcc -E hello.c -o hello.i (预处理阶段)
.PHONY:(伪目标)
clear: (clear部分可以换成自己想写的)
rm -rf hello.o hello.S hello.i hello
(也可以删除一部分文件,Ex. :rm -rf hello.o hello.S hello.i)
- 变量
-
变量符号:=替换、+=追加、:=恒等于
-
使用变量的时候: $(变量名)
比如:
TAR = test
OBJ = test.o main.o -o test
CC := gcc
$(TAR):$(OBJ
$(CC) -c test.c ……
- 隐含规则
-
%.c %.o:任意的.c或.o文件
-
.c、.o:所有的.c和所有的.o文件
- 通配符
-
$^:所有的依赖文件
-
$@:所有的目标文件
-
$<:所有的依赖文件的第一个文件
学习路径
https://www.bilibili.com/video/BV1B4411F7EK?from=search&seid=1534969121755526481