2009-06-10 95 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 ; \ 
    ) 

任何人都可以做得更好?