Lately I've been trying to get into the concepts of GNU Make. While reading, I came accross a topic called Empty Target. From GNU Make manual what I got to know is
The empty target is a variant of the phony target; it is used to hold recipes for an action that you request explicitly from time to time. Unlike a phony target, this target file can really exist; but the file's contents do not matter, and usually are empty.
The purpose of the empty target file is to record, with its last-modification time, when the rule's recipe was last executed. It does so because one of the commands in the recipe is a touch command to update the target file.
From another source, I read something like this
Empty targets are similar to phony targets in that the target itself is used as a device to leverage the capabilities of make. Phony targets are always out of date, so they always execute and they always cause their dependent (the target associated with the prerequisite) to be remade. But suppose we have some command, with no output file, that needs to be performed only occasionally and we don’t want our dependents updated? For this, we can make a rule whose target is an empty file (sometimes referred to as a cookie):
prog: size prog.o $(CC) $(LDFLAGS) -o $@ $^ size: prog.o size $^ touch size
Notice that the size rule uses touch to create an empty file named size after it completes. This empty file is used for its timestamp so that make will execute the size rule only when prog.o has been updated. Furthermore, the size prerequisite to prog will not force an update of prog unless its object file is also newer.
From reading them what I understood is
For doing some hands-on, I have written two sample makefiles
with empty target use
prog: size prog.o
gcc -o $@ prog.o
size: prog.o
size $<
touch size
prog.o: prog.c
gcc -c $<
output
[sourav@localhost Practice]# make
gcc -c prog.c
size prog.o
text data bss dec hex filename
58 0 0 58 3a prog.o
touch size
gcc -o prog prog.o
[sourav@localhost Practice]# make
make: `prog' is up to date.
[sourav@localhost Practice]# touch prog.c //suppose some real change in the file
[sourav@localhost Practice]# make
gcc -c prog.c
size prog.o
text data bss dec hex filename
58 0 0 58 3a prog.o
touch size
gcc -o prog prog.o
[sourav@localhost Practice]#
without empty target use
prog: prog.o
size $^
gcc -o $@ prog.o
prog.o: prog.c
gcc -c $<
output
[sourav@localhost Practice]# make
gcc -c prog.c
size prog.o
text data bss dec hex filename
58 0 0 58 3a prog.o
gcc -o prog prog.o
[sourav@localhost Practice]# make
make: `prog' is up to date.
[sourav@localhost Practice]# touch prog.c
[sourav@localhost Practice]# make
gcc -c prog.c
size prog.o
text data bss dec hex filename
58 0 0 58 3a prog.o
gcc -o prog prog.o
[sourav@localhost Practice]#
In above two different makefiles , the output for the similar condition is same. So, I'm not clear with the particular scope of use for empty targets. If they are used only to hold the timestamp, then we can achieve the same without using them . [Or is related with automatic variable $?
about which I'm yet to read in detail]. Can anyone resolve this confusion in some other wordings, possibly with some example (if I'm not asking too much)?
Thanks and Cheers!!
A simple makefile consists of “rules” with the following shape: target … : prerequisites … recipe … … A target is usually the name of a file that is generated by a program; examples of targets are executable or object files. A target can also be the name of an action to carry out, such as ' clean ' (see 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.
By default, the goal is the first target in the makefile (not counting targets that start with a period). Therefore, makefiles are usually written so that the first target is for compiling the entire program or programs they describe.
In your case you already have a target (size), which changes when one of your source file does. So in your example, gcc acts like touch. However, in your first link, if you take a look at the example:
print: foo.c bar.c
lpr -p $?
touch print
Here without touch print
, make print
will always execute lpr -p
as the print rule does not refer to a file that changes. Example with ls:
Makefile:
print: foo.c bar.c
ls $?
make print (1):
ls foo.c bar.c
bar.c foo.c
make print (2):
ls foo.c bar.c
bar.c foo.c
However, now if make print
changes the timestamp of a file renamed "print", now the rule refers to an existing file:
Makefile:
print: foo.c bar.c
ls $?
touch print
make print (1):
ls foo.c bar.c
bar.c foo.c
make print (2):
make: `print' is up to date.
because file print is more recent than foo.c and bar.c.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With