У меня есть некоторые правила в make-файле, как показано ниже.
...
$(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: %
указывает, что подстановочный знак не раскрывается в команде оболочки.





Вы очень близки, но такие вызовы функций расширяются до, сопоставляя правило шаблона с целью, поэтому % не имеет значения для передачи seq. Способ выполнить такой расчет в списке предварительных условий — использовать вторичное расширение и экранировать каждую переменную дополнительным «$», чтобы предотвратить ее расширение в первом раунде:
.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))
...
Спасибо за очень обстоятельный ответ! Это именно то, что я искал