help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

old style phoney target syntax (part 2)


From: Richard McLean
Subject: old style phoney target syntax (part 2)
Date: Sat, 3 Aug 2013 09:52:35 +1000

Further to my last question (see below)...

Thinking about it a bit more, I think the phrase "make imagines this target to 
have been updated whenever its rule is run"  (Make Manual Section 4.7 Rules 
without Recipes or Prerequisites - included below) may be another way of saying 
that when a target has no prerequisites and no recipe, then make does NOT 
perform a search for an implicit rule to build the target.

If that is the case then then the following 3 code snippets would be exactly 
(functionally) equivalent :

clean: FORCE
        -rm -f $(objects)
FORCE:


and 

clean: FORCE
        -rm -f $(objects)
FORCE: ;

and

.PHONY: clean
clean:
        -rm -f $(objects)


(note semi-colon denoting empty recipe for the FORCE target in the second 
example)

Am I correct in this interpretation ?

Perhaps the 3rd example is a little more clear, and the currently recommended 
way to go, but is there any functional difference between the 3 examples ?

As far as I can see, if the "make clean" command is issued, whether or not the 
files "clean" or "FORCE" exist, the clean recipe will be run - is that correct ?

And any implicit rule that would potentially build a file called "clean" or 
"FORCE" would not be actioned.... right ?


Also, I'm still after an answer to the second unrelated question...

Can the "|" (vertical bar) operator and order-only-prerequisites play any roles 
in pattern rules, or are they strictly related to explicit rules ?

In other words, can a pattern rule include order-only pre-requisites ?

I cannot immediately see a reason why they should, but I'm just trying to see 
what's acceptable syntax.



Cheers


Richard



<<<<<Previous Post>>>>>
Hello,

I'm pretty new to GNU Make and am just trying to get a few things straight in 
my head so please bear with me if these questions sound a bit "basic"...

I've read the Make Manual, and the O'Reilly book, as well as several other 
references I have found.

I'm trying to clarify some things about "old style phony target syntax", mainly 
to give me a better understanding as to what's actually going on.

I concede that using the .PHONY directive is the best way to go in a modern GNU 
makefile, so please don't suggest I just do that, as that's not really the aim 
of my question.

Consider the makefile code :

clean:
        -rm -f $(objects)


Assuming that "clean" does NOT exist as a filename, then my understanding is 
that "clean" will always be regarded as out-of-date, and "make clean" will 
always result in the recipe being run.
If "clean" does exist as a file, then the recipe will never be run, as without 
any prerequisites, the mere existence of the file will be enough for make to 
believe it is up-to-date.
Of course, specifying the clean target as .PHONY, assures the same outcome even 
if there does exist a file named clean :

.PHONY: clean
clean:
        -rm -f $(objects)

And since this causes make to skip any implicit rule search to possibly make 
the "clean" file from some other file, this code is more efficient.

In some older references and also in several sections of the make manual, an 
older style of phony target syntax is given, using the "FORCE" target :

clean: FORCE
        -rm -f $(objects)
FORCE:

My understanding here is that since "clean" and "FORCE" do not exist as 
filenames, make will always consider them out-of-date.
Issuing "make FORCE" on the command line will cause the makefile to be read and 
parsed, the DAG built, the target (FORCE) and all it's pre-requisites checked 
for existence/out-of-dateness.
In this case, as the file "FORCE" doesn't exist, the end result will be that 
the FORCE recipe (no recipe) will be executed and will result in a no-op 
(assuming the parsing of the makefile has no side effects).
In addition, running "make clean" will force the clean recipe to be executed, 
even if "clean" exists as a filename, as the out-of-date FORCE target is a 
normal (non-order-only) prerequisite of "clean".
I'm not completely sure what is being achieved here, over and above my first 
example with just the clean target ?
In some ways we are just adding another layer of files that aren't supposed to 
exist.
I can see that if we used the FORCE target in many similar targets, then this 
could minimise the number of files for which we must ensure non-existence (ie. 
FORCE).
Is that the main aim of this sort of code ?

Also, would it be slightly better syntax to supply the FORCE target with an 
empty recipe (trailing semicolon) to protect it from any match anything 
implicit rules ?

clean: FORCE
        -rm -f $(objects)
FORCE: ;

(since we now must ensure FORCE doesn't exist as a filename, we must also make 
sure that make doesn't find a way to make it)

In the Make Manual (Section 4.7 Rules without Recipes or Prerequisites) it says 
:

If a rule has no prerequisites or recipe, and the target of the rule is a 
nonexistent file, then make imagines this target to have been updated whenever 
its rule is run. This implies that all targets depending on this one will 
always have their recipe run.

I find the phrase "make imagines this target to have been updated whenever its 
rule is run" a bit confusing for some reason.

So is it better to supply the FORCE target with no recipe or an empty recipe ?


Also, as a completely unrelated question....

Can the "|" (vertical bar) operator and order-only-prerequisites play any roles 
in pattern rules, or are they strictly related to explicit rules ?

In other words, can a pattern rule include order-only pre-requisites ?

I cannot immediately see a reason why they should, but I'm just trying to see 
what's acceptable syntax.



Cheers and Thanks in Advance



Richard
P.S. please point out any errors in my summary of what I think is going on - if 
my logic is flawed I would like to know about it


<<<<<<relevant excerpts from Make Manual>>>>>>
3.6 Overriding Part of Another Makefile

Sometimes it is useful to have a makefile that is mostly just like another 
makefile. You can often use the ‘include’ directive to include one in the 
other, and add more targets or variable definitions. However, it is illegal for 
two makefiles to give different recipes for the same target. But there is 
another way.

In the containing makefile (the one that wants to include the other), you can 
use a match-anything pattern rule to say that to remake any target that cannot 
be made from the information in the containing makefile, make should look in 
another makefile. See Pattern Rules, for more information on pattern rules.

For example, if you have a makefile called Makefile that says how to make the 
target ‘foo’ (and other targets), you can write a makefile called GNUmakefile 
that contains:

    foo:
            frobnicate > foo

    %: force
            @$(MAKE) -f Makefile $@
    force: ;

If you say ‘make foo’, make will find GNUmakefile, read it, and see that to 
make foo, it needs to run the recipe ‘frobnicate > foo’. If you say ‘make bar’, 
make will find no way to make bar in GNUmakefile, so it will use the recipe 
from the pattern rule: ‘make -f Makefile bar’. If Makefile provides a rule for 
updating bar, make will apply the rule. And likewise for any other target that 
GNUmakefile does not say how to make.

The way this works is that the pattern rule has a pattern of just ‘%’, so it 
matches any target whatever. The rule specifies a prerequisite force, to 
guarantee that the recipe will be run even if the target file already exists. 
We give the force target an empty recipe to prevent make from searching for an 
implicit rule to build it—otherwise it would apply the same match-anything rule 
to force itself and create a prerequisite loop!


4.6 Phony Targets

A phony target is one that is not really the name of a file; rather it is just 
a name for a recipe to be executed when you make an explicit request. There are 
two reasons to use a phony target: to avoid a conflict with a file of the same 
name, and to improve performance.

If you write a rule whose recipe will not create the target file, the recipe 
will be executed every time the target comes up for remaking. Here is an 
example:

    clean:
            rm *.o temp

Because the rm command does not create a file named clean, probably no such 
file will ever exist. Therefore, the rm command will be executed every time you 
say ‘make clean’. The phony target will cease to work if anything ever does 
create a file named clean in this directory. Since it has no prerequisites, the 
file clean would inevitably be considered up to date, and its recipe would not 
be executed. To avoid this problem, you can explicitly declare the target to be 
phony, using the special target .PHONY (seeSpecial Built-in Target Names) as 
follows:

    .PHONY : clean

Once this is done, ‘make clean’ will run the recipe regardless of whether there 
is a file named clean.

Since it knows that phony targets do not name actual files that could be remade 
from other files, make skips the implicit rule search for phony targets (see 
Implicit Rules). This is why declaring a target phony is good for performance, 
even if you are not worried about the actual file existing.

Thus, you first write the line that states that clean is a phony target, then 
you write the rule, like this:

    .PHONY: clean
    clean:
            rm *.o temp

Another example of the usefulness of phony targets is in conjunction with 
recursive invocations of make (for more information, see Recursive Use of 
make). In this case the makefile will often contain a variable which lists a 
number of subdirectories to be built. One way to handle this is with one rule 
whose recipe is a shell loop over the subdirectories, like this:

    SUBDIRS = foo bar baz

    subdirs:
            for dir in $(SUBDIRS); do \
              $(MAKE) -C $$dir; \
            done

There are problems with this method, however. First, any error detected in a 
submake is ignored by this rule, so it will continue to build the rest of the 
directories even when one fails. This can be overcome by adding shell commands 
to note the error and exit, but then it will do so even if make is invoked with 
the -k option, which is unfortunate. Second, and perhaps more importantly, you 
cannot take advantage of make's ability to build targets in parallel (see 
Parallel Execution), since there is only one rule.

By declaring the subdirectories as phony targets (you must do this as the 
subdirectory obviously always exists; otherwise it won't be built) you can 
remove these problems:

    SUBDIRS = foo bar baz

    .PHONY: subdirs $(SUBDIRS)

    subdirs: $(SUBDIRS)

    $(SUBDIRS):
            $(MAKE) -C $@

    foo: baz

Here we've also declared that the foo subdirectory cannot be built until after 
the baz subdirectory is complete; this kind of relationship declaration is 
particularly important when attempting parallel builds.

A phony target should not be a prerequisite of a real target file; if it is, 
its recipe will be run every time make goes to update that file. As long as a 
phony target is never a prerequisite of a real target, the phony target recipe 
will be executed only when the phony target is a specified goal (see Arguments 
to Specify the Goals).

Phony targets can have prerequisites. When one directory contains multiple 
programs, it is most convenient to describe all of the programs in one makefile 
./Makefile. Since the target remade by default will be the first one in the 
makefile, it is common to make this a phony target named ‘all’ and give it, as 
prerequisites, all the individual programs. For example:

    all : prog1 prog2 prog3
    .PHONY : all

    prog1 : prog1.o utils.o
            cc -o prog1 prog1.o utils.o

    prog2 : prog2.o
            cc -o prog2 prog2.o

    prog3 : prog3.o sort.o utils.o
            cc -o prog3 prog3.o sort.o utils.o

Now you can say just ‘make’ to remake all three programs, or specify as 
arguments the ones to remake (as in ‘make prog1 prog3’). Phoniness is not 
inherited: the prerequisites of a phony target are not themselves phony, unless 
explicitly declared to be so.

When one phony target is a prerequisite of another, it serves as a subroutine 
of the other. For example, here ‘make cleanall’ will delete the object files, 
the difference files, and the file program:

    .PHONY: cleanall cleanobj cleandiff

    cleanall : cleanobj cleandiff
            rm program

    cleanobj :
            rm *.o

    cleandiff :
            rm *.diff


4.7 Rules without Recipes or Prerequisites

If a rule has no prerequisites or recipe, and the target of the rule is a 
nonexistent file, then make imagines this target to have been updated whenever 
its rule is run. This implies that all targets depending on this one will 
always have their recipe run.

An example will illustrate this:

    clean: FORCE
            rm $(objects)
    FORCE:

Here the target ‘FORCE’ satisfies the special conditions, so the target clean 
that depends on it is forced to run its recipe. There is nothing special about 
the name ‘FORCE’, but that is one name commonly used this way.

As you can see, using ‘FORCE’ this way has the same results as using ‘.PHONY: 
clean’.

Using ‘.PHONY’ is more explicit and more efficient. However, other versions of 
make do not support ‘.PHONY’; thus ‘FORCE’ appears in many makefiles. See Phony 
Targets.

5.9 Using Empty Recipes

It is sometimes useful to define recipes which do nothing. This is done simply 
by giving a recipe that consists of nothing but whitespace. For example:

    target: ;

defines an empty recipe for target. You could also use a line beginning with a 
recipe prefix character to define an empty recipe, but this would be confusing 
because such a line looks empty.

You may be wondering why you would want to define a recipe that does nothing. 
The only reason this is useful is to prevent a target from getting implicit 
recipes (from implicit rules or the .DEFAULT special target; see Implicit Rules 
and see Defining Last-Resort Default Rules).

You may be inclined to define empty recipes for targets that are not actual 
files, but only exist so that their prerequisites can be remade. However, this 
is not the best way to do that, because the prerequisites may not be remade 
properly if the target file actually does exist. See Phony Targets, for a 
better way to do this.

_______________________________________________
Help-make mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/help-make

reply via email to

[Prev in Thread] Current Thread [Next in Thread]