0、源文件
cal.c
#include <stdio.h>
#include <unistd.h>
int add(int, int);
int sub(int, int);
int div(int, int);
int main(){
int a = 2, b = 2;
printf("%d + %d = %d\n", a, b, add(a,b));
printf("%d - %d = %d\n", a, b, sub(a,b));
printf("%d / %d = %d\n", a, b, div(a,b));
return 0;
}
add.c
int add(int a, int b){
return a + b;
}
sub.c
int sub(int a, int b){
return a - b;
}
div.c
int div(int a, int b){
return a / b;
}
1、makefile规则
1、若想生成目标,检查规则中的依赖条件是否存在
如不存在,则寻找是否有规则用来生成该依赖文件
2、检查规则中的目标是否需要更新,必须先检查它的所有依赖
依赖中有任一个被更新,则目标必须被更新
目标:依赖
(tab)命令
目标: 要生成的目标文件
依赖: 目标文件由哪些文件生成
命令: 通过执行该命令由依赖文件生成目标文件
1、目标的时间必须晚于依赖条件的时间,否则,更新目录
2、依赖条件如果不存在,寻找新的规则去产生依赖
3、makefile默认把遇到的第一组规则中的目标作为终极目标,因此要把生成终极目标的规则放在第一个,或则使用ALL指定终极目标
ALL: 指定make的终极目标
例1
makefile(哪个变化了就重新编译哪个,避免一个变化编译全部)
cal:cal.o add.o sub.o div.o
gcc cal.o add.o sub.o div.o -o cal
cal.o:cal.c
gcc -c cal.c -o cal.o
add.o:add.c
gcc -c add.c -o add.o
sub.o:sub.c
gcc -c sub.c -o sub.o
div.o:div.c
gcc -c div.c -o div.o
2、两个函数
src = $(wildcard ./*.c)
找到当前目录下所有后缀为.c的文件,把文件名作为一个列表赋值给src,src = add.c sub.c div.c
obj = $(patsubst %.c, %.o, $(src))
把参数3中,包含参数1的部分,替换为参数2,obj = add.o sub.o div.o
clean命令: 删除当前目录下的.o文件和cal文件
clean:
-rm -rf $(obj) cal
"-" 表示出错依然执行,当某个文件不存在时,其他文件依然可以删除
例2
makefile
src = $(wildcard *.c) # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o
ALL:cal
cal:$(obj)
gcc $(obj) -o cal
add.o:add.c
gcc -c add.c -o add.o
sub.o:sub.c
gcc -c sub.c -o sub.o
div.o:div.c
gcc -c div.c -o div.o
cal.o:cal.c
gcc -c cal.c -o cal.o
clean:
-rm -rf $(obj) cal
3、三个自动变量
$@ : 在一组规则的命令中,表示规则中的目标
$^ : 在一组规则中的命令中,表示所有依赖条件
$< : 在一组规则的命令中,表示第一个依赖条件。如果将该变量应用在模式规则中,它可将依赖条件列表中的依赖依次取出,套用模式规则
自动变量只能出现在命令中,目标和依赖中不能出现自动变量
例3
makefile
src = $(wildcard *.c) # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o
ALL:cal
cal:$(obj)
gcc $^ -o $@
add.o:add.c
gcc -c $< -o $@
sub.o:sub.c
gcc -c $< -o $@
div.o:div.c
gcc -c $< -o $@
cal.o:cal.c
gcc -c $< -o $@
clean:
-rm -rf $(obj) cal
4、模式规则
%.o:%.c
gcc -c $< -o $@
静态模式规则,指定模式规则给谁用
$(obj):%.o:%.c
gcc -c $< -o $@
例4
src = $(wildcard *.c) # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o
ALL:cal
cal:$(obj)
gcc $^ -o $@
%.o:%.c
gcc -c $< -o $@
clean:
-rm -rf $(obj) cal
此时增加一个mul.c模块不需要更改makefile文件
例5
使用静态模式规则指定某个模式规则应用于obj
makefile
src = $(wildcard *.c) # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o
ALL:cal
cal:$(obj)
gcc $^ -o $@
$(obj):%.o:%.c
gcc -c $< -o $@
clean:
-rm -rf $(obj) cal
5、clean命令
当前文件夹下有clean文件时,会影响makefile中的clean命令执行
解决方法,增加一行: .PHONY:clean ALL
例6
src = $(wildcard *.c) # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o
ALL:cal
cal:$(obj)
gcc $^ -o $@
$(obj):%.o:%.c
gcc -c $< -o $@
clean:
-rm -rf $(obj) cal
.PHONY:clean ALL
6、增加编译参数
例7
src = $(wildcard *.c) # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o
myArgs = -Wall -g
ALL:cal
cal:$(obj)
gcc $^ -o $@ $(myArgs)
$(obj):%.o:%.c
gcc -c $< -o $@ $(myArgs)
clean:
-rm -rf $(obj) cal
.PHONY:clean ALL
7、练习
文件结构
./inc 存放.h文件
./obj 存放.o文件
./src 存放.c文件
makefile
src = $(wildcard ./src/*.c) # src = ./src/add.c ./src/sub.c ./src/div.c ./src/cal.c
obj = $(patsubst ./src/%.c, ./obj/%.o, $(src)) # obj = ./obj/add.o ./obj/sub.o ./obj/div.o ./obj/cal.o
myArgs = -Wall -g
inc_path = ./inc
ALL:cal
cal:$(obj)
gcc $^ -o $@ $(myArgs)
$(obj):./obj/%.o:./src/%.c
gcc -c %< -o $@ $(myArgs) -I $(inc_path)
clean:
-rm -rf $(obj) cal
.PHONY:clean ALL