Unix Makefiles
Unix Makefiles
COP 3330
Lecture Notes
Dr. David A. Gaitros
Introduction
The make utility in Unix is one of the original tools designed
by S. I. Fieldman of AT&T Bell labs circa 1977. There are many
version.
What is make?: The tool is designed to allow programmers
to efficiently compile large complex programs with many
components easily.
You can place the commands to compile a program in a Unix
script but this will cause ALL modules to be compiled every
time.
The make utility allows us to only compile those that have
changed and the modules that depend upon them.
Simple Example
hello: main.o factorial.o hello.o
g++ main.o factorial.o hello.o -o hello
main.o: main.cpp
g++ -c main.cpp factorial.o: factorial.cpp
g++ -c factorial.cpp
hello.o: hello.cpp
g++ -c hello.cpp
clean:
rm -rf *o hello
The Tree
hello
main.o
factorial.o
factorial.o
hello.o
factorial.cpp
hello.cpp
main.cpp
clean
Components of a Makefile
Comments
Rules
Dependency Lines
Shell Lines
Macros
Inference Rules
Comments
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.
Comments can start anywhere. There are more complex
comment styles that involve continuation characters but
please start each new comment line with an # and avoid the
more advanced features for now.
Example
#
# This is a comment
projecte.exe : main.obj io.obj
Rules
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 or shell
line after it. The action line is executed if the dependency line is out of
date.
Example:
hello.o: hello.cpp
g++ -c hello.cpp
Dependency Lines
At the running of the make utility, the time and date when Project.exe was last
built are 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.
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.
It is important that all dependencies be placed in a descending order in the file.
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
The indented lines (must have tab) that follow each
dependency line are called shell lines. Shell lines tell
make how to build the target.
A target can have more than one shell line. Each line
must be preceded by a tab.
After each shell is executed, make checks to see if it
was completed without error.
You can ignore this but I would not at this point.
Shell Lines
After each shell line is executed, Make checks the shell line
exit status.
Shell lines that returning an exit status of zero (0) means
without error and non-zero if there is an error.
The first shell line that returns an exit status of non-zero will
cause the make utility to stop and display an error.
Macros
Comes from the Greek word makros meaning large.
Basically it is a shorthand or alias used in the
makefile
A string is associated with another usually larger
string
Inside the file, to expand a macro, you have to place
the string inside of $( ) .
The whole thing is expanded during execution of the
make utility.
Macros
Examples of macros:
HOME = /home/courses/cop4530/spring02
CPP = $(HOME)/cpp
TCPP = $(HOME)/tcpp
PROJ = .
INCL = -I $(PROJ) I$(CPP) I$(TCPP)
You can also define macros at the command line such as
Make DIR = /home/faculty/whalley/public_html/cop5622proj/lib2
And this would take precedence over the one in the file.
Inference Rules
Inference rules are a method of generalizing the
build process. In essence, it is a sort of wild card
notation.
The % is used to indicate a wild card.
Examples:
%.obj : %.c