An Example

Let us consider a real example. Suppose you are provided with two files, MyThreads.h and MyThreads.o. The former is a header file that has to be included into your source files and the latter is a library of functions for you to use. In other words, your source files in which multithreaded capability is used depend on MyThreads.h and your executable depends on MyThreads.o.

Suppose your assignment has the following files, prog01.c (the main function), and abc.c, def.c and xyz.c. All of these files contain access to multithread functions defined in MyThreads.h. You also designed some utility functions collected in files ut1.c and ut2.c. None of these two have access to the multithread capability. However, in your judgment, you believe any change made to ut1.c and ut2.c requires recompilation of abc.c and xyz.c. Therefore, on the source level, prog01.c, abc.c, def.c and xyz.c depend on MyThreads.h, and abc.c and xyz.c also depend on ut1.c and ut2.c. Suppose the final executable is to be called prog01.

To generate

prog01, we need the object files prog01.o, abc.o, def.o, xyz.o, ut1.o and ut2.o. The executable requires MyThreads.o as well. Thus, if all of these object files are available, to obtain the executable, you need the following command line:

$ gcc -o prog01 prog01.o abc.o def.o xyz.o ut1.o ut2.o MyThreads.o -lthread
Therefore, the dependency line and the command line are
prog01 : prog01.o abc.o def.o xyz.o ut1.o ut2.o MyThreads.o
     gcc -o prog01 prog01.o abc.o def.o xyz.o ut1.o ut2.o MyThreads.o -lthread
To generate prog01.o, we need prog01.c and MyThreads.h and use the following dependency and command lines:
prog01.o : prog01.c MyThreads.h
     gcc -c prog01.c
Similarly, we have the dependency and command lines for abc.c, def.c and xyz.c:
abc.o : abc.c ut1.c ut2.c MyThreads.h
     gcc -c abc.c
def.o : def.c MyThreads.h
     gcc -c def.c
xyz.o : xyz.c ut1.c ut2.c MyThreads.h
     gcc -c xyz.c
Since ut1.c and ut2.c do not use multithread capability, their dependency lines do not have to include MyThreads.h:
ut1.o : ut1.c
     gcc -c ut1.c
ut2.o : ut2.c
     gcc -c ut2.c
Combining all dependency and command lines together, we have the following Makefile:
CC = gcc -ansi

prog01 : prog01.o abc.o def.o xyz.o ut1.o ut2.o MyThreads.o
     ${CC} -o prog01 prog01.o abc.o def.o xyz.o ut1.o ut2.o MyThreads.o -lthread

prog01.o : prog01.c MyThreads.h
     ${CC} -c prog01.c

abc.o : abc.c c ut2.c MyThreads.h
     ${CC} -c abc.c
def.o : def.c MyThreads.h
     ${CC} -c def.c
xyz.o : xyz.c ut1.c ut2.c MyThreads.h
     ${CC} -c xyz.c

ut1.o : ut1.c
     ${CC} -c ut1.c
ut2.o : ut2.c
     ${CC} -c ut2.c