Note:
We've just listed all the dependencies for the executable
main. The executable depends on some things
directly (like the .o files) and some things
indirectly (i.e., you need the .cpp files to generate
the .o files to generate the executable).

Using dependency chart:

With such a dependency chart, we can answer questions about what
needs to be regenerated if certain files change.

For example, suppose we change the file
main.cpp...What has to be regenerated?

Answer: First, recompile main.cpp to get
main.o. Then, relink all the object files together
again to get the executable main.

Now, suppose we changed Point.h?

Note:
When either a .cpp file changes or a header file included
(directly or indirectly) by a .cpp file changes, we have
to regenerate the corresponding .o file.

Make utility and make files:

Since it is tedious to recompile pieces of a program when something
changes, people often use the make utility instead.

Make needs a make file that encodes both the
dependencies between files and the commands needed to generate files.

When you run the make utility, it examines the
modification times of files and determines what needs to be
regenerated. Files that are older than the files they depend
on must be regenerated. Regenerating one file may cause others to
become old, so that several files end up being regenerated.

Aside:
Note the difference between the make utility (a program you
run) and a make file (that tells the make utility
how to compile/link a specific program).

A make file should be named either Makefile (first letter
uppercase) or makefile (all lowercase). The make file should be
in the same directory as the source code files.

Aside:
Make files can have other file names, but then you'll have to
tell the make utility what the name of the make file is (using
a commandline option).

Finally, it is easiest if the make file is in the same directory as the
source code files.

Writing a make file:

You can create a make file in any text editor.
For this example, we will examine the parts of this Makefile, which generates the executable
main. Go ahead a download that make file.

Simple make files have at least 2 parts:

A set of variables, which specify things like the C++
compiler/linker to use, flags for the compiler, etc.

A set of targets, i.e., files that have to be generated.

Make files may have comments that (hopefully) add to readability. Any
line starting with a pound sign (#) is a comments. Note
that our make file has some comments.

Note:
Keep in mind that make files use their own language, so
don't expect things in them to look like programming languages you
know.

Variables

The first variable listed in our make file is for the compiler to use...

CXX = g++

In general, the form for setting a variable is:

VARNAME = value

(The space around the = is optional for our version of
make, but adds to readability).

The second variable says what flags to pass to the C++ compiler...

CXXFLAGS = -Wall -g

Here, the variable includes the flag for all warnings and the
one that adds debugging information (so that the executable can
later be run under a debugger).

The 2 variables, CXX and CXXFLAGS, are the
ones that our version of make expects to be set for the C++
compiler and flags to the C++ compiler, respectively.

Aside:
You can add your own variables, but make has a set of standard
variables, like these, which it uses for the compiler, flags, etc.

Targets

With the needed variables, we can deal with the targets, which are
files that must be generated.

For each target, there are typically 1 or 2 lines in a make file.
Those lines specify:

and possibly a command to generate the target (easy to determine
from knowledge of separate compilation).

By default, the first target in the make file is the one that gets
generated when you just say "make" at the commandline, so
it should be the name of the executable.

Target: Executable

Let's examine the first target in our make file (i.e., for
main)...

For a target's dependency line, the target file name should be listed,
followed by a colon (:) and the files it depends on:

main: main.o Point.o Rectangle.o

For a target that is an executable, we just list the object files it
depends on.

On the next line, there should be a command that generates the target:

<Tab>$(CXX) $(CXXFLAGS) -o main main.o Point.o Rectangle.o

Note:
This line MUST start with a <Tab> (i.e., hit
the Tab key)...it cannot start with a regular space!

Note that the variables CXX and CXXFLAGS
are used, which means that the command is really:

g++ -Wall -g -o main main.o Point.o Rectangle.o

Note:
Using a variable in a make file involves using the dollar sign
($) and then the variable name in parentheses.

Targets: Object Files

Our next target is the object file, main.o.

For a target that is an object file, we list all files it depends on.
This means its corresponding .cpp file, plus any header
files its .cpp file includes (i.e., include directly or
indirectly, but not system header files like iostream that
aren't going to change).

So, the dependencies line looks like:

main.o: main.cpp Point.h Rectangle.h

The generation command for this target is:

<Tab>$(CXX) $(CXXFLAGS) -c main.cpp

Make is kinda smart

We could have written the main.o target more simply.
Make already knows how to generate certain kinds of files.
Let's take advantage of make's smarts for the next target...

The next object file, Point.o depends on Point.cpp,
however, make already knows that .o files can be
generated from their corresponding .cpp files, so all we need
is:

Point.o: Point.h

Note:
Although some make utilities can automatically determine what
.h files a file depends on, some cannot, so you should
list the include dependencies.

We don't need any generation line since we set up the
variables CXX and CXXFLAGS. Make
will use them to figure out a compilation command.

Finally, there is only one target left, Rectangle.o.
Taking advantage of make's smarts, it only requires:

Rectangle.o: Rectangle.h Point.h

Note that Rectangle.o depends on Point.h
indirectly (i.e., recall that Rectangle.cpp includes
Rectangle.h, which includes Point.h).

That's all for the make file!!! It just encodes the dependencies and
the generation commands for 1 executable and its 3 object files.

Using a make file:

With a make file for our executable, it is easy to compile that
executable.

Try using the make file we've given you.
First, remove the old executable and object files (if there are any):

% rm main *.o

Run make with the command:

% make

Remember that this will cause make to generate the first
target in the make file, which is main.

Since all the .cpp files depend on that header (either
directly or indirectly), they all have to be recompiled and linked
together.

Additional notes on make:

Other versions of make may use different variables for C++
instead of CXX and CXXFLAGS.

In a make file, if you need to continue a line, you cannot just
continue it on the next line. You must end a line with a \
(backslash, not the forward slash) to tell make that the line
continues. Only break lines where space would normally go.