在Makefile中创建依赖项文件

时间:2016-07-14 07:54:29

标签: makefile dependencies

我正在使用包含规则的Makefile来创建依赖文件。编译器是GCC。

%.d: %.c
    mkdir -p $(@D)
    $(CC) $(CFLAGS) $(CPPFLAGS) -M $< | \
    sed 's,\($(notdir $*)\.o\) *:,$(dir $@)\1 $@: ,' > $@.tmp
    mv $@.tmp $@

我是Makefile技术的新手,我觉得有点难以理解这个由多个选项组合而成的规则。
有人可以简单解释这条规则是如何运作的吗? 提前谢谢。

1 个答案:

答案 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)