我正在使用包含规则的Makefile来创建依赖文件。编译器是GCC。
%.d: %.c
mkdir -p $(@D)
$(CC) $(CFLAGS) $(CPPFLAGS) -M $< | \
sed 's,\($(notdir $*)\.o\) *:,$(dir $@)\1 $@: ,' > $@.tmp
mv $@.tmp $@
我是Makefile技术的新手,我觉得有点难以理解这个由多个选项组合而成的规则。
有人可以简单解释这条规则是如何运作的吗?
提前谢谢。
答案 0 :(得分:2)
%.d: %.c
所有以.d
结尾的文件都可以使用此规则生成,只要有.c
文件具有相对于当前目录或其中一个vpath的相同目录和词干。
mkdir -p $(@D)
为$(@D)
创建最顶层和所有中间目录,这是一个自动生成变量,可扩展到当前目标的目录部分。
$(CC) $(CFLAGS) $(CPPFLAGS) -M $< | \
在第一个先决条件(whatever.c
)上调用C编译器,并告诉它输出一个make依赖项列表到标准输出。将此输出传递给
sed 's,\($(notdir $*)\.o\) *:,$(dir $@)\1 $@: ,' > $@.tmp
sed的。输出中的规则将与源文件具有相同的路径,但是编写此规则的人希望将对象文件放在不同的目录中,因此我们需要sed来替换路径。
Sed会捕获目标以.o
结尾且匹配$(notdir $*)
的所有规则。 $*
是另一个自动变量,它扩展为与当前规则中的%
匹配的模式,notdir
将删除任何目录部分,因此您将保留文件名stem而没有扩展名。
然后,Sed将$(dir $@)
添加到目标文件目标,这与我们上面看到的$(@D)
相同,并将依赖项文件本身($@
)添加为目标相同的先决条件。此输出将重定向到当前目标名称为.tmp
的文件。
mv $@.tmp $@
将上一个文件移动到规则的真实目标。
附注:如果你不介意在与目标文件相同的目录中生成依赖文件,那么这些配方已经过时,你可以通过以下方式实现同样的目的:
sources := src/somefile1.c src/somefile2.c
objects := $(sources:src/%.c=obj/%.o)
deps := $(objects:.o=.d)
CFLAGS := -MMD -MP
.PHONY: all
all $(objects)
$(objects): obj/%.o: src/%.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
-include $(deps)