Should Make always remake a target that has prerequisites, but does not point to a file and does not have a recipe? Or should Make only remake such targets if one or more of the prerequisites need to be remade?
For example, in the Makefile shown below, I added a target called objects
that has prerequisites, but does not point to a file.
The main target is called program
which depends on objects
(and potentially other prerequisites).
file1 file2 file3: ; touch $@
objects: file1 file2
program: objects file3 ; @echo 'Making $@'
My expectation is that when make program
is run and no file prerequisites need to be remade (i.e. file1, file2 and file3 all exist), that program
should NOT be remade.
However the actual GNU Make behavior is that the recipe for program
always runs (regardless of prerequisite files). This is because objects
is always considered to be remade, which forces any dependencies (i.e. program
) to be remade.
You can verify this by running: make --trace -d --no-builtin-rules program
and you'll see that Make always outputs "Must remake target 'objects'."
So objects
is always "remade" (even though it has no recipe) and it is always considered to be newly updated.
This is most likely because objects
does not point to a real file. But I was expecting that because it had no recipe, that it would not be remade as long as none of its prerequisites need to be remade.
Is this the expected behavior or is it a bug?
The GNU Make manual states:
If a rule has no prerequisites or recipe, and the target of the rule is a nonexistent file, then make imagines this target to have been updated whenever its rule is run. This implies that all targets depending on this one will always have their recipe run.
But that description doesn't apply to the case above, because the objects
target does have prerequisites. But perhaps the behavior is the same and the Make manual should just be updated to clarify this.
A few additional notes:
I used the recipe-after-semicolon format above to make it easier for readers to copy and paste the code. Otherwise, when copying from a webpage, the tabs would be converted to spaces in the usual tab-indented-recipe format.
Of course I know that I could just make a variable $(OBJECTS)
that
would point to a list of files and use it in place of the objects
target above. That's not really the point here.
This question also seems to involve the same behavior, but whether or not it's the expected behavior or a bug is not discussed.
I'm using GNU Make 4.2.1
I believe that the paragraph you quoted is merely recapping a particular case of behaviour that's already specified elsewhere, in order to set the scene for how FORCE
works.
Indeed a simpler, yet more general, statement is made in the previous section:
If you write a rule whose recipe will not create the target file, the recipe will be executed every time the target comes up for remaking.
And again here:
A target is out of date if it does not exist or if it is older than any of the prerequisites.
So the behaviour you're observing is entirely expected.
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