迭代Makefile中的列表?

时间:2009-06-10 20:21:20

标签: linux makefile

我发现我正在编写很多可以使用 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列表?谢谢!

6 个答案:

答案 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 $<