makefilegnu-make

Why doesn't make fail if a file exists but there is no rule for it


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.


Solution

  • 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.