Makefile快速入门
1 什么是 Makefile
-
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,Makefile 文件定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 Makefile 文件就像一个 Shell 脚本一样,也可以执行操作系统的命令。
-
Makefile 带来的好处就是“自动化编译” ,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。 make 是一个命令工具,是一个解释 Makefile 文件中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,比如 Delphi 的 make, Visual C++ 的 nmake, Linux 下 GNU 的 make。
2 命名规则
- 文件命名:makefile 或者 Makefile
- Makefile 规则:
实例
mult.c
#include <stdio.h>
#include "head.h"
int multiply(int a, int b)
{
return a*b;
}
div.c
#include <stdio.h>
#include "head.h"
double divide(int a, int b)
{
return (double)a/b;
}
add.c
#inclue <stdio.h>
#include "head.h"
int add(int a, int b)
{
return a+b;
}
sub.c
#include <stdio.h>
#include "head.h"
int subtract(int a, int b)
{
return a-b;
}
main.c
#include <stdio.h>
#include "head.h"
int main()
{
int a = 20;
int b = 12;
printf("a = %d, b = %d\n", a, b);
printf("a + b = %d\n", add(a, b));
printf("a - b = %d\n", subtract(a, b));
printf("a * b = %d\n", multiply(a, b));
printf("a / b = %f\n", divide(a, b));
return 0;
}
head.h
#ifndef _HEAD_H
#define _HEAD_H
// 加法
int add(int a, int b);
// 减法
int subtract(int a, int b);
// 乘法
int multiply(int a, int b);
// 除法
double divide(int a, int b);
#endif
Makefile
app:sub.c add.c mult.c div.c main.c
gcc sub.c add.c mult.c div.c main.c -o app
3 工作原理
命令在执行之前,需要先检查规则中的依赖是否存在
- 如果存在,执行命令
- 如果不存在,向下检查其它的规则,检查有没有一个规则是用来生成这个依赖的,如果找到了,则执行该规则中的命令
检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间
- 如果依赖的时间比目标的时间晚,需要重新生成目标
- 如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行
Makefile
app:sub.o add.o mult.o div.o main.o
gcc sub.o add.o mult.o div.o main.o -o app
sub.o:sub.c
gcc -c sub.c -o sub.o
div.o:div.c
gcc -c div.c -o div.o
add.o:add.c
gcc -c add.c -o add.o
mult.o:mult.c
gcc -c mult.c -o mult.o
main.o:mult.c
gcc -c main.c -o main.o
4 变量
Makefile
#def
src=sub.o add.o mult.o div.o main.o
target=app
$(target):$(src)
$(CC) $(src) -o $(target)
sub.o:sub.c
gcc -c sub.c -o sub.o
div.o:div.c
gcc -c div.c -o div.o
add.o:add.c
gcc -c add.c -o add.o
mult.o:mult.c
gcc -c mult.c -o mult.o
main.o:mult.c
gcc -c main.c -o main.o
5 模式匹配
Makefile
#def
src=sub.o add.o mult.o div.o main.o
target=app
$(target):$(src)
$(CC) $(src) -o $(target)
%.o:%.c
$(CC) -c $< -o $@
6 函数
#def
src1=$(wildcard ./*.c)
src=$(patsubst %.c, %.o, $(src1))
target=app
$(target):$(src)
$(CC) $(src) -o $(target)
%.o:%.c
$(CC) -c $< -o $@
可以清理多出来的.o过程文件,通过make clean命令
#def
src1=$(wildcard ./*.c)
src=$(patsubst %.c, %.o, $(src1))
target=app
$(target):$(src)
$(CC) $(src) -o $(target)
%.o:%.c
$(CC) -c $< -o $@
clean:
rm $(src) -f
7 伪目标 .PHONY
若存在clean文件,则通过make clean会冲突,因此设置伪目标形式,可继续使用make clean命令进行清理编译、汇编的结果文件。
所谓伪目标,就是指没有真正的文件和它对应,只是一个标识而已。
#def
src1=$(wildcard ./*.c)
src=$(patsubst %.c, %.o, $(src1))
target=app
$(target):$(src)
$(CC) $(src) -o $(target)
%.o:%.c
$(CC) -c $< -o $@
.PHONY:clean
clean:
rm $(src) -f