Gnu make:是否可以将 include 指令延迟到二次扩展?

Gnu make: is it possible to delay include directive to secondary expansion?

我需要将依赖片段的包含延迟到第二次扩展时间,因为我正在编辑的 make 文件本身就是一个包含文件,并且在第二次扩展之前我不会有源文件列表来生成包含。

.SECONDEXPANSION:
AUTO_DEPENDENCY_FILES = $(patsubst %.cc, depend/%.d, $(CC_SRC_FILES))

# the following does the work because the include argument is not a rule
# prerequisite therefore no secondary expansion occurs
include $$(AUTO_DEPENDENCY_FILES)

depend:
    -mkdir depend

all: autodepend

autodepend: depend autodepend_include

autodepend_include: $$(AUTO_DEPENDENCY_FILES)
    @echo \"$^\"

$$(AUTO_DEPENDENCY_FILES): depend

depend/%.d: | %.cc
    # generate .d files that do not exist
    $(COMPILE.cc) -E $*.cc > /dev/null

%.o: %.cc
    # update .d files that exist
    $(COMPILE.cc) -o $@ $<

请注意 COMPILE.cc 是一个很长的字符串,其中包含用于自动生成依赖项的 -MP -MMD -MFdepend/$*.d 标志。

我不知道这个问题有没有干净的解决方案,但只要稍加技巧,您就可以得到想要的东西。

给定一个主要 Makefile 的:

$(info main one)

include depend.mk

$(info main two)

CC_SRC_FILES := $(addsuffix .c,a b c d e f)

$(info main three)

depend.mk 个:

$(info depend one)

AUTO_DEPENDENCY_FILES = $(patsubst %.c,%.d,$(CC_SRC_FILES))
$(info AUTO_DEPENDENCY_FILES := $(AUTO_DEPENDENCY_FILES))
$(info MAKE_RESTARTS := $(MAKE_RESTARTS))
$(info CC_SRC_FILES := $(CC_SRC_FILES))

$(info depend two)

当您 运行 make:

时,您会得到以下输出
main one
depend one
AUTO_DEPENDENCY_FILES :=
MAKE_RESTARTS :=
CC_SRC_FILES :=
depend two
main two
main three
make: `all' is up to date.

考虑到文件的分配和包含顺序等,这并不奇怪

这就是可怕的黑客入侵的地方。

当 make 遇到引用不存在的文件的 include 指令时,make 会将文件粘贴在 "missing include files" 列表中并继续解析 makefile。

当它到达 makefile 的末尾时,它会尝试将该列表中的每个条目视为潜在的目标目标1 并尝试制作文件。

生成 makefile 后,make 会重新启动并再次尝试。

您可以使用它在您的 makefile 包含的内置 makefile 中捕获 CC_SRC_FILES 的值,并在需要时使其可见。

如果我们让 depend.mk 看起来像这样:

$(info depend one)

include hack.mk

AUTO_DEPENDENCY_FILES = $(patsubst %.c,%.d,$(CC_SRC_FILES))
$(info AUTO_DEPENDENCY_FILES := $(AUTO_DEPENDENCY_FILES))
$(info MAKE_RESTARTS := $(MAKE_RESTARTS))
$(info CC_SRC_FILES := $(CC_SRC_FILES))

$(info depend two)

hack.mk: $(if $(MAKE_RESTARTS),,force)
        @echo creating hack.mk
        @echo 'CC_SRC_FILES := $(CC_SRC_FILES)' > '$@'

force: ;

然后我们从 make 的输出变成:

main one
depend one
depend.mk:3: hack.mk: No such file or directory
AUTO_DEPENDENCY_FILES :=
MAKE_RESTARTS :=
CC_SRC_FILES :=
depend two
main two
main three
creating hack.mk
main one
depend one
AUTO_DEPENDENCY_FILES := a.d b.d c.d d.d e.d f.d
MAKE_RESTARTS := 1
CC_SRC_FILES := a.c b.c c.c d.c e.c f.c
depend two
main two
main three
make: `all' is up to date.

这给了我们想要的价值。

这不是很漂亮,但确实有效。