The Makefile
· The Unix make utility reads
instructions from text files. The makefile has instructions for a specific
project.
o
The
Makefile tells the make utility how to build a project with multiple files and
in what order.
· The filename must be either
“makefile” or “Makefile” and must reside in the directory where the project
exists.
o
There
are exceptions to this but for the purposes of the class we will assume the
makefile will reside in each project directory.
· Makefiles are composed of
the following components:
o
Comments
o
Dependency
Lines
o
Directives
o
Macros
o
Response
files
o
Rules
o
Shell
lines
· Comments
o
A
comment is indicated by the character “#”.
All text that appears after it will be ignored by the make utility until
the end of line is detected.
o
Comments
can start anywhere. There are more
complex comment styles but please start each new comment line with an # and
avoid the continuation feature for now.
o
Example
#
#
This is a comment
projecte.exe
: main.obj io.obj # this is also a comment.
· Rules
o
Rules
tell make when and how to make a file.
The format is as follows:
A rule must have a dependency line and may have an action line after it. The action line is executed if the dependency line is out of date.
Example:
Project.exe: main.obj io.obj
This
shows Project.exe as the main program that requires main.obj and io.obj as
external sources of object code. If the
date of either one is new than Project.exe, then Project.exe is rebuilt.
· Dependency Lines: When to build a target
o
The
lines with a “:” are called dependency lines.
To the left are the dependencies and to the right are the sources needed
to make the dependency.
o
At
the running of the make utility, the time and date when Project.exe was last
built was compared to the dates when main.obj and io.obj were built. If either main.obj or io.obj have new dates,
then the shell line after the dependency line is executed.
o
The
make process is recursive in that it will check all dependencies to make sure
they are not out of date before completing the build process.
o
It
is important that all dependencies be placed in a decending order in the file.
o
Some
files may have the same dependencies.
For instance, suppose that two files needed a file called
bitvect.h. What would the dependency
look like:
main.obj
this.obj: bitvect.h
· Shell Lines
o
The
indented lines (must have tab) that follow each dependency line are called
shell lines. Shell lines tell make how
to build the target.
o
A
target can have more than one shell line.
Each line must be preceeded by a tab.
o
After
each shell is executed, make checks to see if it was completed without error.
o
You
can ignore this but I would not at this point.
· Macros are pretty cool
o
Comes
from the Greek word makros meaning large.
o
Basically
it is a shorthand or alias used in the makefile
o
A
string is associated with another usually larger string
o
Inside
the file, to expand a macro, you have to place the string inside of $(
) .
o
Examples
of your macros:
CPP
= $(HOME)/cpp
TCPP
= $(HOME)/tcpp
PROJ
= .
INCL
= -I $(PROJ) –I$(CPP) –I$(TCPP)
Make CPP =
/home/courses/cop4530/spring02
And
this would take precedence over the one in the file.
· Inference Rules
o
Inference
rules are a method of generalizing the build process. In essence, it is a sort of wild card notation.
o
The
“%” is used to indicate a wild card.
o
Examples:
%.obj
: %.c
$(CC) $(FLAGS) –c $(.SOURCE)
All
.obj files have dependencies of all %.c files of the same name.
· Respond Files will not be
covered.
· Makefile Directives will not
be covered at this time.
Example of a complex
makefile:
CC
= gcc
DIR
= /home/faculty/whalley/public_html/cop5622proj/lib
CFLAGS
= -g -I$(DIR) -I. -c
LFLAGS
= -g
opt:
analysis.o flow.o io.o misc.o opt.o opts.o peephole.o regs.o vect.o
$(CC) $(LFLAGS) -o opt analysis.o flow.o
io.o misc.o opt.o opts.o peephole.o regs.o vect.o
analysis.o:
analysis.c analysis.h $(DIR)/misc.h $(DIR)/opt.h $(DIR)/vect.h
$(CC) $(CFLAGS) analysis.c
flow.o:
$(DIR)/flow.c $(DIR)/flow.h $(DIR)/opt.h
$(CC) $(CFLAGS) $(DIR)/flow.c
io.o:
$(DIR)/io.c $(DIR)/io.h analysis.h $(DIR)/misc.h $(DIR)/opt.h peephole.h
$(DIR)/regs.h
$(CC) $(CFLAGS) $(DIR)/io.c
misc.o:
$(DIR)/misc.c $(DIR)/misc.h $(DIR)/opt.h
$(CC) $(CFLAGS) $(DIR)/misc.c
opt.o:
$(DIR)/opt.c $(DIR)/opt.h
$(CC) $(CFLAGS) $(DIR)/opt.c
opts.o:
opts.c $(DIR)/misc.h $(DIR)/regs.h $(DIR)/opt.h opts.h
$(CC) $(CFLAGS) opts.c
peephole.o:
peephole.c $(DIR)/misc.h $(DIR)/regs.h $(DIR)/opt.h peephole.h
$(CC) $(CFLAGS) peephole.c
regs.o:
$(DIR)/regs.c $(DIR)/regs.h $(DIR)/opt.h
$(CC) $(CFLAGS) $(DIR)/regs.c
vect.o:
$(DIR)/vect.c $(DIR)/vect.h $(DIR)/opt.h
$(CC) $(CFLAGS) $(DIR)/vect.c