Iterate over a list of directories in a Makefile

I would like to complete the task in several directories, but still have not found makefile-like. I know this is a frequently asked question, and I know how to solve it for sub-makfiles and so on, but I'm looking for something simpler.

Instead of doing

copy: cd module1 && mkdir foo cd module2 && mkdir foo cd module3 && mkdir foo 

I would like to have something like

 directories = module1 module2 module3 copy: $(directories) cd $< && mkdir foo 

but this does not work, as the receiver is called only once with the first directory. I came up with this solution that works, but probably not in the style of Make files:

 directories = module1 module2 module3 copy: for d in $(directories); do cd $$d && mkdir foo && cd ..; done 

How can I make it more beautiful?

+7
source share
2 answers

There are many ways to do this.

You can do what Andrew suggests without hard coding the prefix:

 directories = module1 module2 module2 %/foo: ; mkdir -p -- " $@ " copy: $(addsuffix /foo,$(directories)) 

which gives

 $ make -n copy mkdir -p -- "module1/foo" mkdir -p -- "module2/foo" mkdir -p -- "module3/foo" 

You can also generate a copy target from the makefile:

 directories = module1 module2 module2 define copy-target copy:: ; cd $1 && mkdir foo endef $(foreach dir,$(directories),$(eval $(call copy-target,$(dir)))) 

This gives:

 $ make -n copy cd module1 && mkdir foo cd module2 && mkdir foo cd module3 && mkdir foo 

You can also generate commands, not the goal:

 directories = module1 module2 module2 copy: ; $(foreach dir,$(directories),(cd $(dir) && mkdir foo) &&) : 

that leads to

 $ make -n copy (cd module1 && mkdir foo) && (cd module2 && mkdir foo) && (cd module3 && mkdir foo) && : 
+6
source

In Makefiles, when you want to create a file, create a rule with the file name as the target and let the command create the target file.

 copy: module1/foo module2/foo module3/foo module%/foo: mkdir $@ 

If you want to parameterize this a bit to avoid duplication, you can also write something like

 MODULE_NUMBERS = 1 2 3 copy: ${MODULE_NUMBERS:%=module%/foo} module%/foo: mkdir $@ 
+2
source

All Articles