Build System

On modern UNIX systems, the method for build management is overwhelmingly the make utility. Although there are two disjoint make implementations in use (namely by for GNU and BSD UNIX systems), I examine the syntax common to both.

In this section, I'll assume the file Makefile already exists, and is used to build a system where one wishes to incorporate mdoc files.

all: foo

clean:
    rm -f foo foo.o

install: all
    install -m 0755 foo /usr/local/bin

foo: foo.o
    cc -o foo foo.o

A rigorous analysis of this syntax is beyond the scope of this book (do consult your system's documentation for the make command with man make). It defines the targets all, clean, and install: build, clean up, and install the utility, respectively.

File Extension

First, it's important to settle upon an input and output file extension, as make tracks file status by way of comparing the time-stamp of a file's input (which may be multiple files) and output (called the target). In short, if the target is older than any of the input files, it is rebuilt. The input files are created and maintained by the developer; the output files are built by make.

For simplicity, I use the standard .1, .2, and so on convention for the target (the output). I then use .in.1 and so on for input. Thus, it is necessary to notify the make utility of these new extensions before all other rules;

.SUFFIXES: .in.1 .1

If more categories are built, these would need to be added (e.g., .in.3 .3, etc.).

Build Rules

A build rule is required to translate input to output. Let's begin with a general rule to establish that the mdoc syntax is correct. We'll add this to the target building the main system: this way, all changes to the mdoc input file will be syntax-checked when make is invoked. We'll use mandoc to syntax-check the document.

.in.1.1:
    mandoc -Tlint $<
    #nroff -mandoc $< >/dev/null
    cp -f $< $@

We also need to build the target and clean it. Assume that foo.1 is the output file and foo.in.1, the input.

all: foo foo.1

clean:
    rm -f foo foo.o foo.1

Result

Putting these together, the new Makefile is as follows:

.SUFFIXES: .in.1 .1

all: foo foo.1

clean:
    rm -f foo foo.o foo.1

install: all
    install -m 0755 foo /usr/local/bin
    install -m 0644 foo.1 /usr/local/share/man/man1

foo: foo.o
    cc -o foo foo.o

.in.1.1:
    mandoc -Tlint $<
    #nroff -mandoc $< >/dev/null
    cp -f $< $@

Formatted Output

Let's build an HTML manual with the make www rule. For simplicity, we won't install this file; it's merely for instruction. This rule will translate the built manual foo.1 into an HTML file foo.1.html.

.SUFFIXES: .in.1 .1 .1.html

Let's let our rule include a CSS file. Note that the traditional nroff utility doesn't include HTML output.

foo.1.html: style.css

.1.1.html:
    mandoc -Thtml -Ostyle=style.css $< >$@

The target rule is simply as follows:

www: foo.1.html

The reason for building from foo.1 instead of foo.in.1 is that we may wish to postprocess the foo.1 file after it has been created. However, this is entirely decision of the programmer.

Last edited by $Author: kristaps $ on $Date: 2012/01/01 15:13:33 $. Copyright © 2011, Kristaps Dzonsons. CC BY-SA.