make :一般说的是 GNU Make,是一个软件,将源代码文件编译成可执行的二进制文件;
Makefile : make 工具编译的时候需要使用 Makefile 文件,Makefile 文件描述了整个工程的编译、连接规则。
Makefile 举例
注意 Makefile
的大小写 !!!
需要注意的是,所有行首需要空出来的地方一定要使用 TAB 键 !!!
执行一下 Makefile 文件,只需要输入make
命令;
若要清除工程,只需要输入make clean
,注意是删掉所有编译出来的文件,而不是删除源文件。
现在进行一些操作来展现 make 工具的强大之处,比如只修改一下 input.c 文件(在第 5 行输入回车换行);
再次输入make
命令;
通过两次 make 之后的结果可以看出,修改某个源文件,只会重新编译这个源文件。
Makefile 语法
Makefile 可以完成以下功能:
如果工程没有编译过,那么工程中的所有 .c 文件都会被编译并且连接成可执行文件;
如果只修改了工程中某几个 .c 文件,则只会重新编译这几个源文件;
如果只修改了工程中某几个 .h 文件,则就会重新编译包含这几个头文件的所有源文件并且连接成可执行文件;
要使用 make 工具,首先就要编写 Makefile 文件。
Makefile 规则格式:
目标:依赖文件集合
命令1
命令2
......
命令1和命令2前面空出来的地方必须使用 TAB 键
比如下面这条规则:
main:main.o input.o calcu.o
gcc -o main main.o input.o calcu.o
这条规则的目标是 main ,main.o、input.o、calcu.o 是生成 main 的依赖文件,如果要更新 main ,就必须要先更新他的所有依赖文件,只要依赖文件任何一个有了更新,那么它的目标就必须更新。
Makefile 变量
Makefile 中的变量都是字符串,类似于 C 语言中的宏定义;
赋值符 =
前面加上 @ 符号就不会显示执行过程;
采用等号(=)赋值,变量的真实值取决于它所引用的最后一次有效值。
赋值符 :=
采用冒号等号(:=)赋值,不会使用后面定义的变量,只能使用前面已经定义好了的。
赋值符 ?=
采用问号等号(?=)赋值,通过对比可以发现,curname ?= z 这句的意思是如果 curname 前面没有被赋值,则使用 ?= 后面的值,如果 curname 前面已经被赋值过,则使用前面赋的值。
赋值符 +=
采用加等号(+=)赋值, 原来 objects 是 main.o input.o ,追加一个 calcu.o ,现在 objects 是 main.o input.o calcu.o 。
Makefile 模式规则
%.o: %.c
命令
当 % 出现在目标中的时候,目标中 % 的值决定了依赖中 % 的值
Makefile 自动化变量
通过模式规则和自动化变量将 Makefile 修改如下
Makefile 伪目标
Makefile 有一种特殊的目标叫做伪目标,一般的目标名都是要生成的文件,而伪目标不代表真正的目标名,在执行 make 命令的时候通过指定这个伪目标来执行其所在规则的定义的命令。
使用伪目标主要是为了避免 Makefile 中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,有时候我们需要编写一个规则用来执行一些命令,但是这个规则不是用来创建文件的。
上述规则中并没有创建文件 clean 的命令,因此工作目录下永远都不会存在文件 clean,当我们输入“ make clean ”以后,后面的“ rm *.o ”和“ rm main ”总是会执行。可是当不小心在工作目录下创建一个名为“ clean ”的文件之后,那就不一样了,当执行“ make clean ”的时候,规则因为没有依赖文件,所以目标被认为是最新的,因此后面的 rm 命令也就不会执行,我们预先设想的清理工程的功能也就无法完成。
为了避免这个问题,我们可以将 clean 声明为伪目标。声明方式如下:
Makefile 条件判断
与 C 语言类似,通过条件判断语句来根据不同的情况执行不同的分支,条件关键字有 4 个(ifeq、ifneq、ifdef、ifndef)。
Makefile 函数声明
Makefile 中的函数都是定义好了的,可以直接使用,不支持自定义函数,make 所支持的函数虽然不多但绝对够用。
make 的执行过程
1、make 命令会在当前目录下查找以 Makefile(makefile 其实也可以)命名的文件
2、当找到 Makefile 文件以后就会按照 Makefile 中定义的规则去编译生成最终的目标文件。
3、当发现目标文件不存在,或者目标所依赖的文件比目标文件新(也就是最后修改时间比
目标文件晚)的话就会执行后面的命令来更新目标。
1 main: main.o input.o calcu.o
2 gcc -o main main.o input.o calcu.o
3 main.o: main.c
4 gcc -c main.c
5 input.o: input.c
6 gcc -c input.c
7 calcu.o: calcu.c
8 gcc -c calcu.c
9
10 clean:
11 rm *.o
12 rm main
上述代码中一共有 5 条规则,1、2 行为第一条规则,3、4 行为第二条规则,5、6 行为第三条规则,7、8 行为第四条规则,10、11、12 为第五条规则,make 命令在执行这个 Makefile 的时候其执行步骤如下:
首先更新第一条规则中的 main,第一条规则的目标成为默认目标,只要默认目标更新了那么就认为 Makefile 的工作完成了,整个 Makefile 就是为了完成这个工作。在第一次编译的时候由于 main 还不存在,因此第一条规则会执行,第一条规则依赖于文件 main.o、input.o 和 calcu.o 这个三个 .o 文件,这三个 .o 文件目前还都没有,因此必须先更新这三个文件。make 会查找以这三个 .o 文件为目标的规则并执行。以 main.o 为例,发现更新 main.o 的是第二条规则,因此会执行第二条规则,第二条规则里面的命令为“ gcc -c main.c ”,就是不连接编译 main.c,生成 main.o,其它两个 .o 文件同理;最后一个规则目标是 clean,它没有依赖文件,因此会默认依赖文件都是最新的,所以其对应的命令不会执行,当我们想要执行 clean 的话可以直接使用命令“ make clean ”,执行以后就会删除当前目录下所有的 .o 文件以及 main,因此 clean 的功能就是完成工程的清理。
make 工具完成了自动化编译工作,一旦写好了 Makefile 文件,以后只需要一个 make 命令即可完成整个工程的编译,避免了不必要的重复编译,大大提高了效率。
标签:文件,make,规则,Makefile,语法,Linux,input,main From: https://blog.csdn.net/ZSW2027008838/article/details/137397878