Please consider the following setup:
$ ls
base.mk file.ext Makefile
$ cat Makefile
include base.mk
algorithm = another-alg
$ cat base.mk
source = file.ext
binary = $(algorithm)
algorithm = the-alg
.bin: $(binary)
touch .bin
$(binary): $(source)
echo "compiling..." > $(binary)
If I run make .bin
, I get the expected output, however, if I run make .bin
again, the recipe runs again. I expect it to run once, and then, upon a second call, tell me that there is nothing to do for .bin
. Why is not this the case?
$ make .bin
echo "compiling..." > another-alg
touch .bin
$ make .bin
echo "compiling..." > another-alg
touch .bin
I can see that if I do not re-assign algorithm
, I get the expected behavior, but including the base makefile and adjusting variables is the workflow that I devised for the creation of many similar projects that share common logic (in base.mk
)
Please consider the following setup:
$ ls
base.mk file.ext Makefile
$ cat Makefile
include base.mk
algorithm = another-alg
$ cat base.mk
source = file.ext
binary = $(algorithm)
algorithm = the-alg
.bin: $(binary)
touch .bin
$(binary): $(source)
echo "compiling..." > $(binary)
If I run make .bin
, I get the expected output, however, if I run make .bin
again, the recipe runs again. I expect it to run once, and then, upon a second call, tell me that there is nothing to do for .bin
. Why is not this the case?
$ make .bin
echo "compiling..." > another-alg
touch .bin
$ make .bin
echo "compiling..." > another-alg
touch .bin
I can see that if I do not re-assign algorithm
, I get the expected behavior, but including the base makefile and adjusting variables is the workflow that I devised for the creation of many similar projects that share common logic (in base.mk
)
1 Answer
Reset to default 3The answer is pretty clear in the output you provide.
When the rule is defined, the value of the variables is this:
binary = $(algorithm)
algorithm = the-alg
so when make expands the rule:
$(binary): $(source)
echo "compiling..." > $(binary)
The reference $(binary)
expands to $(algorithm)
which expands to the-alg
. So the rule that make internalizes is:
the-alg: file.ext
echo "compiling..." > $(binary)
When make is going to build the target the-alg
, it expands the recipe. By the time that happens the file has been included and now the value of the relevant variables is:
binary = $(algorithm)
algorithm = another-alg
So when make expands the recipe, it will run the command you see in the output:
echo "compiling..." > another-alg
This recipe doesn't build the target that make expects (the-alg
); since that target is not updated the next time you run make, make sees that it's still not up to date and builds it again.
Every recipe you write (other than phony recipes) should use the automatic variable $@
as the name of the target built. That way you always know that your recipe is building the target that make expects. It should be:
$(binary): $(source)
echo "compiling..." > $@
You didn't describe the behavior you are actually hoping to achieve.
binary
andalgorithm
? – Barmar Commented Mar 4 at 20:58