Table of Contents

  1. Introduction
  2. A Sample Makefile: Example #1
  3. Running Example #1
  4. A Fancier Makefile: Example #2
  5. Running Example #2
  6. Closing Words

Introduction

The make utility automatically determines which source code files of a program need to be recompiled and builds them. The make utility determines which source files need to be recompiled by examining their dates relative to a specific target file. The utility is commonly used to compile C/C++ programs.

This document is a beginner's HOWTO on how to use the make utility. The syntax used herein should work for all implementations of make. Most POSIX-based systems will have make installed if a development tool (e.g., a C/C++ compiler) has been installed.

A Sample Makefile: Example #1

Consider this example file called Makefile:

program.exe: prog.cxx
  g++ -o program.exe prog.cxx

Every make file may consist of:

NOTE: Each command under a given rule must have a <TAB> character at the beginning of the line. If your editor does not write tab characters, then you'll need to use another editor or your makefile will not work!

The above Makefile has no macros or comments, but does tell the compiler how to build the file program.exe from prog.cxx. Let's examine what the make actually does under various circumstances in order to understand how this works:

Case #1: The target does not exist yet.

If the target does not exist yet, then it must be built. In the above example, the only target is the file program.exe. Should the make utility not discover the file program.exe in the current directory, then it will assume that the rules for this target need to be executed.

Case #2: The target exists, but, has an older time stamp than all of its dependents.

If the target exists and it has an older time stamp than all of its dependents, then it is assumed that the dependent files were last modified before the target was last built. Consequently, there is no need to rebuild the target (e.g., program.exe).

Case #3: The target exists, but, has a newer time stamp than at least one of its dependents.

If the target exists and it has an newer time stamp than at least one of its dependents, then it is assumed that (one or more of) the dependent files were modified after the target was built. Consequently, the make utility will execute that rules' commands in order to attempt to rebuild that rule's target. In the above example, if the dependent, prog.cxx, for the target, program.exe has a newer time stamp than program.exe, then the make utility will run the command, g++ -o program.exe prog.cxx, in order to rebuild the target file.

Running Example #1

In order to run Example #1 above, be sure to:

By default, the make utility will build the first target mentioned in a file called Makefile. In this instance, the first rule is for the target, program.exe.

You can also run make in a mode that will show you which commands it will run without actually running them. This is handy to debug your make files. To do this, run make with the -n option:

$ make -n
g++ -o program.exe prog.cxx
$

A Fancier Makefile: Example #2

The following make file enables one to build a target prog from three source files: myprog.cxx, silly.cxx, and silly.hxx.

# The next line is a macro...
CXXFLAGS=-g0 -O3

# The next rule is the first rule.
# It is the default rule that will be run.
# The idea for this rule is that there will never be
# an 'all' file so the rule will ALWAYS execute.
all: myprog

# The next rule is intended to "clean up" any temporary files.
# Like the 'all' file, there should never be a 'clean' file
# so that it ALWAYS executes when explicitly invoked.
clean:
  rm -f myprog *.o

# How to build silly.o from silly.cxx...
silly.o: silly.cxx silly.hxx
  $(CXX) -c $(CXXFLAGS) $<

# How to build myprog.o from myprog.cxx...
myprog.o: myprog.cxx silly.hxx
  $(CXX) -c $(CXXFLAGS) myprog.cxx

# How to build myprog from myprog.o and silly.o...
myprog: myprog.o silly.o
  $(CXX) -o myprog $(CXXFLAGS) $+

One should note the following:

Running Example #2

You may build Example #2 by running:

$ make

However, that will only run the default rule. To rule any other rule, simply place the target after the make command:

$ make clean

run the clean rule. Similarly:

$ make silly.o

will execute the rules under the silly.o command if and only if silly.o is out-of-date with respect to its dependents.

Closing Words

The make utility is the defacto C/C++ utility that is used to help keep compiled C/C++ targets in sync with the source code that they dependent on. While make lacks some features of other build tools, it is found on nearly every system having a C/C++ compiler making it a commonly chosen tool to build C/C++ programs.


Copyright © 2007 Paul Preney. All Rights Reserved.