Casey
Casey

Reputation: 487

How to include wildcard pattern in foreach statement of Makefile

I have some rules in a makefile like below

 ...

 $(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)

 ...

This basically specifies that the model for a year depends on data from previous years having been created.

I would like a simpler pattern based rule to make this less prone to copy paste errors. I tried

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

But I get the error

seq: invalid floating point argument: %

indicating that the wildcard is not being expanded in the shell command.

Upvotes: 1

Views: 357

Answers (1)

Beta
Beta

Reputation: 99094

You're very close, but such function calls are expanded before matching the pattern rule to a target, so % has no value to be fed to seq. The way to do this kind of calculation in the prerequisite list is by using secondary expansion, and escaping each variable with an extra '$' to prevent it being expanded in the first round:

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

Finally, notice that seq will give all years up to and including the year of the model, so we must remove the last prerequisite:

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

Upvotes: 2

Related Questions