1、语法
编写 Makefile 的语法规则如下:
1. 目标(Target)规则:
一个目标规则由目标文件、依赖文件和命令组成。它的基本语法如下:
target: dependencies
command
其中,target
是一个目标文件或一个伪目标(以 .PHONY 声明),dependencies
是该目标所依赖的文件,command
是执行的命令。
- 变量(Variable)定义:
可以使用变量来存储和替代一些常用的参数、路径或编译选项。定义一个变量的语法如下:
variable = value
或者使用延续行符 \
定义多行变量:
variable = value1 \
value2 \
value3
在后续使用变量时,可以使用 $
加上变量名来引用它。
- 函数(Function):
Makefile 支持一些内置函数,可以用于对变量进行操作、字符串处理等。函数的语法如下:
$(function_name arguments)
其中,function_name
是函数名,arguments
是函数的参数。
4. 条件判断:
可以使用条件判断来根据不同的情况执行不同的命令或规则。常见的条件判断语法如下:
ifeq ($(variable), value)
command
else
command
endif
其中,$(variable)
是要判断的变量,value
是要比较的值,command
是要执行的命令。
-
注释:
可以使用#
来添加注释,注释可以在一行的任意位置添加。 -
特殊规则:
还有一些特殊的规则,如.PHONY
伪目标,用于声明一个目标是伪目标;.DEFAULT
规则,用于指定默认的目标等。
以上是 Makefile 的基本语法规则。通过这些规则,我们可以定义目标和依赖关系,并编写相应的命令来构建和编译项目。可以根据具体的项目需求,使用条件判断、变量和函数等高级特性来编写更灵活和复杂的 Makefile。
2、例子
2.1、编译单文件的Makefile
main.c文件
#include <stdio.h>
// int fun1(int number, int sum);
int main(int argc, char const *argv[])
{
printf("本程序由makefile进行编译\n");
return 0;
}
Makefile:
main:main.o
gcc -o main main.o
main.o:main.c
gcc -c main.c -o main.o -std=c99 -Wall
clear:
rm main.o main
2.2、编译多文件的Makefile
main.c:
#include <stdio.h>
int fun1(int number, int sum);
int main(int argc, char const *argv[])
{
printf("本程序由makefile进行编译\n");
int number = 0;
printf("请输入一个整数:");
scanf("%d", &number);
printf("从0~%d进行求和得到的值为:%d\n", number, fun1(number, 0));
return 0;
}
file1:
#include <stdio.h>
/**
* @brief 递归函数 fun1
*
* @param number 初始数值
* @param sum 当前累加和
* @return int 最终累加和
*/
int fun1(int number, int sum)
{
if (number == 0)
return sum;
sum += number;
return fun1(--number, sum);
}
Makefile:
main:main.o file1.o
gcc -o main main.o file1.o
main.o:main.c
gcc -c main.c -o main.o -std=c99 -Wall
file1.o:file1.c
gcc -c file1.c -o file1.o -std=c99 -Wall
clean:
rm main.o file1.o main
运行结果为:
make 命令的 -B 参数
在Ubuntu中,make -B
命令会强制执行Makefile中的所有规则,即使目标文件已经是最新的或者没有被修改过。通常情况下,make工具会根据目标文件的时间戳和依赖关系自动判断是否需要重新编译,只对有修改的文件进行重新编译。但是使用make -B
命令后,将会忽略时间戳和依赖关系,强制重新编译所有目标文件。
这个选项通常用于以下情况:
1. 当你修改了Makefile中的规则,需要确保所有目标文件都会被重新编译。
2. 当你需要确保重新编译所有目标文件,无论它们是否已经是最新的。
需要注意的是,使用make -B
命令可能会导致不必要的重新编译,因为它会忽略时间戳和依赖关系。因此,在正常情况下,建议只编译那些有修改的文件或者依赖被修改的文件,以提高编译效率。
用上一份代码来进行举例,make命令只需要加上-B参数:
2.3、万能makefile
万能makefile适用于多文件不同版本的项目。
代码仍然沿用2.2、编译多文件的Makefile
,相关代码为:
SRCS=$(wildcard *.c) # 获取当前目录下所有以.c结尾的源文件名
OBJS=$(patsubst %.c,%.o,$(SRCS)) # 将源文件名替换为对应的目标文件名
TARGET=main # 目标文件名
CC=gcc # 编译器命令
DELETE=rm # 删除命令
# 目标文件依赖于所有的目标文件
$(TARGET):$(OBJS)
# 使用编译器将所有目标文件链接成目标文件
$(CC) $(OBJS) -o $(TARGET)
# 目标文件依赖于对应的源文件
%.o:%.c
# 使用编译器将源文件编译成目标文件
$(CC) -c $(^) -o $(@) -std=c99
# clean规则,用于清除目标文件和可执行文件
clean:
# 使用删除命令删除目标文件和可执行文件
$(DELETE) $(OBJS) $(TARGET)
在虚拟机中观察到的运行现象为: