make and the makefile

Once you have entered the source of a C program, it needs to be compiled and linked - usually several times since nobody is perfect.

To run the compiler manually, means to type in all the commands and options by hand, is somewhat tedious and prone to error. Also, larger programs consist of many modules and will make it extremely diffcult to compile by hand.

Fortunately, there is the "make" utitlity available in UNIX. With proper input (the socalled makefile) make will not only handle the details of compilation but also will keep track of your program development.

So what is make doing?

make generates a sequence of commands for execution by the UNIX shell. The programmer (you!) first produces a table of file dependencies. This is done by editing a file (the makefile).

With this information make can perform updating tasks automatically. make can keep track of the sequence of commands that create certain files, and the list of files that require other files to be current before they can operate efficiently. When a program or even just a part of a program is changed, make can create the update of all files with a minimum of effort.

To call make use the Syntax: make [options] [targets] [macro definitions]

Through this course we will use eventually only one of the make options:

make -f filename.

For other options see the on-line documentation of make (man make, you remember?).

By default make is looking for a file called makefile in the current directory. This file must be edited first, and it has to contain the users file dependencies. With the -f option, files with other names can be understood to be makefiles, too.

Let's have a look at such a "makefile"

#

# makefile to create the executable "histo"

#

CC = cc

CFILES = funct1.c funct2.c funct3 funct4.c

NAME=histo

OBJS = ${CFILES:.c=.o}

$(NAME):$(NAME).o $(OBJS)

$(OBJS):$(CFILES)

$(NAME).o:$(NAME).c

Yikes!!!!(<- this is not part of the makefile anymore!)

Alright, let's have a look again, (almost) line by line....

#

# makefile to create the executable histo

#

Obviously we've got three comment lines here, maked by a # ....

CC = cc

This line means: Everytime in the following something such as $(CC) appears, it will really mean: cc. Calling the C compiler. Doesn't make sense? Well, not yet. But you might want to add additional compiler options later, for example the "-g" option (witch on debugging). Then you have to change only this line once to force all the following compilations to have the debugging option!

CFILES = funct1.c funct2.c funct3.c funct4.c \

Now for make these two lines are really just one line. The "\" tells make to add the following line to the string. And what does it mean? Anytime in the makefile, $(CFILES) is used, it will stand for funct1.c funct2.c funct3 funct4.c funct5.c

NAME=histo

Same here, now $(NAME) stands for "histo".

OBJS = ${CFILES:.c=.o}

Now, this is a smart one. We have already declared the meaning of $(CFILES). This line uses the definition of $(CFILES) (funct1.c funct2.c funct3.c funct4.c funct5.c) but substitutes the ".c" with an ".o". Therefore, $(OBJS) will stand for: funct1.o funct2.o funct3.o funct4.o funct5.o ! Saves a lot of typing, doesn't it? So far the definitions of the environment variables here.

Let's go to the next line:

$(NAME):$(NAME).o $(OBJS)

This means: To create $(NAME) make sure that both, $(NAME).o (means here: histo.o) and $(OBJS) (means here: funct1.o funct2.o funct3.o funct4.o funct5.o) are existant and up to date. If this is the case, perform the following commands that are preceeded by a tab. If negativ, look around inside the makefile to find a simular statement targeting either $(NAME).o or $(OBJS) and bring them up to date first. This is called a dependency line.

And here comes the command (it can be a whole sequence of lines, just don't forget the tab!) that will be performed if, and only if, all the files - histo.o funct1.o funct2.o funct3.o funct4.o funct5.o - are up to date:

Now, it's not difficult to figure out what we have next:

$(OBJS):$(CFILES)

$(NAME).o:$(NAME).c

Let us have a look at the most important features of a makefile:

The makefile may contain any of the following types of lines:


go back to course page


drago@scri.fsu.edu

Feb. 1997