Episode 2: make dats error message is confusing
gcapes opened this issue · comments
This lesson makes a distinction between nothing to be done
and up to date
. However, running make dats
twice in succession gives the message nothing to be done
rather than up to date
. There is however a rule to make dats
, so from what the lesson show so far, we would expect it to identify that dats
exists and doesn't need building. The behaviour for phony targets is different to what we have shown in the lesson, and is a counter intuitive.
This should at least be discussed briefly rather than glossed over.
Can anyone explain this behaviour to me, other than to say it doesn't work that way for phony targets? I'm struggling to find a good explanation to add to this episode.
I had a Google and the explanation in the comment on
makes sense in a way!
Thanks for the reply. Do you mean this comment?
"Nothing to be done" is probably more accurate from makes point of view. All it knows is dependencies. No dependency is newer than the target, so there's "nothing to be done".
Doesn't this contradict the SWC lesson, which explains that "nothing to be done" would mean there is no rule to build the target?
Given there is a rule to build the targets I would expect a return message for make dats
to say either that dats
is up to date, or that isles.dat
and abyss.dat
referred to by the phony target "dats" are up to date.
It's not a core learning objective, but given we're covering it, I would like to present it in a clear way.
At the moment, the best I can come up with is
The distinction between "nothing to be done" and "up to date" only applies to explicit targets. If a phony target is up to date, Make returns the message "nothing to be done".
Sorry, I meant the explanation in the Answer by Eric Melski:
The chief difference is in whether [...]make has a rule to build the target or not.
If there is no rule for the target, but the target exists, then [...]make will say, "Nothing to be done", as in, "I don't know how to update this thing, but it already exists, so I guess there's nothing to be done."
If there is a rule, but the target is already up-to-date, then [...]make will say, "is up to date", as in, "I do have instructions for updating this thing, but it appears to already be up-to-date, so I'm not going to do anything."
Ok, but that doesn't clarify any further. That reiterates the callout in the make-novice lesson. My confusion is this:
dats
is a phony target, but there are rules to build its dependencies (isles.dat and abyss.dat). I equate this with there being a rule to makedats
. As such the message should betarget 'dats' is up to date
, but instead we getnothing to be done
. We have agreed thatnothing to be done
means there is no rule to build the target, yet there is a rule to build the target.
This doesn't look to be addressed anywhere.
Sorry, I see what you mean now!
I wouldn't equate the existence of a .PHONY
target called dats
with "there being a rule to make dats
". Rather, I view it as "there is a rule called dats
whose actions are always invoked".
I tried the following scenarios:
dats
has an action:
dats :
@echo "Called dats"
y :
touch y
z :
touch z
$ make dats
Called dats
$ make dats
Called dats
$ mkdir dats
$ make dats
make: `dats' is up to date.
$ rmdir dats
Add .PHONY : dats
and rerun:
$ make dats
Called dats
$ make dats
Called dats
$ mkdir dats
$ make dats
Called dats
$ rmdir dats
dats
has an action and dependencies:
dats : y z
@echo "Called dats"
y :
touch y
z :
touch z
$ make dats
touch y
touch z
Called dats
$ make dats
Called dats
$ mkdir dats
$ make dats
make: `dats' is up to date.
$ rmdir dats
$ rm y z
Add .PHONY : dats
and rerun:
$ make dats
touch y
touch z
Called dats
$ make dats
Called dats
$ mkdir dats
$ make dats
Called dats
$ rmdir dats
$ rm y z
The behaviour is the same as the foregoing.
dats
has dependencies only:
dats : y z
y :
touch y
z :
touch z
$ make dats
touch y
touch z
$ make dats
make: Nothing to be done for 'dats'.
$ mkdir dats
$ make dats
make: Nothing to be done for 'dats'.
$ rmdir dats
$ rm y z
Add .PHONY : dats
and rerun:
$ make dats
touch y
touch z
$ make dats
make: Nothing to be done for 'dats'.
$ mkdir dats
$ make dats
make: Nothing to be done for 'dats'.
$ rmdir dats
$ rm y z
In this scenario, the presence of .PHONY
seems to make no difference as following behaviour is the same regardless of whether it's .PHONY
or not:
$ make dats
touch y
touch z
$ make dats
make: Nothing to be done for 'dats'.
$ rm y
$ make dats
touch y
$ mkdir dats
$ make dats
make: Nothing to be done for 'dats'.
$ rm y
$ make dats
touch y
$ make dats
make: Nothing to be done for 'dats'.
It looks to me like it is the presence/absence of actions that determines what message is displayed. From the above scenarios, for rules that do not build files/directories with the same name as the target of the rule (e.g. dats
):
- If the rule has actions then:
- Repeated invocations of the rule cause its actions to be repeatedly called.
- If a file/directory already exists with the same name as the target of the rule, then Make will display
make: 'dats' is up to date.
- Declaring the target of the rule as
.PHONY
(e.g..PHONY : dats
) ensures that its actions are always run regardless of whether a file/directory already exists with the same name as the target.
- If the rule has no actions then:
- If the rule has dependencies which need rebuilt, then these are rebuilt.
- If the rule has dependencies which are up-to-date, then Make will display
make: Nothing to be done for 'dats'
, since the rule's dependencies have been rebuilt and it has no actions.
The existing call-out could be changed to something like:
up to date
means that the Makefile has a rule with one or more actions whose target is the name of a file/directory and the file/directory is up to date.Nothing to be done
means that the file/directory exists but that:- Either the Makefile has no rule for it.
- Or, the Makefile has a rule for it but that rule has no actions.
Then a new call-out added explaining in more detail the behaviour of .PHONY
rules, as above.
Excellent! That's clear now. I'll make the necessary changes to the lesson. Thanks!
:-)
I think I'll add the discussion of the.PHONY
rules as a link to this issue in the discussion rather than as a callout in the lesson. It's rather too detailed a discussion to have in episode 2 and would distract from learning how to use Make.
Thanks again for your help!