About makefiles

Tutorial

A good, concise, and colorful tutorial on nakefiles can be found at the University of Hawaii's College of Engineering web site: http://www.eng.hawaii.edu/Tutor/Make/. If you haven't used makefiles before, I strongly suggest that you read this.

Example

Here is the Makefile from the RPC demo code. It uses the most basic capabilities of make; it does not use any macros and shortcuts allowable by the make program.

CC = gcc CFLAGS = -g -DRPC_SVC_FG all: client server client: client.o date_clnt.o $(CC) -o client client.o date_clnt.o -lnsl server: server.o date_svc.o $(CC) -o server server.o date_svc.o -lnsl date_svc.o: date.h $(CC) $(CFLAGS) -c date_svc.c date_clnt.o: date.h $(CC) $(CFLAGS) -c date_clnt.c server.o: server.c date.h $(CC) $(CFLAGS) -c server.c client.o: client.c date.h $(CC) $(CFLAGS) -c client.c # date.x produces date.h, date_clnt.c and date_svc.c # make sure we generate these if they're missing or our interface changes date_clnt.c: date.x rpcgen -C date.x date_svc.c: date.x rpcgen -C date.x date.h: date.x rpcgen -C date.x clean: rm -f client client.o server server.o date_clnt.* date_svc.* date.h

Download this file (save it as Makefile)

Lines starting with a name followed by a colon (e.g., server:) are targets - names of things you want to make. Following the colon is a whitespace separacted list of dependencies: things that need to be made before the target can be made. In the case of server, the dependencies are server.o and date_svc.o. The lines after that, up to the next target, are the actions - the commands that make should execute if the dependencies are met.

Make treats dependencies in one of two ways. If the dependency appears as a target in the Makefile then the process is recursive: make looks at the dependencies of the respective targets and runs the actions if necessary. If the dependency and target are file names, then make compares the modification times of the target and the dependencies. If the dependencies are all older than the target the actions need not be taken.

Using the server example again, make checks to see if server, server.o and date_svc.o exist as files and that server.o and date_svc.o are both older than server. If this is the case then the action need not be executed. If server.o has a later modification than server, make will execute the action:

$(CC) -o server server.o date_svc.o -lnsl

The $(CC) states to use the value of the variable CC which was defined in the first line of the file to gcc. The command that ultimately gets executed is:

gcc -o server server.o date_svc.o -lnsl

If, in checking the target server.o, make discovered that one of its dependencies, server.c has a newer modification time then server.o, it would execute the action:

gcc -g -DRPC_SVC_FG -c server.c

before executing the action for the target server.

When make is run with no arguments, it attempts to open a file named makefile. If that is not fount, it tries to open Makefile. It then makes the first target in the file. In this example, it is a target named all which depends on the targets client and server.