Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of 'Empty Target' in makefile

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

  • Empty target is used to maintain the timestamp
  • The content of empty target is of no interest, only the update time is.

For doing some hands-on, I have written two sample makefiles

makefile 1

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]#

makefile 2

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

like image 447
Sourav Ghosh Avatar asked Dec 13 '13 09:12

Sourav Ghosh


People also ask

What does target mean in makefile?

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

What is the purpose of 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.

What are typical targets in a makefile?

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.


1 Answers

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.

like image 69
Ervadac Avatar answered Nov 04 '22 20:11

Ervadac