I have a file A and want to create a file B from it, replacing same variables during the make process.
The variable names are stored in vars.
A minimal Makefile looks like this:
vars = var1 var2 var3
var1 = AAA
var2 = BBB
var3 = CCC
default:
cp A B
$(foreach var,$(vars),$(shell sed -i "s/$(var)/\"$(value $(var))\"/g" B))
And file A looks like this:
blabla var1 blabla
blabla var2 blabla
blabla var3 blabla
When I execute make, I get the output
sed: can't read B: No such file or directory
sed: can't read B: No such file or directory
sed: can't read B: No such file or directory
cp A B
The copy statement is executed after the foreach! I can correct this by setting up a seperate target, say copy, only place the copy command in there and make default depend on copy.
But why??? Why is the order of execution within a rule not strict?
What am I missing?
ps:
$ make --version
GNU Make 4.0
Built for x86_64-pc-linux-gnu
$(shell) is a make function. It executes at make time (in this case at recipe expansion time). That happens before the recipe is executed.
The $(foreach) happens at that time also.
You just don't want $(shell) here at all. You want the $(foreach) to output a single (long) shell recipe line that make can execute normally. (Make sure to terminate the output command with a ; to make it shell-legal.)
default:
cp A B
$(foreach var,$(vars),sed -i 's/$(var)/"$(value $(var))"/g' B;)
I also switched to single quotes to avoid the need to escape and because there isn't anything in that string that the shell needs to expand. make does all the variable expansions here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With