GNU Make:在传递给 Shell 之前扩展模式

GNU Make: expand pattern before passing to Shell

我想使用 awk 脚本来确定在编译 FORTRAN 源文件之前必须编译哪些模块。我的项目的结构使得我可以通过 运行

获取提供模块的文件名
awk '=/use/{print gensub(",","","g", ) ".o"}' file.f90

在我要编译的文件上

但是,我的 make 命令

%.o: $(shell awk '$=/use/{print gensub(",","","g", $) ".o"}' /path/to/%.f90)

失败

awk: fatal: cannot open file `/path/to/%.f90' for reading: No such file or directory

所以 %.f90 没有得到扩展。为什么会这样,我该如何解决这个问题?

目标和先决条件中的变量和函数在解析 makefile 时扩展,而不是当 make 是 运行 makefile 时。但是,只有当 make 是 运行 生成文件时,模式规则才会扩展,试图构建与模式匹配的目标。因此,在扩展这些变量和函数时,您只有文字模式字符串,而不是将其扩展为真实文件名。

请参阅文档中的 How make reads a makefile

有多种方法可以做到这一点。一种选择是使用 secondary expansion。但是请注意,您必须对正在转义的 $ 进行两次转义!!

.SECONDEXPANSION:
%.o: $$(shell awk '$$$=/use/{print gensub(",","","g", $$$) ".o"}' /path/to/$$*.f90)

预计到达时间

您也可以完全不使用 .SECONDEXPANSION,而是像这样使用 eval

%.o:
        ...

SRCS := $(wildcard *.f90)
OBJS := $(SRCS:%.f90=%.o)

$(foreach O,$(OBJS),\
    $(eval $O: $(shell awk '$=/use/{print gensub(",","","g", $) ".o"}' $(O:%.o=%.f90))))

因为你没有给出一个实际的例子,我只是编造了 SRCSOBJS 变量。也许你已经有类似的变量了。