Programming Utilities Guide

Basic Features

The basic operation of make is to update a target file by ensuring that all of the files on which the target file depends exist and are up-to-date. The target file is regenerated if it has not been modified since the dependents were modified. The make program searches the graph of dependencies. The operation of make depends on its ability to find the date and time that a file was last modified.

The make program operates using three sources of information:

To illustrate, consider a simple example in which a program named prog is made by compiling and loading three C language files x.c, y.c, and z.c with the math library, libm. By convention, the output of the C language compilations is found in files named x.o, y.o, and z.o. Assume that the files x.c and y.c share some declarations in a file named defs.h, but that z.c does not. That is, x.c and y.c have the line

#include "defs.h"

The following specification describes the relationships and operations:

prog : x.o y.o z.o 
      	cc x.o y.o z.o -lm -o prog 
x.o y.o : defs.h H

If this information were stored in a file named makefile, the command

$ make

would perform the operations needed to regenerate prog after any changes had been made to any of the four source files x.c, y.c, z.c, or defs.h. In the previous example, the first line states that prog depends on three .o files. After these object files are current, the second line describes how to load them to create prog. The third line states that x.o and y.o depend on the file defs.h. From the file system, make discovers that there are three .c files corresponding to the needed .o files and that they use built-in rules on how to generate an object from a C source file (that is, issue a cc c command).

If make did not have the ability to determine automatically what needs to be done, the following longer description file would be necessary:

prog : x.o y.o z.o 
      	cc x.o y.o z.o -lm -o prog 
x.o : x.c defs.h 
      	cc -c x.c 
y.o : y.c defs.h 
      	cc -c y.c 
z.o : z.c 
      	cc -c z.c

If none of the source or object files have changed since the last time prog was made, and all of the files are current, the command make announces this fact and stops. If, however, the defs.h file has been edited, x.c and y.c (but not z.c) are recompiled; and then prog is created from the new x.o and y.o files, and the existing z.o file. If only the file y.c had changed, only it is recompiled; but it is still necessary to reload prog. If no target name is given on the make command line, the first target mentioned in the description is created; otherwise, the specified targets are made. The command

$ make x.o

would regenerate x.o if x.c or defs.h had changed.

A method often useful to programmers is to include rules with mnemonic names and commands that do not actually produce a file with that same name. These entries can take advantage of make's ability to generate files and substitute macros (for information about macros, see "Description Files and Substitutions ".) Thus, an entry save might be included to copy a certain set of files, or an entry clean might be used to throw away unneeded intermediate files.

If a file exists after such commands are executed, the file's time of last modification is used in further decisions. If the file does not exist after the commands are executed, the current time is used in making further decisions.

You can maintain a zero-length file purely to keep track of the time at which certain actions were performed. This technique is useful for maintaining remote archives and listings.

A simple macro mechanism for substitution in dependency lines and command strings is used by make. Macros can either be defined by command-line arguments or included in the description file. In either case, a macro consists of a name followed by the symbol = followed by what the macro stands for. A macro is invoked by preceding the name by the symbol $. Macro names longer than one character must be enclosed in parentheses. The following are valid macro invocations:

$(CFLAGS) 
$2 
$(xy) 
$Z 
$(Z)

The last two are equivalent.

Four special macros $*, $@, $?, and $< change values during the execution of the command. (These four macros are described under "Description Files and Substitutions ".) The following fragment shows assignment and use of some macros:

OBJECTS = x.o y.o z.o 
LIBES = -lm 
prog: $(OBJECTS) 
        	cc $(OBJECTS) $(LIBES) -o prog 
...

The command

$ make LIBES="-ll -lm"

loads the three objects with both the lex (-ll) and the math (-lm

) libraries, because macro definitions on the command line override definitions in the description file. (In operating system commands, arguments with embedded blanks must be quoted.)

As an example of the use of make, a description file that might be used to maintain the make command itself is given. The code for make is spread over a number of C language source files and has a yacc grammar. The description file contains the following:

# Description file for the make command 

FILES = Makefile defs.h main.c doname.c misc.c \ 
        	files.c dosys.c gram.y 
OBJECTS = main.o doname.o misc.o files.o dosys.o gram.o 
LIBES = 
LINT = lint -p 
CFLAGS = -O 
LP = lp 

make: $(OBJECTS) 
        	$(CC) $(CFLAGS) -o make $(OBJECTS) $(LIBES) 
        	@size make 

$(OBJECTS): defs.h 

cleanup: 
        	-rm *.o gram.c 
        	-du 

install: 
        	make 
        	@size make /usr/bin/make 
        	cp make /usr/bin/make && rm make 

lint: dosys.c doname.c files.c main.c misc.c gram.c 
        	$(LINT) dosys.c doname.c files.c main.c misc.c gram.c 

        	# print files that are out-of-date 
        	# with respect to "print" file.  

print: $(FILES) 
        	pr $? | $(LP) 
        	touch print

The make program prints each command before issuing it.

The following output results from entering the command make in a directory containing only the source and description files:

cc -O -c main.c 
cc -O -c doname.c 
cc -O -c misc.c 
cc -O -c files.c 
cc -O -c dosys.c 
yacc gram.y 
mv y.tab.c gram.c 
cc -O -c gram.c 
cc -o make main.o doname.o misc.o files.o dosys.o gram.o \
 13188 + 3348 + 3044 = 19580

The last line results from the size make command. The printing of the command line itself was suppressed by the symbol @ in the description file.