Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU Make for loop with two variables

Tags:

makefile

gnu

I want to write something along these lines:

$(foreach (var1, var2), ($(LIST1), $(LIST2)), cp $(var1) $(var2);)

How do I go about doing this in a GNU makefile?

like image 365
Matthew Hoggan Avatar asked Mar 08 '12 18:03

Matthew Hoggan


People also ask

Can you have two variables in a for loop?

Yes, I can declare multiple variables in a for-loop. And you, too, can now declare multiple variables, in a for-loop, as follows: Just separate the multiple variables in the initialization statement with commas. Do not forget to end the complete initialization statement with a semicolon.

Can we use 2 variables in for loop in C?

Yes, by using the comma operator. E.g. for (i=0, j=0; i<10; i++, j++) { ... }

What does += mean in Makefile?

6.6 Appending More Text to Variables Often it is useful to add more text to the value of a variable already defined. You do this with a line containing ' += ', like this: objects += another.o.

What is $$ in Makefile?

If you want a string to have a dollar sign, you can use $$ . This is how to use a shell variable in bash or sh . Note the differences between Makefile variables and Shell variables in this next example.


2 Answers

Beta's suggestion to use join is on the right track, but the problem is that it's not so easy to use it in a way that constructs a command line containing whitespace, such as the one you originally wanted:

$(foreach (var1, var2), ($(LIST1), $(LIST2)), cp $(var1) $(var2);)

because join joins words together: it was originally intended for constructing filenames. However you can play a trick; here's an example of a way to use join that gives you the output you are looking for:

$(subst ^, ,$(join $(addprefix cp^,$(LIST1)),$(patsubst %,^%;,$(LIST2))))

If you think your lists might contain ^ characters then choose something else. Let me know if you need this unpacked/explained.

like image 136
MadScientist Avatar answered Oct 18 '22 22:10

MadScientist


LIST1 := a b c
LIST2 := 1 2 3

# outside a rule:
$(foreach var1, a b c, $(foreach var2, 1 2 3, $(info $(var1)_$(var2))))

# inside a rule: first line starts with a TAB, all the rest are spaces
all:
    @for x in $(LIST1);\
    do \
      for y in $(LIST2);\
      do\
        echo $$x $$y; \
      done \
    done

(Please note that a nested loop that does cp doesn't make much sense.)

EDIT:
Well why didn't you say so?

LIST3 := $(join $(LIST1),$(LIST2))
like image 35
Beta Avatar answered Oct 18 '22 20:10

Beta