swcarpentry / make-novice

Automation and Make

Home Page:http://swcarpentry.github.io/make-novice

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

@mikej888 ?

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 make dats. As such the message should be target 'dats' is up to date, but instead we get nothing to be done. We have agreed that nothing 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:

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

  1. 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!