[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
old style phoney target syntax (small correction)
From: |
Richard McLean |
Subject: |
old style phoney target syntax (small correction) |
Date: |
Sat, 3 Aug 2013 21:40:38 +1000 |
One small adjustment...
In my last post, the sentence :
"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
?"
should have read :
"As far as I can see, if the "make clean" command is issued, whether or not the
file "clean" exists, the clean recipe will be run, as long as the file "FORCE"
does not exist - is that correct ?"
So the las email should have read as follows :
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
file "clean" exists, the clean recipe will be run as long as the file "FORCE"
does not exist - 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
_______________________________________________
Help-make mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/help-make
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- old style phoney target syntax (small correction),
Richard McLean <=