Makefiles
While the use of "#include" statements to link classes into programs is acceptable for small programs, makefiles allow the efficient compilation of larger programs in an organized, somewhat-automatic manner. When using makefiles, the manner of including classes in other files changes slightly, but all in all, it is more efficient.
Makefiles
Makefiles contain information regarding the compilation of a program. A Makefile for a program is located in the same directory as the program files, but always has the name "makefile" (with no extension). The file itself is a simple text file that consists of as many entries as are required to create the program. Each entry in the makefile consists of the following:
Tag: Dependencies
Command
Here, the entry Tag consists of the file or entity that will be created by the command, and the Dependencies are the files that the Tag requires for compilation. On the second line, which has a tab before the Command, is the command that the system will execute to build the file or entity specified by the Tag.
For example, to build a simple program consisting of the Stack class (of our creation and beign contained in teh files "Stack.cpp" and "Stack.h") and the driver "main.cpp", we could have the entry:
MyProgram: main.cpp Stack.cpp Stack.h
g++ -o MyProgram main.cpp
This command indicates that the file/object "MyProgram" depends on the files "main.cpp", "Stack.cpp", and "Stack.h", and that it can be created by issuing the specified command.
More Complex Makefiles
While the example in the previous section works on simple programs, makefiles can be much more advanced and offer us more flexibility. Doing so requires that we include out class file a little differently in the driver file. Instead of using the statement #include "Stack.cpp" in the driver file or other files where the Stack class is utilized, we use include the declaration file instead. Thus, we now place the statement #include "Stack.h" where we once had the implementation file included. This change is dealt with in the makefile.
Now that the class is is included by referencing the declaration file, we cna change our makefile so that it has the following two entries:
MyProgram: main.cpp Stack.o
g++ -o MyProgram main.cpp Stack.o
Stack.o: Stack.cpp Stack.h
g++ -c Stack.cpp
These entries (both in the makefile) will create the same program, but in a different way. The first entry now indicates that the program is dependent on the object file "Stack.o". The object file "Stack.o" is defined in the second entry, where the compiler is given the "-c" option, which directs it to create the object file "Stack.o" that we reference. By creating the object file, we create a library that the compiler will link to whenever it encounters a reference to the Stack class.
Executing a Makefile
Executing a makefile is simple. When in teh same directory as the makefile, simply issue the command:
make
This command will execute the makefile in the current directory, building the program that it specifies. Any errors encountered will stop the compilation process, as would be the case if we compiled the program using separate commands on the command-line.
Benefits
The benefits of using makefiles are as follows:
  • Efficient compilation - Object files that have not changes are not rebuilt
  • Easier - Compiling the program is accomplished with one short, simple command, as opposed to several longer ones
  • Compartmentalized - Classes are compiled into object files, which meshes with our concept of classes as standalone components of a program
These reasons, among a few others, make makefiles a better way to compile projects, whether they be small or complex. The time saved by recompiling only the program dependencies that have changed can be substantial, when working on a project that spans several files.
On This Page...
Makefiles
More Complex Makefiles
Executing a Makefile
Benefits