2009-06-10 90 views
8

我发现我正在写大量的Makefile,可以使用n -tuple清单进行清理。但我找不到任何方法正确(干净地)做到这一点。到目前为止,我只能够拿出使用$(shell ...)tr,sed,或者其他非Makefile标准。在Makefiles中对列表进行迭代?

例如,我想这样做:

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的好办法?谢谢!

回答

10

Makefiles基本上是声明性的,所以我不认为这会让你自己提供你想要的。但是,您似乎想要将某些字符串值与特定目标相关联,因此GNU make的Target specific variable values功能可能会引起您的兴趣。这是从手工摘录:

有 特定目标变量的一个比较特殊的功能:当你 定义一个特定目标变量, 变量值也有效 为所有依赖这个目标 (除非那些依赖关系用它们自己的目标特定 变量值覆盖它 )。因此,举例来说,一个 声明是这样的:

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 
+0

很酷,它可能在那里!有没有语法来做到这一点? 狗:ANIMAL = dog.c BULLY = pull_tail SOUND =树皮 – Dylan 2009-06-10 21:06:42

+0

+1,非常好。 – 2009-06-24 16:45:28

+2

问题不是make是声明式的,而是它没有为这种经常需要的模式提供声明性语法! – reinierpost 2010-07-06 14:24:58

0

你倒着做。

你正在试图像对待它是一个脚本。这不是,而是它关于如何创建X给定Y的一组规则。然后,make引擎会计算出需要发生什么才能获得结果。

对于给出的示例,您确实应该使用脚本来生成步骤。也许从make调用,但让我们来处理CC的东西。

+4

这是make中的一个限制,没有理由首先出现,无论如何可以用$(foreach)解决。 – reinierpost 2010-07-06 14:29:49

2

我所知道的都不是,但那是因为你试图强迫make开始工作,并且这是一种命令式语言,但当它不是这样的时候。

在GNU让你可能会想要做的事,如:

pull_tail : SOUND=bark 
pull_tail : dog.c 
     $(CC) $< -o $^ 
     ln [email protected] $(SOUND) 

chase : SOUND=quack 
chase : duck.c 
     $(CC) $< -o $^ 
     ln [email protected] $(SOUND) 

... 

或者更好的是,重新定义.c文件处理链接为您的默认规则,但你的名字的奇特结构(程序名称与源名称没有词汇关系)使得这很难。

如果你想能够没有大量的手工编辑的快速重建这算什么,你可能想编写一个脚本来重新生成数据makefile文件framgment和使用GNU的include功能使...

5

我会检查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# === [email protected] linking\n" 
     $(call compile,[email protected],$([email protected]),$(CXX),$(MPICXX),$(LDFLAGS) $(LIBS) $(SYSLIBS) $(OTHER_LIB) $(EXTRA_LD_FLAGS)) 
     @echo "\n# --- [email protected] 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 
0

您可以使用默认的规则一组具有相同的扩展名的文件在编制各c文件的o。当然,你不限于任何特殊的文件扩展名。对于编制一套.c文件,你可以做这样的:

OBJS = foo.o bar.o baz.o 
OUT = myprog 

all: $(OBJS) 
     $(SILENT) echo "LD [email protected]" 
     $(SILENT) $(CPP) -o $(OUT) $^ $(LDFLAGS) 

%.o: %.c 
     $(SILENT) echo "CC $<" 
     $(SILENT) $(CC) $(CCOPTS) -o [email protected] -c $< 
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 ; \ 
    ) 

任何人都可以做得更好?