The make program is a UNIX facility for describing dependencies among a group of related files, usually ones that are part of the same project. This facility has enjoyed widespread use in software development projects. Programmers use make to describe how to "make" a program - what source files need to be compiled, what libraries must be included, and which object files need to be linked. By keeping track of these relationships in a single place, individual members of a software development team can make changes to a single module, run make, and be assured that the program reflects the latest changes made by others on the team.
We group make with the other commands for keeping track of differences between files only by a leap of the imagination. However, although it does not compare two versions of the same source file, it can be used to compare versions such as a source file and the formatted output.
Part of what makes UNIX a productive environment for text processing is discovering other uses for standard programs. The make utility has many possible applications for a documentation project. One such use is to maintain up-to-date copies of formatted files that make up a single manual and provide users with a way of obtaining a printed copy of the entire manual without having to know which preprocessors oroptions need to be invoked.
The basic operation that make performs is to compare two sets of files, for example, formatted and unformatted files, and determine if any members of one set, the unformatted files, are more recent than their counterpart in the other set, the formatted files. This is accomplished by simply comparing the("timestamp") of pairs of files. If the unformatted source file has been modified since the formatted file was made, make executes the specified command to "remake" the formatted file.
To use make, you have to write a description file, usually named makefile (or Makefile), that resides in the working directory for the project. The makefile specifies a hierarchy of dependencies among individual files, called components. At the top of this hierarchy is a target. For our purposes, you can think of the target as a printed copy of a book; the components are formatted files generated by processing an unformatted file with nroff.
Here's the makefile that reflects these dependencies:
manual: ch01.fmt ch02.fmt ch03.fmt lp ch0[1-3].fmt ch01.fmt: ch01 nroff -mm ch01 > ch01.fmt ch02.fmt: ch02 tbl ch02 | nroff -mm > ch02.fmt ch03.fmt: ch03a ch03b ch03c nroff -mm ch03[abc] > ch03.fmt
This hierarchy is represented in Figure 28.1.
The target is manual, which is made up of three formatted files whose names appear after the colon. Each of these components has its own dependency line. For instance, ch01.fmt is dependent upon a coded file named ch01. Underneath the dependency line is the command that generates ch01.fmt. Each command line must begin with a TAB.
When you enter the command
make, the end result is that the three
formatted files are spooled to the printer.
However, a sequence of operations is performed before this final action.
The dependency line for each component is evaluated, determining if
the coded file has been modified since the last time the formatted
file was made.
The formatting command will be executed only if the coded file is
After all the components are made, the
command is executed.
As an example of this process, we'll assume that all the formatted files are up-to-date. Then by editing the source file ch03a, we change the modification time. When you execute the make command, any output files dependent on ch03a are reformatted:
makenroff -mm ch03[abc] > ch03.fmt lp ch0[1-3].fmt
Only ch03.fmt needs to be remade. As soon as that formatting command finishes, the command underneath the target manual is executed, spooling the files to the printer.
Although this example has actually made only limited use of make's facilities, we hope it suggests more ways to use make in a documention project. You can keep your makefiles just this simple, or you can go on to learn additional notation, such as internal macros and suffixes, in an effort to generalize the description file for increased usefulness.
- from UNIX Text Processing, Hayden Books, 1987