我正在使用包含规则的 Makefile 来创建依赖文件。编译器是GCC。
%.d: %.c
mkdir -p $(@D)
$(CC) $(CFLAGS) $(CPPFLAGS) -M $< | \
sed 's,\($(notdir $*)\.o\) *:,$(dir $@)\1 $@: ,' > <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5a7e1a742e372a" rel="noreferrer noopener nofollow">[email protected]</a>
mv <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="77533759031a07" rel="noreferrer noopener nofollow">[email protected]</a> $@
我对 Makefile 技术相当陌生,我发现理解这个由多个选项混合组成的规则有点困难。
有人可以简单解释一下这个规则是如何运作的吗?
提前致谢。
最佳答案
%.d: %.c
所有以 .d
结尾的文件可以使用这个规则,只要有.c
相对于当前目录或 vpath 之一具有相同目录和主干的文件。
mkdir -p $(@D)
为 $(@D)
创建最顶层和所有中间目录,这是一个自动 make 变量,可扩展到当前目标的目录部分。
$(CC) $(CFLAGS) $(CPPFLAGS) -M $< | \
根据第一个先决条件 ( whatever.c
) 调用 C 编译器,并告诉其将 make 依赖项列表输出到标准输出。将此输出通过管道传输到
sed 's,\($(notdir $*)\.o\) *:,$(dir $@)\1 $@: ,' > <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7551355b011805" rel="noreferrer noopener nofollow">[email protected]</a>
sed.输出中的规则将与源文件具有相同的路径,但是编写此规则的人希望对象文件位于不同的目录中,因此我们需要 sed 来替换路径。
Sed 捕获目标以 .o
结尾的任何规则那场比赛$(notdir $*)
。 $*
是另一个自动变量,它扩展到与 %
匹配的模式在当前规则中,和 notdir
将删除所有目录部分,以便您留下不带扩展名的文件名主干。
Sed 然后在前面加上 $(dir $@)
到目标文件目标,与 $(@D)
相同我们在上面看到,并将依赖文件本身( $@
)添加为相同先决条件的目标。此输出被重定向到一个文件,其名称为当前目标 + .tmp
.
mv <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b094f09ec4ddc0" rel="noreferrer noopener nofollow">[email protected]</a> $@
将前一个文件移动到规则的实际目标。
旁注:如果您不介意在与目标文件相同的目录中生成依赖项文件,那么这些配方已经过时,您可以通过以下方式实现相同的目的:
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)
关于makefile - 在Makefile中创建依赖文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38368531/