Iterating over lists in Makefiles?
Makefiles are essentially declarative in nature, so I don't think that make itself provides what you want. However, you seem to be wanting to associate some string values with specific targets, so maybe the Target specific variable values feature of GNU make will be of interest. This is an extract from the manual:
There is one more special feature of
target-specific variables: when you
define a target-specific variable,
that variable value is also in effect
for all dependencies of this target
(unless those dependencies override it
with their own target-specific
variable value). So, for example, a
statement like this:
prog : CFLAGS = -g
prog : prog.o foo.o bar.o
will set
CFLAGS
to-g
in the command
script forprog
, but it will also
setCFLAGS
to-g
in the command
scripts that create prog.o, foo.o,
and bar.o, and any command scripts
which create their dependencies.
If you haven't already read it, the GNU make manual is pretty damn good.
Edit: To do what you asked about in your comment:
dog: ANIMAL=dog.c BULLY=pull_tail SOUND=bark
use:
dog: ANIMAL=dog.c
dog: BULLY=pull_tail
dog: SOUND=bark
Iterating over lists in Makefiles - revisited
It's because you're stringing together print_tmp
blocks on a single line-- but the blocks have internal line breaks. Consider:
partition_tmp:
$(foreach color, red blue, \
$(call print_tmp, $(color)) \
)
define print_tmp
@echo first $(1)
endef
The foreach
evaluates to @echo first red @echo first blue
, which is then executed as a shell command and produces:
first red @echo first blue
Now add another line to the macro:
partition_tmp:
$(foreach color, red blue, \
$(call print_tmp, $(color)) \
)
define print_tmp
@echo first $(1)
@echo second $(1)
endef
Now the foreach
evaluates to
@echo first red
@echo second red @echo first blue
@echo second blue
which produces:
first red
second red @echo first blue
second blue
To correct the problem, just add a blank line:
define print_tmp
@echo in print_tmp
@echo set_global -name PARTITION_NAME $(1)
@echo set_global -color PARTITION_COLOR $(2) -name PARTITION_NAME $(1)
endef
Iterating through a list of directories in a Makefile
There are lots of ways of doing this.
You can do what Andrew suggests without hard-coding a 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 the 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 could also generate the commands, not the target:
directories = module1 module2 module2
copy: ; $(foreach dir,$(directories),(cd $(dir) && mkdir foo) &&) :
which results in
$ make -n copy
(cd module1 && mkdir foo) && (cd module2 && mkdir foo) && (cd module3 && mkdir foo) && :
How to generate targets in a Makefile by iterating over a list?
Use text-transforming functions. With patsubst
you can make quite general transformations. For constructing filenames, addsuffix
and addprefix
are both convenient.
For the rules, use pattern rules.
The overall result might look something like this:
LIST = 0 1 3 4 5
targets = $(addprefix rambo, $(LIST))
all: $(targets)
$(targets): rambo%: rambo%.sh
sh $<
Iterating over a list in a Makefile and getting both values and indexes
There are several ways to do this, none of them very clean (which is a strong hint that you're trying to do something that isn't really suited to Make), and your particular case may require special handling, but here goes:
OBJECTS = foo bar baz
NLIST = $(shell for x in {1..$(words $(OBJECTS))}; do echo $$x; done)
LIST = $(foreach x,$(NLIST), do_something_with_$(x)_and_$(word $(x),$(OBJECTS)))
How to create a multiple recipes by looping over a Makefile list?
You would use pattern rules most likely:
apply: stage process
var := 2000 2001 2002
process: $(foreach V,$(var),output/$V/config.json)
stage: $(foreach V,$(var),output/$V/esc)
output/%/config.json: dir/level/%/config.json
cp $< $@
output/%/esc : dir/common/%/esc
mkdir -p $(@D)
cp $< $@
Iterating through makefile argument list
This can't be right:
+uvm_set_config_int=*,A,3
+uvm_set_config_int=*,B,4
+uvm_set_config_int=*,C,5
because that just sets, then overrides, the single value +uvm_set_config_int
. At the end the variable +uvm_set_config_int
will contain the single value *,C,5
since that's the last assignment. Maybe you mean to use uvm_set_config_int += ...
in each of the above, to append to the existing value?
I really don't understand what you're trying to accomplish here.
However, here's an example of how to do what you've asked, even though it doesn't seem to make much sense:
c = ,
$(foreach X,$(subst $c, ,$(cfg)),$(eval +uvm_set_config_int=*,$(subst =,$c,$X)))
Since commas are special to make functions we have to hide them behind a variable $c
above. The first subst
turns commas into spaces, since that's what make uses to delimit words. The second converts =
to comma so you can change A=3
to A,3
etc. The eval
evaluates the text given as a makefile line.
Parallel iteration over lists in makefile or CMake file
Here you go:
set(list1 1 2 3 4 5)
set(list2 6 7 8 9 0)
list(LENGTH list1 len1)
math(EXPR len2 "${len1} - 1")
foreach(val RANGE ${len2})
list(GET list1 ${val} val1)
list(GET list2 ${val} val2)
message(STATUS "${val1} ${val2}")
endforeach()
Related Topics
Bash: Get List of Commands Starting with a Given String
Injecting Code into Executable at Runtime
How to Remove Warning About Storing Unencrypted Password After Committing File in Svn
Retrieve Plain Text Script from Compiled Bash Script
How to Specify Time in Cron Considering Year
Accessing Linux /Dev/Usb as Standard Files to Communicate with Usb Device
Dhcp Server to Redirect Any Url to Landing Page
How to Combine Two Variable Column-By-Column in Bash
Bash Printf %Q Invalid Directive
Linux Write Sys Call Using String on Stack
Prepend Data from One File to Another
Linux, Print All Lines in a File, Not Starting With
Installing G++ on Windows Subsystem for Linux
What Does This Command Do? "Exec Bash -L"
How to Change Version String of the Kernel
Emacs, Linux and International Keyboard Layouts
Mmap: Will the Mapped File Be Loaded into Memory Immediately
Is There Any Significant Difference Between Tcp_Cork and Tcp_Nodelay in This Use-Case