My bugbear with make (and even the better remake) is finding out why things are not happening. "No rule to make target" is such an uninformative error message. Could it not identify rules which would make the target were they not failing?
GNU Make has a number of implicit rules. A blank target rule (or no target rule) in the Makefile (or no Makefile at all!) will cause `make` to try to create the specified target `foo` from `foo.c` or `foo.cpp` (or others) if they exist. More complete explanation here:
Note: I was initially annoyed with parent's "do this and see what happens" post and its lack of substantive communication, and responded poorly. This comment is substantially edited.
Once you step off the beaten path, you find that errors from things like:
false | true
Get silently swallowed by bash (this is configurable, but the default ignores such errors). Also, the point about not noticing that a rule didn't create its target is a good one. (That behavior should be configurable; I don't think it is.)
Anyway, with -j, make is as async as pretty much anything else out there.
That one is a bit of an urban myth: old version of make used to reply "make: don't know how to make love" if you told them to make love and the Makefile in the current directory didn't have a target called "love", but GNU make, which is what you get on most systems now, has for years responded much less poetically with "make: * No rule to make target `love'. Stop."
In any case, I don't think the "make love" error message is dumb -- it's just that you can manipulate the program into saying something amusing. The message in the OP, on the other hand, seems to be the result of very confused thinking on the part of the programmer.
> The real insanity with make is that it has no interface to check whether a Makefile contains a given target.
>
> Best you can do is to run make -n target to probe, but it's possible to write Makefiles that run code even though -n is used, which will defeat such probes at distribution scale. It quickly becomes an exercise in heuristics and output parsing.
The real insanity with make is that it has no interface to check whether a Makefile contains a given target.
Best you can do is to run make -n target to probe, but it's possible to write Makefiles that run code even though -n is used, which will defeat such probes at distribution scale. It quickly becomes an exercise in heuristics and output parsing.
Hmm. `--list-rules` doesn't seem to work (in the docker version anyway), and I threw it at an absolutely awful Makefile (cyclic dependencies, variable spelling errors making them empty, several other clear problems) both before and after I rewrote the whole thing...
... and it's only complaining about targets over 5 lines long (really? some of the CLI tools I'm running take 20+ lines of flags spread out for readability, I'm not going to shrink that) and one or two missing .PHONY markers (it's correct about those). There's one fewer missing .PHONY after my rewrite.
Given the list in the rules folder, kinda seems like it doesn't check enough to be useful. As much as I would truly love a brutal make checker.
Don't know why anyone's modded you down. I was thinking that either the interpreter, e.g. ruby, or the script itself already returned a non-zero exit status and the makefile detected that. That doesn't cause make to remove the target.
$ make foo
false >foo
make: *** [foo] Error 1
$ make foo
make: `foo' is up to date.
$
I suppose they could do "cmd foo >bar || rm bar" instead of the mv I suggested. But that causes no bar to exist whereas the mv leaves the pre-build one behind.
Well, I'd be talking about things like "I'd like it to be an error if a make rule claims to make a certain dependency and it fails to do so.", like I said in the next sentence.
While we're at it, undefined variables should be errors, not turned into empty strings, and like I said, were I working with it routinely I'm sure I could come up with more. There's a lot more to make than just its shell invocations.
Furthermore, embedding shell's default error handling behavior into make isn't exactly a comforting thing. It's way quirkier than a lot of people understand, and unfortunately it all comes to the surface when people start using make. "It stops at a non-zero exit code!" is, unfortunately, far, far from the simple thing it sounds like.
And encountering the "errors? pshaw, whatever" attitude in multiple languages is precisely why I know it's such a bad idea. Were it just Perl or something, I wouldn't be able to tell if it's a bad idea or if Perl is just a bad implementation, but after the decades I've been using these languages, I've come to the conclusion it's just a bad idea everywhere I encounter it.
My make-audit tool only reports a few errors, but they are very general and apply to all rules. This is probably the best way to compare the tools. Here are the make-audit reports:
* Error: Target TARGET : unreported prerequisites: SET : The make recipe for creating TARGET is reading from the prerequisites in SET, but the makefile fails to report them as dependencies. You may want to add SET to the prerequisites of TARGET.
* Error: Target TARGET : claimed but unused prerequisites: SET : The make recipe for creating TARGET claims that it depends on SET, but the items in SET were never read. You may want to remove SET from the prerequisites of TARGET.
* Error: Target TARGET : unreported target: SET The make recipe for updating TARGET also modifies the files in SET but this is not reported. The easy solution is to use GNU make's grouped targets feature that it added in version 4.3, e.g., TARGET SET &: PREREQUISITES. There are alternative solutions.
* Error: Target TARGET : unmodified reported target: SET The make recipe for updating TARGET does not appear to actually write to TARGET. You may need to add a missing command to actually modify TARGET.
> it's incumbent upon him to clearly state what failures I will avoid
He does exactly that though? Here's a list of some of them:
Rule: "Use a strict Bash mode"
Failure(s) avoided: "your build may keep executing even if there was a failure in one of the targets."
Rule: .ONESHELL
Failure(s) avoided: assignments failing to take effect on subsequent lines ("it lets you do things like loops, variable assignments and so on in bash")
Rule: .DELETE_ON_ERROR
Failure(s) avoided: "ensures the next time you run Make, it’ll properly re-run the failed rule, and guards against broken files"
Rule: MAKEFLAGS += --warn-undefined-variables
Failure(s) avoided: avoids silent misbehavior when a variable doesn't exist ("if you are referring to Make variables that don’t exist, that’s probably wrong and it’s good to get a warning")
A while back I started an experiment/prototype called "make-audit"; this is a (draft) tool to report when an execution of GNU make reads or changes files in ways that are inconsistent with its Makefile: https://github.com/david-a-wheeler/make-audit It's nowhere ready for serious use, but it can detect the following:
* Error: Target TARGET : unreported prerequisites: SET : The make recipe for creating TARGET is reading from the prerequisites in SET, but the makefile fails to report them as dependencies. You may want to add SET to the prerequisites of TARGET.
* Error: Target TARGET : claimed but unused prerequisites: SET : The make recipe for creating TARGET claims that it depends on SET, but the items in SET were never read. You may want to remove SET from the prerequisites of TARGET.
* Error: Target TARGET : unreported target: SET The make recipe for updating TARGET also modifies the files in SET but this is not reported.
* Error: Target TARGET : unmodified reported target: SET
This is a really weird request. make won't rebuild things that haven't changed, so the default make all rule will only rebuild the things depending on mytarget. Every time you change mytarget, just run make (all) and everything that depends on mytarget (and only those things) will be rebuilt.
reply