\documentstyle[11pt]{article}

\addtolength{\oddsidemargin}{-.75in}
\addtolength{\evensidemargin}{-.75in}
\addtolength{\topmargin}{-1in}
\addtolength{\textwidth}{1.5in}
\addtolength{\textheight}{2in}
\setlength{\parindent}{0pt}
\setlength{\parskip}{.6\baselineskip}

\hyphenation{Nor-mal-Li-brary-Ob-ject-Rule}
\hyphenation{Lint-Li-brary-Ob-ject-Rule}

\newcommand{\pgraph}[1]{{\bf #1}\ }

\begin{document}
\thispagestyle{empty}

\section{Introduction}

This document is a short introduction to writing Imakefiles that use
the X11R4 Imake configuration files.  Although the X11R4 set is
extremely complex, only a rather small subset is required to build the
vast majority of programs and systems; I will describe what I consider
to be that subset.

There are two basic classes you have to be familar with to use Imake.
The first are the Make macros used in the Imake template file.  The
second are the C preprocessor macros defined in Imake.rules that, when
used, expand to produce valid Make rules to perform a certain action.
The Make macros used by Imake are all uppercase, just like normal
Make, and the C preprocessor macros are mixed case.

\section{Make Macros}

The commonly used macros that control the compiler and linker, such as
CFLAGS and LDFLAGS, are used by the configuration files as
conglomerates---each consists of the contents of several other
variables.  Instead, the Imake template expects similar options to be
placed in macros defined by the following table.

\begin{tabular}{ll}
{\bf Option} & {\bf Macro} \\
-I & INCLUDES \\
-D & DEFINES \\
-g, -O & CDEBUGFLAGS \\
-L, -y & CDEBUGFLAGS \\
-llibnam & LDLIBS 
\end{tabular}

\section{CPP Macros}

The real power of Imake comes from its use of C preprocessor macros to
abtract away the machine-specific details of performing certain tasks.
If you want to compile a program, for example, you might use the macro
CompileProgram in an Imakefile that looks something like this.

\begin{verbatim}
SRCS = foo1.c foo2.c
OBJS = foo1.o foo2.o

DEFINES = -DRANDOM_DEFINE
LDLIBS = -lm

CompileProgram(foo, $(OBJS))
\end{verbatim}

(Note that CompileProgram is not actually in the X11R4 distribution;
it is an example.)  Imake would then combine your Imakefile with the
Imake.rules file that contains a machine-specific definition of
CompileProgram, resulting in a Makefile that will build the program
{\it foo} from the source files {\it foo1.c} and {\it foo2.c} for your
particular architecture.

There are some macros that do not take any arguments; for example, the
macros that define the pattern rules that tell Make how to convert C
files into object files.  To use these macros, just put the name
followed by () anywhere in your Imakefile.  For example, if you wanted
to build profiled versions of {\it foo1.c} and {\it foo2.c}, you would
put
\begin{verbatim}
ProfiledObjectRule()
\end{verbatim}
somewhere in the previous Imakefile.

The following sections describe the different classes of Imake macros
and what they are used for.

\subsection{Object Files}

There are several different rules available for building object files
from source files; you can use whichever is appropriate for a
particular program or library.  For a reason that is not entirely
clear to me, many of the rules are named ``-LibraryObjectRule'' even
though they just work just as well for building program object files.

\pgraph{NormalLibraryObjectRule} This rule builds objects in the
normal way, although it deletes the target object before compiling it.

\pgraph{ProfiledLibraryObjectRule}  This rule builds both normal
object files and profiled object files.  A ``make all'' will ensure
that the directory {\it profiled} exists and a ``make clean'' will
delete all object files in the profiled directory.

\pgraph{DebuggedLibraryObjectRule}  This rule works exactly as
ProfiledLibraryObjectRule, except it adds the -g option when compiling
and uses the directory {\it debugger}.

\pgraph{DebuggedAndProfiledLibraryObjectRule}  This rule works
exactly as you would expect.

\pgraph{SpecialObjectRule(objs, depends, options)} This rule
generates a rule to compile {\it objs} with dependencies {\it
depends}, using CFLAGS and any additional options specified in {\it
options}.  Profiled, Debugged, and ProfiledAndDebugged versions of
this rule also exist.

\subsection{Programs}

\pgraph{SimpleProgramTarget(program)}  This macro generates rules
to build a single program, {\it program}, that contains a single,
self-named source file.

\pgraph{NormalProgramTarget(program, objects, deplibs, locallibs,
syslibs)} This macro generates rules to compile, link, and clean {\it
program}, which will depend on {\it objects} and {\it deplibs}, and be
linked against both {\it locallibs} and {\it syslibs}.  The idea is
that the former will likely also be dependencies and probably explicit
paths into the current build tree, while the latter will be libraries
that are assumed to be built on the system (such as -lm).  This macro
does not explicitly depend on any global macros other than CFLAGS and
LDOPTIONS, so you can use it multiple times in a single Imakefile.
Note that NormalProgramTarget does {\it not} cause ``make all'' to
build the program; use AllTarget({\it program}) for that.

\pgraph{ComplexProgramTarget(program)} This macro's name is
misleading; a ``complex'' program is merely defined as one that can be
built, installed, depended, cleaned, linted, and have a manual page.
It builds the program {\it program}, assuming its object list is in
OBJS and its library list in LDLIBS.  It generates rules so that make
{\it program}, all, install, clean, depend, and lint do the right
thing.  (The program is installed in BINDIR, the man page in MANDIR.)
Since it uses global macros, you can only use this once per Imakefile.

\pgraph{ComplexProgramTargetN(program)} These macros, with N
replaced with 1 through 4, work exactly like ComplexProgramTarget
except that the names of the global macros they expect are also
appended with N.  They are designed to allow multiple
ComplexProgramTargets within a single Imakefile.

\subsection{Libraries}

\pgraph{NormalLibraryTarget(libname, objlist)}  This macro produces
a normal library, using ar and ranlib, from the object files in {\it
objlist}.  ``make all'' will build {\it libname}.

\pgraph{ProfiledLibraryTarget(libname, objlist)}  This macro
produces a library in the normal way, with ar and ranlib, using the
files in {\it objlist} from the {\it profiled} directory.  It assumes
you are using ProfiledLibraryObjectRule.  The library will be named
{\it libname\_p.a} in the {\it profiled} directory, and ``make all''
will build it.

\pgraph{DebuggedLibraryTarget(libname, objlist)}  This macro builds
a normal library from the files in {\it objlist} in the {\it debugged}
directory.  A ``make all'' will build the library.

\pgraph{LintLibraryTarget(libname, srclist)}  This macro builds a
lint library named {\it llib-llibname.ln} from the source files in
{\it srclist}.  A ``make lintlib'' will make the library.

\subsection{Subdirectories}

\pgraph{NamedTargetSubdirs(name, dirs, verb, flags, subname)}  This is
a general subdirectory target.  It produces a rule such that ``make
{\it name}'' will perform a ``make {\it subname}'' in each of {\it
dirs}, passing {\it flags} in addition to MFLAGS to each recursive
call to make, and printing out a message containing {\it verb} and
each directory name as it gets there.  For example, 
\begin{verbatim}
NamedTargetSubdirs(clean_subdirs, $(SUBDIRS), cleaning,, clean)
\end{verbatim}
will cause a ``make clean\_subdirs'' in the current directory to run
``make clean'' for each subdirectory listed in SUBDIRSDIRS, printing
out ``cleaning in {\it current directory}'' for each one.

\pgraph{MakeSubdirs(dirs)}  This macros causes ``make all'' to
perform a ``make all'' in all directories in {\it dirs}.  It is
frequently used in the top-level Imakefile of a large system.  It
expands to a call to NamedTargetSubdirs, with {\it flags} set to
``PassCDebugFlags.''  Thus, if you want the top-level CDEBUGFLAGS,
such as -O or -g, to propagate down to all subdirectory makes, put 
\begin{verbatim}
#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
\end{verbatim}
in the current Imakefile (if you only want this particular Imakefile
to do the propagation) or in an appropriate configuration file.
Otherwise, be sure to define this macro to the empty string.  (This
should be done in the project configuration file.)

\pgraph{DependSubdirs(dirs), {\it et al}} DependSubdirs, as well as
Install-, InstallMan-, Include-, Clean-, Tag-, and MakefileSubdirs,
turn into an appropriate call to NamedTargetSubdir, such that ``make
{\it name}'' will call ``make {\it name}'' in all the subdirectories
in {\it dirs}.  The install rules propagate DESTDIR, the clean rule
propagates RM\_CMD, and the tags rule propagates TAGS, all through the
{\it flags} argument.  Note that MakefileSubdirs actually defines a
rule for Makefiles.

\pgraph{MakeMakeSubdirs(dirs, target)} This macro causes ``make
{\it target}'' to rebuild the Makefile and then run ``make Makefiles''
in each directory in {\it dirs}.  It is most useful if you want to be
able to separately specify several different sets of directories that
will have ``make Makefiles'' work on them; for example, if you only
want to have ``make Makefiles'' work on a given subdirectory if a
certain symbol is defined, but you always want it to work on a list of
subdirectories.  You cannot use MakeSubdirs twice because you can only
have one copy of a particular rule produced by that macro.

\subsection{Installation}

\pgraph{InstallProgram(program, dest)}  This macro generates rule to
install {\program} in {\it dest} on a ``make install.''

\pgraph{InstallProgramWithFlags(program, dest, flags)}  This macro is
just like InstallProgram except that the install program is passed the
additional flags {\it flags}.

\pgraph{InstallLibrary(libname, dest)}  This macro generates rules to
install the library lib{\it libnam}.a in the directory {\it dest} on a
``make install.'' The install target will depend on the library.

\pgraph{InstallLintLibrary(libname, dest)}  This macro generates rules
to install the lint library llib-l{\it libname}.ln in {\it dest} on a
``make install.ln.''  The install target will depend on the lint library.

\pgraph{InstallManPage(file, dest)}  This macro generates rules to
install the man page {\it file}.man in {\it dest} on a ``make
install.man.''  This install target will depend on {\it file}.man.

\pgraph{InstallMultiple(list, dest)} This macro generates rules to
install the files in {\it list} in {\it dest} on a ``make install.''
The install target will depend on all files in the list.

\section{BUGS}

Makefile depends on IMAKE.  The first action for IMAKE is a silent if,
and if it fails Make simple exits with ``error code 1,'' and no
message.

There is no way to say ``have make depend work on these files.''

ProfiledLibraryObjectRule makes ``all::'' check to see if the profiled
directory exists; but this happens AFTER the object files have been
compiled.

\end{document}

