Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU make always considers a non-file target as being remade (possible bug?)

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

like image 841
drwatsoncode Avatar asked Dec 21 '17 20:12

drwatsoncode


1 Answers

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.

like image 78
Oliver Charlesworth Avatar answered Sep 27 '22 23:09

Oliver Charlesworth