.\"
.\" these macros are used in addition to the -ms macros.
.so tmac.wrprc
.\"
.\" $(TBL) thisfile | $(TROFF) $(MSMACROS) > output
.\"
.\" revision date - change whenever this file is edited
.ds RD 15 July 1996
.\"
.EH 'WRPRC2 \fIImakefile\fP Writing'- % -''
.OH ''- % -'WRPRC2 \fIImakefile\fP Writing'
.OF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr'
.EF 'Revision date:\0\0\*(RD''Printed:\0\0\n(dy \*(MO 19\n(yr'
.\"
.TL
Writing Imakefiles Using the
.sp .3v
WRPRC2 Configuration Files
.AU
Paul DuBois
dubois@primate.wisc.edu
.AI
Wisconsin Regional Primate Research Center
Revision date:\0\0\*(RD
.LP
This document is a tutorial showing how to write Imakefiles using
Release 2 of the WRPRC imake configuration files.
It explains the more commonly used rules and parameters
and provides example Imakefiles illustrating how to use them.
.LP
The tutorial doesn't cover all of the rules and parameters that are available.
A separate document serves as a reference describing the contents of the
individual configuration files.
.\"
.Ah "Imakefile Writing"
.\"
.LP
To use
.I imake ,
you write an
.I Imakefile
containing descriptions of targets you want to build.
Then you use
.I imake
to generate a
.I Makefile
from the
.I Imakefile
(typically by running the
.I imboot
bootstrapper, which runs
.I imake
for you.)
The
.I Imakefile
is a machine-independent description of your targets.
.I imake
generates the properly configured machine-dependent
.I Makefile
that's appropriate for your system.
Once you have the
.I Makefile ,
you run
.I make
to build your targets.
.LP
To generate the initial
.I Makefile
from an
.I Imakefile ,
use
.I imboot :
.Ps
% \f(CBimboot -C WRPRC2\fP \f(CItopdir\fP
.Pe
.Ci topdir
is the location of the project root directory, specified
either relative to your current directory or as an absolute path.
If you are in the project root,
.Ci topdir
may be omitted.
.I imboot
runs
.I imake
for you with the appropriate arguments for selecting the WRPRC2
configuration files.
.LP
If you edit an
.I Imakefile
thereafter, you must rebuild the
.I Makefile
so it reflects the changes.
If you've already got a
.I Makefile ,
you can use it to rebuild itself with the following command:
.Ps
% \f(CBmake Makefile\fP
.Pe
If your changes to the
.I Imakefile
are erroneous and result in an unusable
.I Makefile ,
fix the
.I Imakefile
and use
.I imboot
again to regenerate a working
.I Makefile .
.LP
If your directory has subdirectories,
use this command to build the Makefiles in those directories:
.Ps
% \f(CBmake Makefiles\fP
.Pe
If you're writing C programs, you should regenerate header file dependencies
each time you rebuild a
.I Makefile :
.Ps
% \f(CBmake depend\fP
.Pe
Makefiles generated from the WRPRC2 configuration files automatically
contain a
.Cw help
target entry.
This means you can run the following command to find out how to build the
other targets listed in the
.I Make\%file :
.Ps
% \f(CBmake help\fP
.Pe 0
.\"
.Ah "Building and Installing Programs"
.\"
.LP
This section describes the rules provided by the WRPRC2 configuration
files for building programs and libraries.
.\"
.Bh "Building a Single Program"
.\"
.LP
To build a single program that consists of one source file,
use
.Cw BuildSimpleProgram() .
This rule takes three arguments:
.Ps
BuildSimpleProgram(\f(CIprog\fP,\f(CIlinklibs\fP,\f(CIdeplibs\fP)
.Pe
The first argument is the name of the program;
.Cw BuildSimpleProgram()
assumes there is a single source file named
.Ci prog\fI.c\fP
and a single object file
.Ci prog\fI.o\fP .
The second argument names the libraries needed to link the program, and
the third names the libraries the program depends on.
.LP
If a program uses no libraries, the
.I Imakefile
looks like this:
.Ps
BuildSimpleProgram(myprog,NullArg,NullArg)
.Pe
This specifies you want to build a program
.I myprog .
The second and third arguments are empty, which is specified explicitly using
.Cw NullArg .
The symbol
.Cw NullArg
evaluates to nothing; it's preferable to leaving the arguments empty because
that causes problems building the
.I Makefile
on some systems.
.LP
If a program uses libraries, you need to specify what they are.
The libraries the program depends on are the same as the link libraries,
but the value of
.Ci deplibs
is often different than
.Ci linklibs
because
.Ci deplibs
can consist only of libraries that can be named as pathnames
.I make "" (
understands pathnames only as dependencies, not libraries specified
using
.I \-l
syntax).
A system library is usually specified using
.I \-l
and thus has no dependency specifier.
.LP
Suppose a program uses the math library, you can write the
.I Imakefile
like this:
.Ps
BuildSimpleProgram(myprog,-lm,NullArg)
.Pe
The math library is specified as
.I \-lm
for linking, but since it's a system library, there's no dependency specifier
for it and
.Ci deplibs
is empty.
.LP
Suppose a program needs a library
.I mylib
that's located in the
.I lib
directory under the project root.
You can refer to it as
.Cw $(TOP)\fI/lib/libmylib.a\fP ,
because
.Cw TOP
always refers to the top of the project tree.
Since that reference is a pathname, you can use it not only for linking, but
for dependency purposes as well:
.Ps
BuildSimpleProgram(myprog,$(TOP)/lib/libmylib.a,$(TOP)/lib/libmylib.a)
.Pe
.Cw BuildSimpleProgram()
can be invoked only once per
.I Imakefile .
It generates target entries for the following operations:
.Ps
% \f(CBmake\fP \f(CIprog\fP						\fRBuild program\fP
% \f(CBmake\fP							\fRSame as \f(CWmake\fP \f(CIprog\f(CW
% \f(CBmake all\fP						\fRSame as \f(CWmake
% \f(CBmake clean\fP					\fRRemove object and executable files\fP
% \f(CBmake lint\fP						\fRRun sources through \fIlint\f(CW
% \f(CBmake install\fP					\fRInstall program\fP
% \f(CBmake install.man\fP				\fRInstall program's manual page\fP
.Pe
The
.Cw install
target installs the program in the directory named by
.Cw LOCALBINDIR ,
which by default is your site's normal installation directory for user
programs.
The
.Cw install.man
target installs the manual page in the directory named by
.Cw MANDIR ,
(your site's normal directory for user program manual pages) with the
suffix named by
.Cw MAN\%SUFFIX .
Of course, the
.Cw install.man
target entry only works if you write a manual page; if you do, name it
.Ci prog\fI.man\fP .
.LP
Note that for all installation operations,
the installation directory is created if it doesn't exist.
That means it's prudent to run
.I make
.I \-n
.I install
(or
.I make
.I \-n
.I install.man )
before you run
.I make
.I install
(or
.I make
.I \-n
.I install.man ),
to see where your files will be installed.
If the installation directories are somewhere other than what you expect
or intend, you need to redefine
.Cw Local\%Bin\%Dir
and/or the manual page installation location macros in the configuration files.
Alternatively, you can redefine the
.Cw LOCAL\%BIN\%DIR
or the
.Cw MAN\%DIR
and
.CW MAN\%SUFFIX
.I make
variables on the command line:
.Ps
% \f(CBmake install LOCALBINDIR=/var/local/bin\fP
% \f(CBmake install.man MANDIR=/var/local/man/man1 MANSUFFIX=1\fP
.Pe
.\"
.Bh "Building and Installing Multiple Programs"
.\"
.LP
The general-purpose interface for building programs is
.Cw BuildProgram() .
You can invoke this rule any number of times in an
.I Imakefile ,
so it's suitable for building an arbitrary number of programs in a single
directory.
.LP
Suppose you're building three programs
.I proga ,
.I progb ,
and
.I progc .
Your
.I Imakefile
might look like this:
.Ps
BuildProgram(proga,proga.c,proga.o,NullArg,NullArg)
BuildProgram(progb,bmain.c bfuncs.c,bmain.o bfuncs.o,-lm,NullArg)
BuildProgram(progc,progc.c,progc.o,NullArg,NullArg)
.Pe
The arguments to
.Cw BuildProgram()
are the program name, the program's source and object files,
and the program's link and dependency libraries.
.LP
There are certain improvements we can make to the
.I Imakefile .
For one thing, we can make the the rule invocations
more readable by using
.I make
variables to hold the source and object file lists, and the link and
dependency libraries.
Then we refer to the variables in the invocations:
.Ps
   ASRCS = proga.c
   AOBJS = proga.o
   ALIBS =
DEPALIBS =
.sp .3v
   BSRCS = bmain.c bfuncs.c
   BOBJS = bmain.o bfuncs.o
   BLIBS = -lm
DEPBLIBS =
.sp .3v
   CSRCS = progc.c
   COBJS = progc.o
   CLIBS =
DEPCLIBS =
.sp .3v
BuildProgram(proga,$(ASRCS),$(AOBJS),$(ALIBS),$(DEPALIBS))
BuildProgram(progb,$(BSRCS),$(BOBJS),$(BLIBS),$(DEPBLIBS))
BuildProgram(progc,$(CSRCS),$(COBJS),$(CLIBS),$(DEPCLIBS))
.Pe
These changes also make the
.I Imakefile
easier to edit.
.LP
.Cw BuildProgram()
generates target entries for the following operations:
.Ps
% \f(CBmake\fP \f(CIprog\fP						\fRBuild a single program\fP
% \f(CBmake all\fP						\fRBuild all programs\fP
% \f(CBmake\fP							\fRSame as \fPmake\fP \fPall
% \f(CBmake clean\fP					\fRRemove object and executable files\fP
% \f(CBmake lint\fP						\fRRun sources through \fRlint\f(CW
% \f(CBmake lint.\f(CIprog\f(CW				\fRRun \f(CIprog\fP sources through \fIlint\f(CW
.Pe
The commands
.I make
or
.I make
.I all
build all programs in the
.I Makefile ,
whereas
.I make
.Ci prog
builds only
.Ci prog .
This is useful when you don't want to build everything.
Similarly,
.I make
.I lint
runs the source files for all programs through
.I lint ,
whereas
.I make
.Ci \fIlint.\fPprog
lints only the sources for
.Ci prog .
This is useful when you make a change to the sources for only one program and
don't want to
.I lint
everything.
.LP
.Cw BuildProgram()
doesn't generate any
.Cw depend
target, so we should invoke
.Cw DependTarget()
to do that.
.Cw DependTarget()
implicitly assumes the
.I make
variable
.Cw SRCS
is set to the names of all the source files for which dependencies
should be generated.
It's convenient to set
.Cw SRCS
to the concatenation of the variables used to name the sources for
individual programs:
.Ps
   ASRCS = proga.c
   AOBJS = proga.o
   ALIBS =
DEPALIBS =
.sp .3v
   BSRCS = bmain.c bfuncs.c
   BOBJS = bmain.o bfuncs.o
   BLIBS = -lm
DEPBLIBS =
.sp .3v
   CSRCS = progc.c
   COBJS = progc.o
   CLIBS =
DEPCLIBS =
.sp .3v
    SRCS = $(ASRCS) $(BSRCS) $(CSRCS)
.sp .3v
BuildProgram(proga,$(ASRCS),$(AOBJS),$(ALIBS),$(DEPALIBS))
BuildProgram(progb,$(BSRCS),$(BOBJS),$(BLIBS),$(DEPBLIBS))
BuildProgram(progc,$(CSRCS),$(COBJS),$(CLIBS),$(DEPCLIBS))
.sp .3v
DependTarget()
.Pe
Note that
.Cw DependTarget()
shouldn't be invoked before the program-building rules or
.Cw depend
will become the default target.
.LP
No installation target entries are generated by
.Cw BuildProgram() .
To install a program, invoke
.Cw InstallProgram() :
.Ps
InstallProgram(\f(CIprog\fP,\f(CIdir\fP)
.Pe
.Ci prog
is the name of the program and
.Ci dir
is the directory in which to install it.
.Cw LOCALBINDIR
can be used to install the program in your site's ``usual''
user program installation directory.
For example:
.Ps
InstallProgram(proga,$(LOCALBINDIR))
.Pe
.Cw InstallProgram()
generates target entries for the following operations:
.Ps
% \f(CBmake install\fP					\fRInstall all programs built by the \fIMakefile\f(CW
% \f(CBmake i.\f(CIprog\f(CW					\fRInstall only \f(CIprog\f(CW
.Pe
If you write a manual page for
.Ci prog ,
name it
.Ci prog\fI.man\fP
and invoke
.Cw InstallManPage() :
.Ps
InstallManPage(\f(CIprog\fP)
.Pe
Note that you specify only the program name (without the
.I .man
suffix).
.Cw InstallManPage()
generates target entries for the following operations:
.Ps
% \f(CBmake install.man\fP				\fRInstall manual pages for all programs built by the \fIMakefile\f(CW
% \f(CBmake i.\f(CIprog\fP.man\f(CW				\fRInstall manual page only for \f(CIprog\f(CW
.Pe
Manual pages are installed in your site's ``usual'' directory for user program
manual pages.
.LP
After modifying the
.I Imakefile
to add installation rules for our programs and manual pages,
it looks like this:
.Ps
   ASRCS = proga.c
   AOBJS = proga.o
   ALIBS =
DEPALIBS =
.sp .3v
   BSRCS = bmain.c bfuncs.c
   BOBJS = bmain.o bfuncs.o
   BLIBS = -lm
DEPBLIBS =
.sp .3v
   CSRCS = progc.c
   COBJS = progc.o
   CLIBS =
DEPCLIBS =
.sp .3v
    SRCS = $(ASRCS) $(BSRCS) $(CSRCS)
.sp .3v
BuildProgram(proga,$(ASRCS),$(AOBJS),$(ALIBS),$(DEPALIBS))
InstallProgram(proga,$(LOCALBINDIR))
InstallManPage(proga)
.sp .3v
BuildProgram(progb,$(BSRCS),$(BOBJS),$(BLIBS),$(DEPBLIBS))
InstallProgram(progb,$(LOCALBINDIR))
InstallManPage(progb)
.sp .3v
BuildProgram(progc,$(CSRCS),$(COBJS),$(CLIBS),$(DEPCLIBS))
InstallProgram(progc,$(LOCALBINDIR))
InstallManPage(progc)
.sp .3v
DependTarget()
.Pe 0
.\"
.Bh "Building and Installing a Library"
.\"
.LP
The WRPRC2 configuration files provide support only for building static
libraries.
There is no support for shared libraries.
.LP
To build a library, invoke
.Cw BuildNormalLibrary() ,
passing it the library basename and the source file and object file lists.
(If a library's name is
.I libxyz.a ,
the basename is
.I xyz ).
You should invoke
.Cw NormalLibraryObjectRule()
in conjunction with
.Cw BuildNormalLibrary()
so that
.I .o
files are built in a way suitable for libraries.
You should also set the
.I make
variable
.Cw SRCS
and invoke
.Cw DependTarget()
so that
.I make
.I depend
works.
Thus, a typical library-building
.I Imakefile
looks like this:
.Ps
OBJS = ...
SRCS = ...
.sp .3v
NormalLibraryObjectRule()
BuildNormalLibrary(name,$(SRCS),$(OBJS))
DependTarget()
.Pe
.Cw NormalLibraryObjectRule()
may redefine the default
.I .c
\(->
.I .o
transformation that
.I make
uses to produce object files, so it's best not to build
programs in a directory that's used to build a library or libraries.
.LP
.Cw BuildNormalLibrary()
generates target entries for the following operations:
.Ps
% \f(CBmake lib\f(CIname\fP.a\f(CW				\fRBuild library \fP\f(CIname\f(CW
% \f(CBmake all\fP						\fRBuild all libraries\fP
% \f(CBmake\fP							\fRSame as \f(CWmake\fP \fPall
% \f(CBmake clean\fP					\fRRemove object and library files\fP
% \f(CBmake lint\fP						\fRRun all sources through \fIlint\f(CW
% \f(CBmake lint.lib\f(CIname\fP.a\f(CW			\fRRun sources for library \f(CIname\fP through \fIlint\f(CW
.Pe
.Cw BuildNormalLibrary()
does not generate any installation target entries; use
.Cw Install\%Library()
to install a library:
.Ps
InstallLibrary(\f(CIname\fP,\f(CIdir\fP)
.Pe
The
.Ci dir
parameter is often
.Cw LOCALUSRLIBDIR ,
which by default is
.I /usr/local/lib .
.Cw InstallLibrary()
generates entries for the following operations:
.Ps
% \f(CBmake install\fP					\fRInstall all libraries\fP
% \f(CBmake i.lib\f(CIname\fP.a\f(CW				\fRInstall only library \f(CIname\f(CW
.Pe
You can invoke
.Cw BuildNormalLibrary()
any number of times to build an arbitrary number of libraries.
Example:
.Ps
OBJS1 = ...
SRCS1 = ...
.sp .3v
OBJS2 = ...
SRCS2 = ...
.sp .3v
 SRCS = $(SRCS1) $(SRCS2)
.sp .3v
NormalLibraryObjectRule()
.sp .3v
BuildNormalLibrary(lib1,$(SRCS1),$(OBJS1))
InstallLibrary(lib1,$(LOCALUSRLIBDIR))
.sp .3v
BuildNormalLibrary(lib2,$(SRCS2),$(OBJS2))
InstallLibrary(lib2,$(LOCALUSRLIBDIR))
.sp .3v
DependTarget()
.Pe
Note that you invoke
.Cw NormalLibraryObjectRule()
just once.
.\"
.Ah "Other Installation Rules"
.\"
.LP
The WRPRC2 files provide a number of installation rules besides
.Cw Install\%Program() ,
.Cw Install\%Library() ,
and
.Cw Install\%Man\%Page() .
Some of the more common ones are:
.Ps
InstallScript(file,dir)			\fRInstall an executable script\fP
InstallDataFile(file,dir)		\fRInstall a non-executable file\fP
InstallIncludeFile(file,dir)	\fRInstall a header file\fP
.Pe
You can install manual pages in directories other than the ``usual''
directory.
To install a page explicitly in the directory for a given manual section,
invoke
.Cw InstallMan\f(CIS\fPPage() ,
where
.Ci S
is 1, 2, 3, 4, 5, 6, 7, 8, L, or N.
As with
.Cw InstallManPage() ,
the name of the file to be installed should end in a
.I .man
suffix, but the argument to the rule does not include the suffix.
The installed manual page will be renamed appropriately for the directory
into which it's installed.
.\"
.Ah "Naming WRPRC Libraries"
.\"
.LP
At WRPRC, several locally-developed libraries are commonly used to build
programs.
The WRPRC2 configuration files provide link and dependency specifiers for
them.
The following table lists
the specifiers provided by the WRPRC2 configuration files.
For every library
.Ci XXX ,
there is a
.Ci XXX\f(CWLIB\fP
variable for link purposes and a
.Ci \f(CWDEP\fPXXX\f(CWLIB\fP
variable for dependency purposes.
.ps -2
.vs -2
.TS
tab(:);
lfB | lfB | lfB
lfB | lfB | lfB
l | lfCW | lfCW .
Library:Link:Dependency
Name:Specifier:Specifier
_
\fIrefer\fP record manipulation library:BIBSTUFFLIB:DEPBIBSTUFFLIB
Exception and termination manager library:ETMLIB:DEPETMLIB
Form processing library:FPLLIB:DEPFPLLIB
Form query library:FQLLIB:DEPFQLLIB
GECOS library:GECOSLIB:DEPGECOSLIB
Simple log manager library:LOGMGRLIB:DEPLOGMGRLIB
Simple memory manager library:MEMMGRLIB:DEPMEMMGRLIB
Network database service library:NDSLIB:DEPNDSLIB
Network I/O library:NIOLIB:DEPNIOLIB
Order processing library:ORDERLIB:DEPORDERLIB
Sequence number library:SEQNUMLIB:DEPSEQNUMLIB
Simple screen-management library:SIMSCRLIB:DEPSIMSCRLIB
Temporary file manager library:TFMlIB:DEPTFMLIB
Token scanning library:TSLIB:DEPTSLIB
_
.TE
.vs +2
.ps +2
.LP
Example:
Suppose a program
.I myprog
is built from
.I prog.c
and the ETM, memory manager, and token scanning libraries.
The
.I Imakefile
might look like this:
.Ps
   LIBS = $(MEMMGRLIB) $(TSLIB) $(ETMLIB)
DEPLIBS = $(DEPMEMMGRLIB) $(DEPTSLIB) $(DEPETMLIB)
.sp .3v
BuildSimpleProgram(myprog,$(LIBS),$(DEPLIBS))
.Pe
.\"
.Ah "Multiple-Directory Support"
.\"
.LP
If a directory has subdirectories, normally you want
.I make
to traverse those subdirectories when you run it.
Write the
.I Imakefile
like this:
.Ps
#define IHaveSubdirs
#define PassCDebugFlags
.sp .3v
SUBDIRS = \f(CIlist\fP
.Pe
where
.Ci list
is a space-separated list of the subdirectories that should be processed
by
.I make ,
in the order you want them processed.
For example:
.Ps
#define IHaveSubdirs
#define PassCDebugFlags
.sp .3v
SUBDIRS = include lib apps doc man
.Pe
After you build the
.I Makefile ,
it will contain recursive entries for
.Cw all ,
.Cw depend ,
.Cw install ,
.Cw install.man ,
.Cw clean ,
.Cw tags ,
and
.Cw Makefiles
targets.
.LP
If you anticipate that you'll want to build debuggable targets,
define
.Cw PassCDebugFlags
like this instead:
.Ps
#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
.Pe
Then you can specify debugging flags from the
.I make
command line, e.g.:
.Ps
% \f(CBmake CDEBUGFLAGS=-g\fP
.Pe 0
.\"
.Ah "Generating a World Target"
.\"
.LP
You can invoke
.Cw SimpleWorldTarget() 
in the
.I Imakefile
in a project's root (top-level) directory to generate a
.Cw World
target entry.
Then you can say
.I make
.I World
to build the entire project from scratch (including configuring its Makefiles).
Note that if your project is at all complex, it may require a configure/build
sequence that varies from the simple
.Cw World
entry provided by
.Cw SimpleWorldTarget() .
In this case you'll need to write your own
.Cw World
entry by hand.
.LP
.Cw SimpleWorldTarget()
takes the project name and release level as arguments:
.Ps
SimpleWorldTarget(\f(CIproject\fP,\f(CIrelease\fP)
.Pe
If your project has a
.I config
directory for private configuration information, it's useful to create a file
.I Imake.p-params
there to override the macros that define the project name and release numbers.
For example:
.Ps
#ifndef ProjectName
#define ProjectName My Project Name
#endif
#ifndef ProjectMajorRelease
#define ProjectMajorRelease 1
#endif
#ifndef ProjectMinorRelease
#define ProjectMinorRelease 03
#endif
.Pe
Then you can invoke
.Cw SimpleWorldTarget()
using the associated
.I make
variables:
.Ps
SimpleWorldTarget($(PROJECTNAME),$(PROJECTRELEASE))
.Pe
In this case, whenever you change the release numbers in
.I Imake.p-params ,
you don't have the change the project root
.I Imakefile .
However, you do need to rebuild the
.I Makefile
so it gets the updated release numbers.
.LP
If your project builds targets in multiple directories, the root
.I Imakefile
might look like this:
.Ps
#define IHaveSubdirs
#define PassCDebugFlags
.sp .3v
SUBDIRS = \f(CIlist\fP
.sp .3v
SimpleWorldTarget($(PROJECTNAME),$(PROJECTRELEASE))
.Pe
.\"
.Ah "Formatting Documents"
.\"
.LP
The WRPRC2 files contain rules for producing PostScript files from
.I troff
documents.
In most cases, a
.I troff
document is formatted using the
.I \-man ,
.I \-me ,
.I \-mm ,
or
.I \-ms
macros, possibly after having been run through one or more preprocessors
such as
.I tbl
or
.I pic .
.LP
For instance,
to produce a PostScript file
.I doc.ps
from a document
.I doc.ms
that requires the
.I \-ms
macros but no preprocessors, write this:
.Ps
TroffMsToPostScript(doc.ps,doc.ms,NullArg,NullArg)
.Pe
The arguments to
.Cw TroffMsToPostScript()
are the destination output file, the input source file (or
files), the
preprocessor list, and any dependencies that must exist before the source
can be processed.
The preprocessor list must be given in the form of a piece of a command
pipeline, beginning with ``|''.
For example, to run the input through
.I pic ,
use this:
.Ps
TroffMsToPostScript(doc.ps,doc.ms,|$(PIC),NullArg)
.Pe
To run the input through
.I tbl
and
.I eqn ,
use this:
.Ps
TroffMsToPostScript(doc.ps,doc.ms,|$(TBL)|$(EQN),NullArg)
.Pe
.LP
To format a document with one of the other macro packages, change the ``Ms''
in the rule name to
``Man'', ``Me'', or ``Mm''.
.\"
.Ah "Default Target Entries"
.\"
.LP
The WRPRC2 configuration files provide several target entries in the
.I Makefile
for you.
Some of them actually do something, others are simply placeholders to prevent
errors when certain
.I make
operations are performed.
.IP \(bu
A
.Cw help
entry is provided allowing
.I make
.I help ,
which indicates some typical
.I make
commands and what they do.
.IP \(bu
A
.Cw Makefile
entry is produced so you can run
.I make
.I Makefile
to rebuild the
.I Makefile
after you make changes to the
.I Imakefile .
.IP \(bu
A default
.Cw clean
entry is produced that removes typical garbage files such as
.I *.o ,
.I *.a ,
and
.I *.bak
files, and
.I core .
.B Note:
Unlike the default
.Cw clean
entry produced by the X11 rules, the WRPRC2 default
.Cw clean
entry does not remove
.I *~
files; this is because my own convention for creating backup files is
to use
.Cw ~
rather than
.I \&.bak .
.IP \(bu
A
.Cw tags
entry is provided so you can say
.I make
.I tags .
.IP \(bu
If the
.I Imakefile
is for a directory with subdirectories, recursive
.Cw all ,
.Cw depend ,
.Cw install ,
.Cw install.man ,
.Cw clean ,
.Cw tags ,
and
.Cw Makefiles
entries are produced.
If the directory doesn't have subdirectories, dummy targets for these
operations are produced as necessary so that
.I make
doesn't generate errors (this is necessary or recursive
.I make
operations would fail as soon as they reached a directory with no
subdirectories).
