目录
makefile的编写规则:基本格式:示例:联合编译apple.c 和 orange.c
进阶:更省时间的编写方法 || 预定义变量 || 获取同类型文件指令 || 替换文件名后缀
makefile是什么:
makefile是一个文本文件,我们在其中编写项目的构建规则。
如何使用makefile:
(以下操作均在mkf文件中进行):
[dev@localhost mkf]$ vim makefile //创建一个makefile文件
[dev@localhost mkf]$ make //使用make命令
输入make命令后,makefile的解释程序开始运行,在当前目录下找到名为makefile的文件,逐行解释执行。
makefile的编写规则:
基本格式:
目标对象 :依赖对象
[tab]为了生成目标对象所需要执行的指令
示例:联合编译apple.c 和 orange.c
首先,在mkf文件下创建两个.c文件
1: apple.c+ ⮂⮂ buffers
1 #include<stdio.h>
2 #include"fruit.h"
3
4 int main()
5 {
6 printf("this is apple.c.");
7 Orange();
8 return 0;
9 }
1: orange.c
1 #include<stdio.h>
2 #include"fruit.h"
3
4 void Orange(){
5 printf("this is orange.c\n");
6 }
通过fruit.h将两个.c文件联合,使得apple.c可以使用orange.c中的函数
1: fruit.h
1 extern void Orange(); //声明Orange()为全局函数
常规方法是使用如下命令,对这几个文件进行编译(注意:不需要加上fruit.h,在编译程序时,编译器会自动在目录下检索名为fruit.h的头文件)
此时,若需要多次编译调试,使用makefile ,可以省区许多写编译代码的时间。
进入makefile:
makefile+
main:orange.c apple.c
gcc orange.c apple.c -o main
目标对象 (main) :依赖对象(orange.c apple.c)
[tab]为了生成目标对象所需要执行的指令(gcc orange.c apple.c -o main)
这时,使用make指令,就可以和使用“gcc orange.c apple.c -o main”指令达到相同的效果了。
进阶:更省时间的编写方法
预定义变量
有时候,如果我们需要联合编译上百个文件,a.c ,b.c ,c.c ,d.c ,..... ,那么以下粉色字体需要写两遍,若是还要求生成.o文件,则需要花费更多的时间重复做相同的事情。此时,预定义变量可以帮助我们省去许多的时间。
预定义变量格式:
$@ 代表目标对象 $^ 代表所有依赖对象 $< 代表依赖对象的第一个
示例:
main:orange.c apple.c
gcc orange.c apple.c -o main
就等价于:
main:orange.c apple.c
gcc $^ -o $@
获取同类型文件指令
除了预定义变量,还有一个指令值得使用。情景:在当前文件下有许多.c为后缀的文件,需要将他们联合编译。
SRC=$(wildcard ./*.c) //代表获取所有.c类型的文件
main:$(SRC)
gcc $^ -o $@
其中,./代表当前目录,.c表示这类文件。
替换文件名后缀
$(SRC:%.c=%.o)
含义:将SRC变量中所有以.c结尾的文件名替换成对应的以.o结尾的文件名,然后赋回给SRC。
OBJ=$(patsubst %.c, %.o ,$(SRC))
含义:将SRC变量中所有以.c结尾的文件名替换成对应的以.o结尾的文件名,然后赋回给OBJ。
make解释执行规则:
1. make生成第一个目标对象之后就会退出
2. 为了生成目标对象,递归先查找依赖对象的生成规则,生成依赖对象之后再去生成目标对象。
示例:
apple.o:apple.c
gcc -c apple.c -o apple.o
orange.o:orange.c
gcc -c orange.c -o orange.o
main:apple.o orange.o
gcc apple.o orange.o -o main
在这段代码中,我们希望先由apple.c生成apple.o ,再由orange.c生成orange.o ,最后apple.o和orange.o一同生成main,而结果却与之不符:
可以看出没有生成orange.o,也没有生成main,而原因就是执行规则的第一条,“make”生成第一个目标对象之后就会退出。
所以,我们根据解释执行规则的第二条进行代码的改进:
main:apple.o orange.o
gcc apple.o orange.o -o main
apple.o:apple.c
gcc -c apple.c -o apple.o
orange.o:orange.c
gcc -c orange.c -o orange.o
此时,当编译器想通过apple.o 和 orange.o生成main时,发现并不存在这两个文件,就会递归寻找依赖对象的生成规则,依次生成apple.o和orange.o后,再生成main。
有的同学可能会问,不是生成目标对象就会退出吗?为什么生成apple.o后还会继续执行?注意了:因为是生成第一个目标对象之后,才会退出编译。