如何在Makefile中編寫循環?


Answers

如果你使用GNU make,你可以試試

NUMBERS = 1 2 3 4
doit:
        $(foreach var,$(NUMBERS),./a.out $(var);)

這將生成並執行

./a.out 1; ./a.out 2; ./a.out 3; ./a.out 4;
Question

我想執行以下命令:

./a.out 1
./a.out 2
./a.out 3
./a.out 4
.
.
. and so on

如何將這個東西寫成Makefile的循環?




您可以使用set -e作為for循環的前綴。 例:

all:
    set -e; for a in 1 2 3; do /bin/false; echo $$a; done

make會立即退出,退出代碼<> 0




這不是對問題的純粹回答,而是一種解決此類問題的智能方法:

而不是編寫一個複雜的文件,只需將控制委託給例如bash腳本,如:makefile

foo : bar.cpp baz.h
    bash script.sh

和script.sh如下所示:

for number in 1 2 3 4
do
    ./a.out $number
done



我意識到這個問題已經有幾年了,但是這篇文章可能對某些人仍然有用,因為它展示了一種與上述不同的方法,並且不依賴於shell操作,也不需要開發人員拼出硬編碼數字值的字符串。

$(eval ....)內建宏是你的朋友。 或者至少可以。

define ITERATE
$(eval ITERATE_COUNT :=)\
$(if $(filter ${1},0),,\
  $(call ITERATE_DO,${1},${2})\
)
endef

define ITERATE_DO
$(if $(word ${1}, ${ITERATE_COUNT}),,\
  $(eval ITERATE_COUNT+=.)\
  $(info ${2} $(words ${ITERATE_COUNT}))\
  $(call ITERATE_DO,${1},${2})\
)
endef

default:
  $(call ITERATE,5,somecmd)
  $(call ITERATE,0,nocmd)
  $(info $(call ITERATE,8,someothercmd)

這是一個簡單的例子。 對於較大的值,它不會很好地縮放 - 它可以工作,但是對於每次迭代,ITERATE_COUNT字符串將會增加2個字符(空格和點),當您進入數千個字符時,需要逐漸更長的時間才能計算字數。 正如所寫,它不處理嵌套迭代(你需要一個單獨的迭代函數和計數器來做到這一點)。 這純粹是gnu make,沒有shell要求(儘管顯然OP每次都想運行一個程序 - 在這裡,我只是在顯示一條消息)。 ITERATE中的if旨在捕獲值0,因為$(word ...)會以其他方式出錯。

請注意,用作計數器的字符串越來越多,因為$(words ...)內建函數可以提供一個阿拉伯數字,但是這個數字並不支持數學運算(您不能將1 + 1賦值給某個數值並得到2,除非你從shell中調用某些東西來完成它,或者使用同樣複雜的宏操作)。 這對INCREMENTAL計數器非常有用,但是對於DECREMENT計數器來說不太好。

我自己並沒有使用它,但最近我需要編寫一個遞歸函數來評估跨多個二進制,多庫構建環境的庫依賴關係,在這些環境中,當您包含某個庫時需要知道引入OTHER庫本身有其他的依賴關係(其中一些依賴於構建參數),我使用類似於上面的$(eval)和counter方法(在我的情況下,計數器用於確保我們不會無休止地進入無盡的循環,也作為診斷來報告需要多少迭代)。

別的什麼也沒有價值,儘管對於OP的Q來說並不重要:$(eval ...)提供了一種方法來規避make對循環引用的內部厭惡,當變量是一個宏類型時,這是很好和很好的執行方式=)與立即賦值(用=初始化)之間的關係。 有時你希望能夠在自己的任務中使用變量,而$(eval ...)將使你能夠做到這一點。 這裡要考慮的重要一點是,在你運行eval的時候,變量會被解析,而被解析的那部分不再被視為宏。 如果你知道自己在做什麼,並且正在嘗試在自己的任務的RHS上使用變量,那麼這通常就是你想要發生的事情。

  SOMESTRING = foo

  # will error.  Comment out and re-run
  SOMESTRING = pre-${SOMESTRING}

  # works
  $(eval SOMESTRING = pre${SOMESTRING}

default:
  @echo ${SOMESTRING}

快樂make'ing。






Related