1

I have a top-level makefile which is auto-generated by my custom build tool from various configuration files: I would like the makefile to be able to re-make itself when it is out of date. To do this, I have the following rule:

<absolute path to makefile>: <list> <of> <configuration> <files>
    @echo "Rebuilding top-level makefile"
    @<invoke my build tool>

I'm using GNU Make 4.3 which claims to support this, as detailed here, where it claims that "after all makefiles have been checked, if any have actually been changed, make starts with a clean slate and reads all the makefiles over again."

The problem I have is that although this rule is invoked correctly (but not implicitly, I actually need another PHONY default goal which has the makefile as a prerequesite), it seems that make does not reload the makefile even after it has been changed. I note that make does correctly reload included makefiles when they have a recipe and are out of date: it's only this top-level makefile which has the problem.

The effect of this is that the other rules in the file are out of date, and changes are only reflected in the subsequent invocation of make.

My current solution is to have the makefile recipe return a non-zero exit code and echo a warning asking the user to re-run make: I tried using ($error _), but this didn't have the intended effect.

It seems GNU Make claims to support this use-case, so I presume I must be doing something wrong here?

  • Are you running this on Windows by any chance? – HolyBlackCat Oct 17 '20 at 16:37
  • @HolyBlackCat Nope, Arch. I managed to fix it per my answer below: seems GNU Make can't tell that the absolute path to the makefile in the rule actually points to the makefile it has loaded by itself. – denotational Oct 17 '20 at 16:39

1 Answers1

1

It seems that make (or at least GNU Make 4.3) cannot recognise that the absolute path which serves as the target of the rule is actually referring to makefile it has already loaded automatically: it's just doing a naive textual comparison rather than resolving the paths properly.

Changing the rule to:

Makefile: <list> <of> <configuration> <files>
    @echo "Rebuilding top-level makefile"
    @<invoke my build tool>

fixed the problem.

I think this should probably be treated as a bug in GNU Make since it does not appear to be documented.

  • It's not that it "cannot handle it". It's that make doesn't realize that it's the same file. Make uses simple text comparison to decide whether targets match or not. If you run `make -f ` then make will understand that your target `` is the same thing and it will re-exec after rebuilding it. If you run `make` (so that the default `Makefile` is read), then make won't realize that `Makefile` and `` are the same file and it won't re-exec after the latter is rebuilt. – MadScientist Oct 18 '20 at 02:49
  • @MadScientist The fact that make uses naive text comparison to identify targets is precisely *why* make cannot handle this situation; I don't think my statement is incorrect? I'm quite surprised that it can't unify file paths correctly, however, and I haven't been able to find any mention of this in the documentation; it seems significant enough a deviation in expected behaviour that I think it should either be treated as a bug, or documented explicitly. – denotational Oct 18 '20 at 13:29
  • As I said, it _CAN_ handle absolute paths. You just have to provide the same filename on the command line as appears in the makefile. So the statement "cannot handle absolute paths to the makefile" is, at least, misleading and I was clarifying the real situation in my comment. This behavior (textual comparison of targets) is true for all targets, not just targets that rebuild makefiles: there's nothing special about the latter. – MadScientist Oct 18 '20 at 15:05
  • 1
    @MadScientist I don't agree with this assessment. It strikes me that *sane* behaviour would be for make to recognise that the absolute path the file points to the very same makefile which has been automatically selected through invoking make without the `-f` flag; the fact that make is _universally_ using textual comparison of targets doesn't to make this behaviour any more sane in my opinion, at least whilst it remains undocumented. – denotational Oct 18 '20 at 18:27
  • I'm not sure which part of my assessment you don't agree with. To the best of my knowledge everything I said was a fact. I offered no opinions as to whether the current behavior is right or wrong, or good or bad. – MadScientist Oct 18 '20 at 19:27
  • Still without offering an opinion, I will say that telling whether two paths point to the same file, especially in a portable manner (GNU make runs on POSIX, Windows, DOS, VMS systems at least) is not as clear-cut as it may seem. What about symbolic links? Is the link the same thing as the file? What if it's not the file but a directory that's the link? What about hard links? I don't suggest that these questions couldn't be answered, just that it's more complex than it might seem at first. – MadScientist Oct 18 '20 at 19:29