The following is a minimal example from something odd that was happening to me. My situation was obviously more complex than what follows, but the "misunderstanding" boils down exactly to this.
I am in a directory which contains only a file, named makefile, which is empty.
I run
make foo
and I get
make: *** No rule to make target 'foo'. Stop.
So far so good. Exactly what I was expecting.
At this point I create a file named foo
touch foo
and run the same command as before, i.e.
make foo
only that this time I get
make: Nothing to be done for 'foo'.
Well... not sure...
How can make tell me there's nothing to be done for foo if it does not have a rule for it?
I thought that maybe it's using a built-in rule, but running make -r foo gives me the same result.
How can make tell me there's nothing to be done for foo if it does not have a rule for it?
In the first place, you need to understand a subtlety of make's semantics. Although we sometimes think in terms of asking make to "build" a target, that's imprecise. We can only ever ask make to ensure that a target is [present and] up to date.
For your first example, when you ask make to ensure that target foo is present and up to date, foo does not exist, and make has no information about how to fix that to comply with your request, so it emits an error.
For your second example, when you ask make to ensure that target foo is present and up to date, foo does exist, and make has no information to indicate that it is out of date, so it has nothing to do (and it tells you so as a courtesy).
Of course, that explains only how make's behavior is consistent. It could also be consistent for make to insist on there being a rule, explicit or implicit, for each target it is asked to ensure up to date. There's no compelling answer to why make should or does choose the former style of consistency over the latter. That's just a design choice.