Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order of execution in a Makefile

Tags:

makefile

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
like image 680
steffen Avatar asked Feb 01 '26 13:02

steffen


1 Answers

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

like image 75
Etan Reisner Avatar answered Feb 03 '26 08:02

Etan Reisner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!