URL: <https://savannah.gnu.org/bugs/?56892>
Summary: toxic combination of -include and match-anything rules Project: make Submitted by: boyski Submitted on: Sat 14 Sep 2019 08:28:32 PM UTC Severity: 3 - Normal Item Group: Bug Status: None Privacy: Public Assigned to: None Open/Closed: Open Discussion Lock: Any Component Version: 4.2.1 Operating System: POSIX-Based Fixed Release: None Triage Status: None _______________________________________________________ Details: I'm not saying this is a bug necessarily but want to submit it for some sort of resolution. I an into an infinite loop situation recently. On my advice, in a very old and complex recursive makefile suite (not of my design or under my ownership) a co-worker added a construct like the following: -include foobar.mk foobar ?= XYZ The idea is that foobar.mk would be a one-line include file which assigns the "foobar" variable if it exists and if not we fall back to the default value "XYZ". This is simple and solved his problem in unit testing but when plugged into the large old suite it resulted in an infinite loop. The reason is twofold: (a) if an included makefile doesn't exist make will try to run a recipe to create it and (b) somewhere deep in this makefile suite was a match-anything rule. From here it's obvious: make went looking for a recipe that claimed to be able to make foobar.mk, landed on the match-anything rule which does a recursive make invocation (and does not create foobar.mk), and we're off to the races with an infinite make loop. The situation is illustrated by the following test file: $ cat Makefile .PHONY: all all: @:$(info making $@) %: # @test -f nosuchfile.mk $(MAKE) $@ #-include nosuchfile.mk As it stands this works fine: $ make making all If the -include line is enabled the infinite loop happens, but if the test -f line is also uncommented things work correctly again. My first thought is that it makes no sense to invoke a recipe to create a nonexistent file included via -include because the whole point of -include is to say "I know this file may not exist and that's ok". However, the documentation says of -include that it: "... acts like include in every way except that there is no error [...] if any of the filenames [...] do not exist or cannot be remade." I guess the "or cannot be remade" is a strong implication that -include files are subject to remaking so maybe it would hard to "fix" this for compatibility reasons? And of course there's a difference between a file being out of date and not existing and it makes perfect sense to want to update a -included file if it exists. However, I still think that in the special case where foobar.mk does not exist and is included with -include the remake attempt should be elided and the inclusion silently skipped. Whether that's too much of a compatibility break is a valid question though. But even stepping back from those details, with either "include" or "-include", why should make continue if it ran the recipe and the recipe did not in fact create the file as it claimed it would? In other words, why not do a check for existence after running the remake recipe (as illustrated in the test case)? It seems to me that dying with "no such file or directory" would be preferable to allowing an infinite loop, and furthermore I think this could be added without breaking (documented) compatibility. AFAICT the manual discusses only situations where the included file "cannot be remade". Currently "remaking" seems to be a synonym for "running the recipe which claims to make it" but tightening that definition to to require that the recipe actually creates the file seems both more robust and entirely compatible, not to mention intuitive. Thus I suggest one or both of these minor tweaks: 1. Fail (with include) or continue (with -include) when, after running the remake recipe, the file does not exist. 2. Ignore (do not attempt to make) a file included by -include if it does not exist at all. But if if does exist, go ahead and try to update it. _______________________________________________________ Reply to this item at: <https://savannah.gnu.org/bugs/?56892> _______________________________________________ Message sent via Savannah https://savannah.gnu.org/ _______________________________________________ Bug-make mailing list Bug-make@gnu.org https://lists.gnu.org/mailman/listinfo/bug-make