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.
这给了我们想要的价值。
这不是很漂亮,但确实有效。
我需要将依赖片段的包含延迟到第二次扩展时间,因为我正在编辑的 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.
这给了我们想要的价值。
这不是很漂亮,但确实有效。