make is a UNIX tool that facilitates working with projects which are composed of multiple files. It can be instructed to execute a sequence of commands and resolve dependencies between files. Once the project is compiled, make is smart enough to only recompile those files which have been changed in the mean time, thus saving time.
This document gives a very brief introduction to make, discussing enough material to enable a student completely unfamiliar with the tool to get started with using it in coding projects.
Let's assume that we have a project composed of files one.c, two.c and inc.h in a project directory. The files one.c and two.c include the file inc.h with an #include statement. Our directory looks like this:
$ ls
inc.h one.c two.c
We need a way to manage the compilation process so that we don't have
to recompile the whole project every time we change one file, and we
want to compile everything with one quick command. We create a file
named Makefile in the current directory, with the following
contents1: (The meaning of
this file will be explained below.)
proj: one.o two.o
gcc -o proj one.o two.o
one.o: inc.h one.c
gcc -c one.c
two.o: inc.h two.c
gcc -c two.c
clean:
rm -f *.o core proj
Now that our Makefile is in the current directory, we
type make:
$ make
gcc -c one.c
gcc -c two.c
gcc -o proj one.o two.o
$ ls
Makefile one.c proj* two.o
inc.h one.o two.c
A binary by the name of proj has been created; this is our
program. So, with one simple command, we are able to compile the
entire project without worrying about getting the compiler arguments
right, the order in which we compile, etc. Now, say that we need to
make a change to one.c. We change the file, save it, and then
type make again:
$ make
gcc -c one.c
gcc -o proj one.o two.o
Note that this time, the file two.c has not been
recompiled. Its old object file, two.o, was reused in the
linking process, since it is still valid; its source file has not
changed. Now, say we want to clean up the project directory to where
we only have source files, so we can tar it up and submit it. We type
make clean:
$ make clean
rm -f *.o core proj
$ ls
Makefile inc.h one.c two.c
And our project is ready to be submitted.
When executed, the make program looks for a special file named Makefile in the current directory, typically provided by the author of the project being built. It then reads this Makefile and builds the project according to its contents. A typical Makefile is composed of a series of rules. The following is a rule:
one.o: inc.h one.c
gcc -c one.c
A rule has three main components: a target, a list of dependencies and a command. The three are represented in a rule as follows:
TARGET: DEPENDENCIES
COMMAND
Typically, make takes a target name as an argument. For example, if all we want to do is build one.o, we would type make one.o:
$ make one.o
gcc -c one.c
And make will build that target and exit. When we type make without an argument, make will attempt to build the
target named all. If a rule for all doesn't exist, make will build the topmost target in your Makefile.
Typically, you will see a rule for all that looks like this:
all: proj
This simply says that the implied target is proj and is useful
when your main target is not at the top of the file, or simply for
readability.
Notice that our Makefile from the previous section has a peculiar target named clean with no dependency list. The clean target is a widespread convention for providing a rule which cleans up the directory and revert it to its source-only state, before any builds were performed. The command for this rule is usually a rm command which removes any object files, binaries, core dumps, temporary files, etc. This allows us to simply type make clean to start fresh.
After reading the above, you should be able to write your own Makefiles for your small-to-medium size school projects. make, however, is a complex tool with a wealth of features, which can be used to manage projects with thousands of files. To find out more, read the GNU make manual: http://www.gnu.org/manual/make-3.80/make.html
On our UNIX systems, the default make command is different than GNU make. Though the two are very similar, GNU make has many more features. GNU make is available as gmake by adding the GNU package with the addpkg command. The examples in this tutorial work with both versions.
Email your questions to CS tutors at tutors@cs.pdx.edu, or join our IRC channel, #cschat on irc.cat.pdx.edu.