我发现我正在编写很多可以使用 n -tuple列表清理的Makefile。但是我找不到任何方法(干净利落地)做到这一点。到目前为止,我只能使用 $(shell ...)和 tr , sed 或其他非Makefile标准。
例如,我想这样做:
XYZs = \
dog.c pull_tail bark \
duck.c chase quack \
cow.c tip moo
all:
@- $(foreach X Y Z,$(XYZs), \
$(CC) $X -o bully/$Y ; \
ln bully/$Y sounds/$Z ; \
)
有没有一种好方法可以在Makefile中迭代 n -tuple列表?谢谢!
答案 0 :(得分:11)
Makefile本质上是声明性的,所以我不认为make本身提供了你想要的东西。但是,您似乎想要将某些字符串值与特定目标相关联,因此GNU make的Target specific variable values功能可能会引起您的兴趣。这是手册摘录:
还有一个特殊功能 特定于目标的变量:当你 定义特定于目标的变量, 该变量值也有效 对于此目标的所有依赖项 (除非这些依赖关系覆盖它 与他们自己的目标具体 变量值)。所以,例如,a 声明如下:
prog : CFLAGS = -g
prog : prog.o foo.o bar.o
会在命令中将
CFLAGS
设置为-g
prog
的脚本,但它也会 在命令中将CFLAGS
设置为-g
创建prog.o,foo.o的脚本, 和bar.o,以及任何命令脚本 这会创建他们的依赖。
如果您还没有阅读过,那么GNU make手册非常好。
编辑:在评论中执行您的要求:
dog: ANIMAL=dog.c BULLY=pull_tail SOUND=bark
使用:
dog: ANIMAL=dog.c
dog: BULLY=pull_tail
dog: SOUND=bark
答案 1 :(得分:7)
我会在foreach上查看GNU Make手册。这里有一些随机剪辑,我在一个不同的项目中使用过...这个例子不完整,但也许会给你一些想法?如果我有更多的时间,我可能会在以后清理它......
REMAKE_PROGS:= dog duck cow
XYZs = \
dog.c pull_tail bark \
duck.c chase quack \
cow.c tip moo
$(foreach src, $(XYZs), $(eval $MAKE $(src))
$(REMAKE_PROGS):
@echo "\n# === $@ linking\n"
$(call compile,$@,$(OBJS_$@),$(CXX),$(MPICXX),$(LDFLAGS) $(LIBS) $(SYSLIBS) $(OTHER_LIB) $(EXTRA_LD_FLAGS))
@echo "\n# --- $@ compiled\n"
define compile
@mkdir -p $(dir $(1))
$(if ${ANNOUNCE},@echo "\n# +++ ${MAKECMDGOALS} compiling\n" $(eval ANNOUNCE=))
$(call compiler,$(1),NOMPI,$(3),$(4))
$(eval MY_FLAGS=$(FLAGS_$(1)) $(5))
$(if $(filter %xlf %xlf90,$(COMPILER_$(1))),$(eval MY_FLAGS:=$(MY_FLAGS:-D%=-WF,-D%)))
$(strip $(COMPILER_$(1)) $(2) $(MY_FLAGS) -o $(1) )
endef
答案 2 :(得分:6)
感谢提示 - 经过一些黑客攻击后,我认为这更像是我所希望的:
XYZs = \
dog.c:pull_tail:bark \
duck.c:chase:quack \
cow.c:tip:moo
all:
@- $(foreach XYZ,$(XYZs), \
$(eval X = $(word 1,$(subst :, ,$(XYZ)))) \
$(eval Y = $(word 2,$(subst :, ,$(XYZ)))) \
$(eval Z = $(word 3,$(subst :, ,$(XYZ)))) \
\
$(CC) $X -o bully/$Y ; \
ln bully/$Y sounds/$Z ; \
)
任何人都可以做得更好吗?
答案 3 :(得分:2)
我不知道,但那是因为你试图强迫make工作和命令式语言,当它不是它的时候。
在GNU中,你可能想做类似的事情:
pull_tail : SOUND=bark
pull_tail : dog.c
$(CC) $< -o $^
ln $@ $(SOUND)
chase : SOUND=quack
chase : duck.c
$(CC) $< -o $^
ln $@ $(SOUND)
...
或者更好的是,重新定义.c文件的默认规则来处理链接,但是名称的奇怪结构(程序名称与源名称没有词汇关系)使得这很难。 / p>
如果您希望能够在没有大量手动编辑的情况下快速重建此内容,您可能希望编写一个脚本来从数据重新生成makefile framgment并使用GNU make的include
功能...
答案 4 :(得分:0)
你正在倒退。
你正在尝试将make视为一个脚本。它不是,而是关于如何在给定Y的情况下创建X的一套规则。然后,make引擎会计算出获得该结果需要发生的事情。
对于给出的示例,您确实应该使用脚本来生成步骤。也许从make调用,但让我们处理CC的东西。
答案 5 :(得分:0)
您可以对一组具有相同扩展名的文件使用默认规则,以便将每个c
文件编译为o
。当然,您不限于任何特殊的文件扩展名。要编译一组.c
文件,您可以这样做:
OBJS = foo.o bar.o baz.o
OUT = myprog
all: $(OBJS)
$(SILENT) echo "LD $@"
$(SILENT) $(CPP) -o $(OUT) $^ $(LDFLAGS)
%.o: %.c
$(SILENT) echo "CC $<"
$(SILENT) $(CC) $(CCOPTS) -o $@ -c $<