大家好,又见面了,我是你们的朋友全栈君。
1.上一篇博客虽然简单实现了自动处理依赖关系,但是生成的各种临时文件都混在一起,太乱了。
假定我们的源文件放在src目录,头文件放在inc目录,.o文件放在obj目录,.d文件放在dmk目录,Makefile和上述4个目录为同一级别。
则定义如下变量:
D_SRC = src
D_INC = -I./inc
D_OBJ = obj
D_MK = dmk
2.自动遍历src目录下的所有.c文件
SRC_C = $(wildcard $(D_SRC)/*.c)
# wildcard表示把$(D_SRC)目录下的.c文件遍历出来
SRC_C = $(foreach dir, $(D_SRC), $(wildcard $(dir)/*.c))
# foreach表示遍历$(D_SRC)的所有子目录同时把子目录下的.c文件遍历出来
假设src目录中有a.c,b.c,则$(SRC_C) 表示 src/a.c src/b.c
3.生成所有的.o文件依赖和.d文件集合
OBJ_C = $(addprefix $(D_OBJ)/,$(patsubst %.c,%.o,$(notdir $(SRC_C))))
SRC_MK = $(addprefix $(D_MK)/, $(patsubst %.c,%.d,$(notdir $(SRC_C))))
notdir表示去除目录,则$(notdir $(SRC_C))表示a.c b.c
patsubst表示把$(notdir $(SRC_C))中的.c替换成.o,即a.o b.o
addprefix表示增加前缀$(D_OBJ)/,则OBJ_C变量表示为obj/a.o obj/b.o
4.明白了上述语句之后我们可以把makefile写成如下状态
D_SRC = src
D_INC = -I./inc
D_OBJ = obj
D_MK = dmk
TATGET = hello
SRC_C = $(foreach dir, $(D_SRC), $(wildcard $(dir)/*.c))
OBJ_C = $(addprefix $(D_OBJ)/,$(patsubst %.c,%.o,$(notdir $(SRC_C))))
SRC_MK = $(addprefix $(D_MK)/, $(patsubst %.c,%.d,$(notdir $(SRC_C))))
$(TATGET):$(OBJ_C)
gcc -o $@ $^
$(D_OBJ)/%.o:$(D_SRC)/%.c
gcc -c -Wall $(D_INC) $< -o $@
$(D_MK)/%.d:$(D_SRC)/%.c
@set -e; rm -f $@; \
$(CC) -MM $(D_INC) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,$(D_OBJ)/\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
include $(SRC_MK)
.PHONY: clean
clean:
rm -f $(D_OBJ)/* $(TATGET) $(D_MK)/*
多出来的几行依赖关系其实就是一个字符串匹配的模式,clean就不需要解释了。
5.vpath 自动变量的使用,第一个参数是查找的类型,第二个是查找的目录
vpath %.c src #查找依赖时如果遇到%.c,则自动到src目录下寻找
D_SRC = src
D_INC = -I./inc
D_OBJ = obj
D_MK = dmk
TATGET = hello
SRC_C = $(foreach dir, $(D_SRC), $(wildcard $(dir)/*.c))
OBJ_C = $(addprefix $(D_OBJ)/,$(patsubst %.c,%.o,$(notdir $(SRC_C))))
SRC_MK = $(addprefix $(D_MK)/, $(patsubst %.c,%.d,$(notdir $(SRC_C))))
$(TATGET):$(OBJ_C)
gcc -o $@ $^
$(D_OBJ)/%.o:%.c #自动去src目录下找.c结尾的文件。
gcc -c -Wall $(D_INC) $< -o $@
$(D_MK)/%.d:%.c
@set -e; rm -f $@; \
$(CC) -MM $(D_INC) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,$(D_OBJ)/\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
include $(SRC_MK)
.PHONY: clean
clean:
rm -f $(D_OBJ)/* $(TATGET) $(D_MK)/*
查找多个目录用下面的写法
vpath %.c src:src1:src2
大写VPATH只能指定依赖的查找目录,不能指定类型,所以也可以写成
VPATH = src
D_SRC = src
D_INC = -I./inc
D_OBJ = obj
D_MK = dmk
TATGET = hello
SRC_C = $(foreach dir, $(D_SRC), $(wildcard $(dir)/*.c))
OBJ_C = $(addprefix $(D_OBJ)/,$(patsubst %.c,%.o,$(notdir $(SRC_C))))
SRC_MK = $(addprefix $(D_MK)/, $(patsubst %.c,%.d,$(notdir $(SRC_C))))
$(TATGET):$(OBJ_C)
gcc -o $@ $^
$(D_OBJ)/%.o:%.c
gcc -c -Wall $(D_INC) $< -o $@
$(D_MK)/%.d:%.c #自动去VPATH指定的目录查找,指定多个路径 写成VPATH = src:src1:src2
@set -e; rm -f $@; \
$(CC) -MM $(D_INC) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,$(D_OBJ)/\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
include $(SRC_MK)
.PHONY: clean
clean:
rm -f $(D_OBJ)/* $(TATGET) $(D_MK)/*
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/143708.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...