In a Unix environment when working with C++ or C, a Makefile can be a very handy thing. Instead of typing several separate commands each time you update a file and want to recompile, you can just type make and the Makefile is executed.

A Makefile is a plain-text file traditionally named “Makefile” or “makefile” that resides in the same directory as your program source.

No matter which technique shown here you use (Quick and Dirty or Long and Explicit), the basic setup of a Makefile is as follows:

main_program:  dependency_1 dependency_2 dependency_3... dependency_n
     command for main_program

Note that the second line is indented while the first is not. And then, following that, you’ll have n number of dependency definitions like the following:

dependency_n:  dependency_a dependency_b dependency_c...
     command for dependency_n

The dependencies for dependencies (i.e. dependency_a, dependency_b, etc.) are usually files, and not other dependencies, that determine when dependency_n’s command should be run. For example, take the following dependency definition:

main.o: main.cpp header.h
     g++ -Wall -c main.cpp

In this example, when main.cpp or header.h is changed and the Makefile is run, the command for main.o will be executed. That command happens to be g++ -Wall -c main.cpp.

Here are some examples of Makefiles:

Quick and Dirty

prog5: main.o readData.o car.o radio.o
     g++ -o $@ main.o readData.o car.o radio.o

Here, prog5 is the name of the executable that will be made. g++ is the compiler I’m using. Each .o file will be created from a .cpp (or whatever C++ extension you choose) file of the same name.

I say that this Makefile is dirty because if you update a header file (i.e. one typically ending in .h) and recompile, this Makefile will not notice any changes. This isn’t normally a problem because after initially creating your header files, you probably won’t be making any changes to them except to perhaps update a function prototype, and of course if you do that, you’ll need to update the corresponding implementation file (i.e. a .cpp file) as well.

Long and Explicit

myProgram: main.o stu.o cla.o readData.o
     g++ -o myProgram main.o stu.o cla.o readData.o

main.o: main.cpp header.h
     g++ -Wall -c main.cpp

stu.o: stu.cpp header.h stu.h
     g++ -Wall -c stu.cpp

cla.o: cla.cpp header.h cla.h
     g++ -Wall -c cla.cpp

readData.o: readData.cpp header.h
     g++ -Wall -c readData.cpp

Here, myProgram is the executable that will be created, while each .o file is created with its own explicit definition of dependencies. For example, cla.o depends on cla.cpp, header.h, and cla.h; if any of those files changes, cla.o will be recompiled. The -Wall is a g++ option to turn on all warnings about your source.