如何在 Makefile 的 foreach 语句中包含通配符模式

How to include wildcard pattern in foreach statement of Makefile

我在 makefile 中有一些规则,如下所示

 ...

 $(MODEL_DIR)/2001.model : $(DATA_DIR)/2000.dat
    python fit.py --year 2001 --data-dir $(DATA_DIR) --output-dir $(MODEL_DIR)

 $(MODEL_DIR)/2002.model : $(DATA_DIR)/2000.dat $(DATA_DIR)/2001.dat 
    python fit.py --year 2002 --data-dir $(DATA_DIR) --output-dir $(MODEL_DIR)

 $(MODEL_DIR)/2003.model : $(DATA_DIR)/2000.dat $(DATA_DIR)/2001.dat $(DATA_DIR)/2002.dat 
    python fit.py --year 2003 --data-dir $(DATA_DIR) --output-dir $(MODEL_DIR)

 $(MODEL_DIR)/2004.model : $(DATA_DIR)/2000.dat $(DATA_DIR)/2001.dat $(DATA_DIR)/2002.dat $(DATA_DIR)/2003.dat 
    python fit.py --year 2004 --data-dir $(DATA_DIR) --output-dir $(MODEL_DIR)

 ...

这基本上指定了一年的模型取决于已创建的前几年的数据。

我想要一个更简单的基于模式的规则,以减少复制粘贴错误的发生。我试过了

$(MODEL_DIR)/%.model : $(foreach num,$(shell seq 2000 %),$(DATA_DIR)/$(num).dat) 
    python fit.py --year $* --data-dir $(DATA_DIR) --output-dir $(MODEL_DIR)

但是我得到了错误

seq: invalid floating point argument: %

表示通配符未在shell命令中展开。

您非常接近,但是在将模式规则与目标匹配之前扩展了此类函数调用,因此%没有价值可以提供给seq。在先决条件列表中进行这种计算的方法是使用 secondary expansion,并用额外的 '$' 转义每个变量以防止它在第一轮中被扩展:

.SECONDEXPANSION:
$(MODEL_DIR)/%.model : $$(foreach num,$$(shell seq 2000 %),$(DATA_DIR)/$$(num).dat)
    ...

最后,请注意 seq 将给出所有年份 并包括 型号的年份,因此我们必须删除最后一个先决条件:

.SECONDEXPANSION:
$(MODEL_DIR)/%.model : $$(filter-out $$*.dat,$$(foreach num,$$(shell seq 2000 %),$(DATA_DIR)/$$(num).dat))
    ...