是否可以在 GNU make 模式中使用目录名称?

is it possible to use directory names in GNU make patterns?

我有许多设备驱动程序:每个设备的源代码都在与设备同名的子目录中:

devices/foo/foo.c
devices/bar/bar.c

如果我像这样为每个设备设置单独的 GNU make 规则,它会起作用:

obj/foo.o: devices/foo/foo.c
    $(CC) $(CFLAGS) devices/foo/foo.c -o obj/foo.o

如果我这样设置制作模式,它无法计算出如何制作文件。我想问题出在使用 % 作为子目录的名称。

obj/%.o: devices/%/%.c
    $(CC) $(CFLAGS) $< -o $@ 

有什么方法可以设置模式来执行此操作?

一个模式中只能有一个%matching rules 有点复杂。但是,匹配仅发生在目标(左侧)端,这就是为什么不能使用单个模式来搜索多个目录以获得正确先决条件的原因。

作为解决方法,您可以为每个目录生成一个模式规则。 GNU make 将使用先决条件实际存在的第一个模式规则。您还可以使用 VPATH variable or the vpath directive 搜索多个目录。

请注意,所有这些构造都会大大降低 GNU make 的速度,并使 makefile 更难编写和调试。最后,生成一个仅包含非模式规则的简单 makefile 可能是一个更好的权衡(在性能和维护开销方面)。

另一种方法是在您的 makefile 中定义以下函数 expand

expand = devices//.c

然后,启用 secondary expansion 后,您可以调用该函数来根据词干确定目标的先决条件,该词干位于 $*:

.SECONDEXPANSION:
obj/%.o: $$(call expand,$$*)
    $(CC) $(CFLAGS) $< -o $@