Make is a program based on a Unix system utility over 25 years old. It is mainly used to maintain programs based on many source files. The instructions on how to build a program and what source files a program depends on are specified in a makefile. Make can be used for other tasks as well.
A makefile is a list of what needs to be built for a project. A project may include several executables and/or DLLs called targets. For each target a makefile may specify what source, object, and library files are needed to build the target. These are called dependents. It is entirely possible (even common) that a dependent for one target is itself a target.
For each target and its dependents, the makefile may also specify the
exact sequence of commands needed to build the target.
Below is a simple makefile that shows how to build
is a complete program in a single file):
hello.exe: hello.cpp bcc32 -ehello.exe hello.cpp
You can test out make by typing the above into a file called
makefile and also put
hello.cpp in the
same directory such as
(Note white space is significant in a makefile.
The first line starts in column one, and the second has a leading tab.)
This example assumes your C++ compiler is called
bcc32, which is
the case if you are using the free Inprise/Borland
C++ 5.5 compiler for Windows.
If you are using some other C++ compiler, modify the second line
appropriately for your compiler and system.
(For a Unix/Linux system the second line should probably read
g++ -o hello.exe hello.cpp".)
make as shown below and see what happens.
In reality you would not need a makefile for such a simple example. However even if the project only has one or two source files a makefile can sometimes be useful. The executable may need to be compiled with certain options, or using some non-standard library (such as the XML C++ parser library). Help files (man pages for Unix/Linux) and configuration files may need to be installed in various directories, or registry keys may need to be set.
Once the makefile is written, all you need ever type to rebuild the project is the command:
The make command looks for a file in the current directory called "makefile" or "Makefile" and builds the first target listed in the file. (It is possible to call your makefile something else, see make options below.) If the makefile contains several targets, you can specify which one you'd like to build on the command line. Thus the previous example is exactly equivalent to:
C:\Temp> make hello.exe
Make is smart in that it only builds things if it needs to.
hello.exe exists and is newer than all of its dependents,
then nothing will be done when running make.
If only some of the dependents are newer, only they will get
You can appreciate this feature when you consider that some commercial
software projects consist of over 2000 source files and only 25 of them
may have changed since the last time the target was built.
Even on modern PCs it can take a lot of time to compile 2000 source files!
Make will keep track of which
object files are out of date with respect to their source files
and only re-compile those.
Another nice feature of make is that it comes configured for many common
foo.cpp, no makefile is
Just enter the command "
make foo.exe" and make will realize
there is no makefile, will look for source files named foo that
it knows how to build into executables, will find
and then will build it.
A complete working (but simple) makefile for a voicemail project is shown below. If this example makes sense to you, you can skip the remaining sections of this document, which describe make and makefiles in more detail.
# Simple Borland makefile for voicemail project. # (Note the system knows how to build an obj file from a cpp file.) # (C)2000 by Wayne Pollock, Tampa Florida. All Rights Reserved. # The .exe depends on all the object files. vmail.exe: VMail.obj MBox.obj Msg.obj Telephone.obj Main.obj bcc32 -evmail.exe VMail.obj MBox.obj Msg.obj Telephone.obj Main.obj clean: -DEL *.obj # If the files don't exist this produces an error. -DEL *.tds # The leading "-" says ignore any error & continue.
Make can be used with many options specified on the command line.
For example entering the command "
make -n target"
won't actually build anything.
Instead this option causes make to print out the commands it would run (had
you not specified the -n option) when building target.
This is useful for determining which files and directories make will use
when installing something.
To name your makefile something interesting such as foo.mak, you can use
the "-f" option ( i.e., "
make -f foo.mak") to tell make which
makefile to use.
To display a brief summary of options for make, enter "
Makefiles are at the heart of all project files today. For instance, Borland projects, Symantic Cafe projects, and MS Visual Studio projects simply provide GUI interfaces for a project's makefile, although sometimes extra information is kept in a project file as well. In fact most of these systems have a menu command to write out the makefile which you can then easily look at with any text editor (such as NotePad). Unix, Linux, Windows, and Macintosh systems today usually come with a stand-alone make utility already. (If your system does not you can easily find and download one from the Internet. Borland C++ v5.5 comes with make (including the free downloadable version used at HCC). The GNU project also contains a popular free make program as well as additional developer tools.
There are many versions of make floating around these days, including the original make, Gnu's gmake, imake, nmake (MS provides this with Windows), and others. Fortunately the basic makefile syntax is the same for all of them. However there are some differences, so you should read the documentation on the version of make you are using before creating complex makefiles. The makefile syntax discussed here should be common to nearly all versions of make.
A different problem is that the commands listed in a makefile to build a target
are dependent on your system and compiler.
For example, the commands used on Windows with a Borland compiler will not
work well on a Linux system using g++ (the GNU C++ compiler).
Make does provide a feature called macros that help isolate the
system dependencies but it is still a problem.
A makefile is a plain text file containing entries.
In addition to entries a makefile may contain blank lines and
All entries (except for rules) must fit on a single line,
however a line ending in a backslash ("
onto the next line.
(The backslash and newline are replaced with a space.)
In some places in an entry white space is significant.
Furthermore all entries must start in column one.
There are four types of entries allowed in a makefile: macro definitions, make directives, implicit rules, and explicit rules. Both types of rules may be (and usually are) multi-line entries. All lines except the first must be indented by at least one tab. (A single tab is common; some versions of make permit one or more spaces instead.) The first line of a rule is known as the dependency line and the remaining lines (if any) are known as the command lines.
These are all described in the table below but first a reminder: Most makefiles are simple and quite short, containing some comments at the top and one explicit rule (or just a few). Make contains some powerful defaults so you don't usually need to write more than this. However for the adventurous out there I will try to describe some of the other features that may be found in a makefile. This is not intended to replace your make documentation! Borland's make comes with extensive tool help, and does the other make programs such as Gnu make.
To keep the discussion interesting I have provided a sample makefile. This makefile is not typical, but instead tries to show every make feature in the context of a realistic example, with lots of comments. (In real life the original makefile for voice mail project was less than a dozen lines long, comments and all. However the sample makefile used here will work fine, at least with Borland make.)
|Blank lines||Blank lines may appear almost anywhere to improve the readability of the makefile. However, rules in a makefile may be multi-line entries, and inserting a blank line in the middle of one would confuse make into thinking you had two broken entries rather than a single rule.|
Any line containing a
Make allows you to define macros, which are short names that
expand out to an arbitrary string of text.
Like all entries, macro definitions start in column one and contain the
macro's name, an equal sign, and the replacement text (up to the end
of the line).
Macros may be defined in terms of other previously defined macros.
(Macros may also defined on the command line to make.)
Some example macro definitions are:
The first macro definition defines the macro
The second macro defines some options to pass to the C++ compiler when building object files. Should the options change (e.g., add a debug option), you need only change a single line and all the compile commands later in the makefile would use the new set of options.
The last macro defines
A macro may be used anywhere in a makefile after it has been defined.
To use a macro, type its name in parenthsis and preceeded by a dollar sign.
Using some macros, the simple makefile shown previously becomes:
Make also defines some special macros that are defined automatically. These are a single character each. (When using them the parenthesis are optional.) These macros have meaning only in certain places within your makefile. In fact the same macro had different meanings depending on where it is used; make redefines them as needed.
There are considerable differences in special macros between various make versions, so care is needed: read your local documentation! GNU make is available for all platforms and contains a large (and very useful) set, including macros for object files within a library when the library is the target, and other goodies. However, the following two special macros are fairly standard:
Here's a Linux example that uses both macros. There are several interesting points about it: I have modified the example to create and use a DLL. (Note how simple it is to do under Linux.) The example also shows an advanced macro feature, substitution. It often happens that you define a macro for object files, then need to reference the source files. Or vice versa. This example shows how to do that.
If this appears cryptic, it's probably because it is.
On Linux (and Unix), "
Notice how easy it would be to add another source file to
this project; only the
One final note about macros: if you wish to use a dollar sign in your filenames or (more commonly) in commands, you must double up the dollar sign:
|Directives||yada yada yada goes here.|
yada yada yada goes here.
One advanced feature is the use of the ".cpp.obj" rule (which is also pre-defined in in the make configuration file (for Borland the file is called "BUILTINS.MAK", and found in the same directory as make.exe). This rule says that a file foo.obj depends on the file foo.cpp, and provides the commands to build the .obj files. An alternative is to have many rule entries like:
foo.obj: foo.cpp $(CC) $(CPPFLAGS) $(INCLUDE_PATH) -c $*.cpp
|Send comments and mail to the author.|