.so /research/devel/khaos/manual/utils/tmac.manual
.ds f. imake.man
.\"
.\" I - italic font (taken from -ms and changed)
.de I
.nr PQ \\n(.f
.if t \&\\$3\\f2\\$1\\fP\&\\$2
.if n .if \\n(.$=1 \&\\$1
.if n .if \\n(.$>1 \&\\$1\c
.if n .if \\n(.$>1 \&\\$2
..
.\" start block.  LP gives a bit extra space. Can say .Ds .IP C, etc.
.de Ds
.if \\n(.$<1 .LP
.if \\n(.$>=1 \\$1
.if \\n(.$<2 .DS
.if \\n(.$>=2 .DS \\$2 \\$3 \\$4 \\$5
..
.\" end block.  If arg is given, it replaces the .LP (e.g., .De .IP).
.de De
.DE
.if \\n(.$<1 .LP
.if \\n(.$>=1 \\$1 \\$2 \\$3 \\$4 \\$5
..
.\" if the Sy definition changes, there are four symbols which had to be
.\" manually formatted and which need to be changed manually,
.\" UNCOMPRESSFILT, BDFTOSNFFILT, SHELLPATH, ZBDFTOSNFFILT
.de Sy		\" symbol definition
.br
.ne 3v
.ta 6iR
\fB\\$1\fR	\\$3
.br
\0\0default: \\$2
..
.de Ru		\" imake rule
.br
.ne 3v
.B \\$1
..
.ds RF \\n(PN
.J7
.K7 "Tom Sauer and Charlie Gage"
.K0 "Khoros \fBImake\fP Symbols and Variables"
.sp 2
.NH 1 "INTRODUCTION"
.XS
\s12\*(SN  INTRODUCTION\s0
.XE
.PP
The \fIcpp\fP symbols and \fBmake\fP
variables that define the Khoros configuration files 
in \fIKHOROS_HOME/repos/config/imake_conf\fP 
are listed and described in this appendix.
.PP
Besides symbols used for rule macros, symbols may be classed in
three categories.
Some are used as booleans and are defined as YES or NO.
Some are defined as nothing, and some are left undefined.
Boolean and defined/not-defined symbols are rarely if ever
associated with variables appearing in
.I Makefiles;
rather, they are used for control purposes to modify the configuration
and build process.
.PP
The other symbols are general-purpose, usually (but not always)
having a value that is assigned to some
.I Makefile
variable.
The value may be empty (that is, the symbol may be defined as nothing):
.Ds
#define\0\0\0\fIsymbol\fR\0\0\0/* as nothing */
.De
The descriptions below give symbol names, a short description
and their defaults.  A default of ``nothing'' means the 
empty definition. The following symbol definitions are
found in the \fIKhoros.tmpl\fP file, the \fISite.def\fP file,
the \fILibrary.def\fP file and the \fIplatform.cf\fP files.
.sp 2
.NH 2 "SYMBOL DESCRIPTIONS"
.XS
      \*(SN  SYMBOL DESCRIPTIONS
.XE
.PP
The default value of some symbols is determined based
on whether SystemV is YES or NO.
For these symbols both defaults are listed, with the SystemV=YES case first.
.sp 2
.LP
.Sy MacroIncludeFile <generic.cf> general
.Sy MacroFile generic.cf general
.IP
Both of these name the platform-specific file to be included by the
template after the header block section.
The defaults are deliberately rebarbative and are selected only if the
correct header block for your system was not triggered.
Otherwise these symbols will have values like
.I platform .cf> <
and
.I platform .cf,
where
.I platform
is ``ultrix'', ``sun'', ``hp'', ``apollo'', etc.
.IP
There are two symbols associated with this name because it is used two
different ways.
MacroIncludeFile is used by
.I cpp
to include the platform file.
MacroFile is used to generate file names.
.LP
.Sy SystemV varies boolean
.IP
SystemV indicates whether your system is System V based (YES) or not
(NO).
If not, that usually means BSD based.
The default value of many other symbols depends on SystemV, so it is
usually set explicitly early
in the platform-specific file to make sure it's correct.
.LP
.Sy OSMajorVersion "0" general
.Sy OSMinorVersion "0" general
.IP
These two symbols indicate the major and minor version numbers of the
operating system.
They are often used as control symbols in the platform files
to select symbol values that vary depending on the OS version.
For this reason, they are usually set in the platform file.
.IP
Example: if some feature of your OS didn't appear until version 5.7,
you could test for that with:
.Ds .IP
/**/# these definitions would go in the platform file
# ifndef OSMajorVersion
# define OSMajorVersion 5
# endif
# ifndef OSMinorVersion
# define OSMinorVersion 7
# endif

/**/# this test would go wherever you need to test for 5.7 and up
# if OSMajorVersion >= 5 && OSMinorVersion >= 7
	/**/# 5.7-and-up specific stuff here
# endif
.De
.LP
.Sy ExecableScripts "NO(SystemV)/YES(BSD)" boolean
.IP
Whether the kernel
.I exec ()
system call correctly executes scripts beginning with ``#!''.
ExecableScripts determines the way the CppScriptTarget() rule macro is
expanded and thus the way shell scripts are built.
.IP
Script prototypes begin with a line that says ``#!/bin/sh''.
If ExecableScripts is NO, that line is stripped out and replaced with
one that says ``:''.
.LP
.Sy BourneShell "/bin/sh" general
.IP
Path name of Bourne shell.
This is used to set the value of SHELL, and in construction of some
commands that run shell scripts.
.LP
.Sy ConstructMFLAGS "YES(SystemV)/NO(BSD)" boolean
.IP
Whether to construct MFLAGS
.B make
variable from MAKEFLAGS.
This is used for compatibility with versions of
.B make
that use MFLAGS instead of MAKEFLAGS.
.LP
.Sy HasLargeTmp "YES" boolean
.IP
Whether the file system on which
.I /tmp
resides has lots of free space.
The meaning of ``lots'' is roughly 1MB, although that may need to be revised
upward for future releases.
This symbol determines the default value of ArCmd.
.LP
.Sy HasSockets "NO(SystemV)/YES(BSD)" boolean
.IP
Whether the system has BSD socket support.
.LP
.Sy HasVFork "NO(SystemV)/YES(BSD)" boolean
.IP
Whether the
.I vfork ()
system call is supported.
Presumably this causes
.I fork()
to be used instead of
.I vfork()
if HaveVFork is NO.
.LP
.Sy HasPutenv "NO" boolean
.IP
Whether the
.I putenv ()
C library call is supported.
.LP
.Sy HasRandom "YES" boolean
.IP
Whether the
.I random ()
C library call can be used instead of
.I rand().
.LP
.Sy HasDirent "NO" boolean
.IP
Whether the
.I dirent
directory structure can be used instead of
.I direct.
.LP
.Sy HasBsdTypes "YES" boolean
.IP
Identifies how the system defines
.I u_char,
.I u_short,
etc.
.LP
.Sy HasWait3 "YES" boolean
.IP
Whether the system supports
.I wait3
system call.
.LP
.Sy ReDefFortran "NO" boolean
.IP
Whether C calls fortran as
.I name_
.LP
.Sy HasVoidSignalReturn "YES(SystemV)/NO" boolean
.IP
Whether the
.I signal ()
C library call returns
.I void *
(YES)
or
.I int *
(NO).
The default is YES for System V platforms, but
if you have a BSD platform, you should not assume NO.
Some BSD-based systems (e.g., Ultrix and Sun) have changed from
.I int *
to
.I void *
in new OS releases.
Some machines try to support both sets of semantics.
.LP
.Sy HasBsearch "YES(SystemV)/NO" boolean
.IP
Whether the
.I bsearch ()
C library call is supported.
.LP
.Sy HasSaberC "NO" boolean
.IP
Whether the system has the Saber C development environment.
The default value of this symbol will usually be overridden in the
platform file.
.B Warning:
some of the platform files define HasSaberC as YES, so be sure to
check this and change it if necessary.
.LP
.Sy HasFortran "YES" boolean
.IP
Whether the system has a FORTRAN compiler.
Needed for Linpack, Eispack, and FFT support.
.LP
.Sy ForSysLibs "\-lF77 \-lI77"  general
.IP
Specifies the Fortran libraries that your machine uses.
If 
.I HasFortran
is YES, then the default above is used, otherwise
it is set to 
.I nothing.
If 
.I ForSysLibs
is defined in the machine.cf file, that will override this definition.
.LP
.Sy ForLocalLibs "$(LINPACKLIB) $(EISPACKLIB)" boolean
.IP
The libraries needed for Linpack, and Eispack.
.LP
.Sy ForLocalDependLibs "$(DEPENDLINPACKLIB) $(DEPENDEISPACKLIB)" boolean
.IP
The libraries needed for Linpack, and Eispack.
.LP
.Sy HasSunOSSharedLibraries "NO" boolean
.IP
Whether SunOS shared libraries are supported.
.LP
.Sy SharedCodeDef "varies" general
.IP
Flags to compile sharable library code.
.LP
.Sy SharedLibraryDef "varies" general
.IP
Flags to turn on use of shared libraries.
.LP
.Sy HasSharedLibraries "varies" boolean
.IP
Whether shared libraries are supported.
.B Note:
This symbol is defined
.I inside
the (convoluted) definition of SharedLibraryDef.
.LP
.Sy StripInstalledPrograms "YES" boolean
.IP
If YES, strip symbol table from installed programs, otherwise leave intact.
Setting to YES can save lots of disk space on some machines, but
leaving it as NO can help during debugging.
This symbol affects use of InstPgmFlags.
.LP
.Sy DestDir nothing general
.IP
Prefix to prepend to installation directory pathnames.
Normally this is left empty. Unused symbol in Khoros at this time.
.LP
.Sy IncRoot "KHOROS_HOME/include" general
.IP
Path to root of the Khoros system header file hierarchy.
Khoros header files are installed under this.
.LP
.Sy UNCOMPRESSPATH "/usr/ucb/uncompress" general
.IP
Command to run the
.I uncompress
program.
This is used to uncompress compressed postscript files for the manual.
If you override this symbol, the definition should probably be a full
path name.
.LP
.Sy OptimizedCDebugFlags "\-O" general
.IP
C compiler flags to turn on optimization.
.LP
.Sy DebuggableCDebugFlags "\-g" general
.IP
C compiler flags to turn on debugging information.
.LP
.Sy NoOpCDebugFlags nothing general
.IP
C compiler flags to not turn on optimization or debugging.
.LP
.Sy DefaultCDebugFlags "OptimizedCDebugFlags" general
.IP
C compiler flags to turn on optimization for programs.
.LP
.Sy LibraryCDebugFlags "OptimizedCDebugFlags" general
.IP
C compiler flags to turn on optimization for libraries.
.LP
.Sy DefaultCCOptions nothing general
.IP
Special C compiler flags (other than \-I's and \-D's?
See StandardDefines, StandardCppDefines).
Useful, e.g., for turning on floating point options.
.LP
.Sy DefaultYFlags "\-d" general
.IP
Default flags for yacc.
Specify the default YFLAGS to re-generate (update)
the y.tab.h everytime the {file}.y is yacc'ed.
.LP
.Sy DefaultLFlags "\-n" general
.IP
Default flags for lex.
.LP
.Sy LibraryCCOptions "DefaultCCOptions" general
.IP
Special C compiler flags for compiling libraries.
.LP
.Sy InstPgmFlags "\-s" general
.IP
Flags for installing programs.
The default strips symbol tables.
This symbol is used in conjunction with StripInstalledPrograms to set
the
.B make
variable INSTPGMFLAGS.
Note that INSTPGMFLAGS applies to installs of
binary programs and also shell
scripts; some systems give a warning when you try to strip a script
because they have no symbol table (such warnings can be ignored).
.LP
.Sy InstBinFlags "\-m 0755" general
.IP
Flags for setting the mode of installed executable files.
.LP
.Sy InstLibFlags "\-m 0664" general
.IP
Flags for setting the mode of installed libraries.
.LP
.Sy InstIncFlags "\-m 0444" general
.IP
Flags for setting the mode of installed header files.
.LP
.Sy InstManFlags "\-m 0444" general
.IP
Flags for setting the mode of installed manual pages.
.LP
.Sy ArCmd "ar cq (HasLargeTmp)/ar clq (use local dir)" general
.IP
Command to create archive files.
If HasLargeTmp is YES,
.I /tmp
is used for temp file space, otherwise the current directory is used.
.LP
.Sy BootstrapCFlags "nothing" general
.IP
Defines needed to get
.B ccimake
compiled and by
.B imake
to get
.I cpp
to select the correct header block in
.I Imake.tmpl .
.LP
.Sy CcCmd "cc" general
.IP
Command to run the C compiler.
.LP
.Sy HasGcc "NO" boolean
.IP
Whether GNU CC,
.I gcc ,
is available.
.LP
.Sy LibraryCcCmd "CcCmd" general
.IP
Command to run the C compiler to compile libraries.
If 
.I HasGcc
is defined, then 
.I CcCmd
is defined as, 
gcc -bsd -DNOSTDHDRS -fstrength-reduce -fpcc-struct-return -fwritable-strings
.LP
.Sy FortranCmd "f77 \-O" general
.IP
Command to run the FORTRAN compiler.
.LP
.Sy FortranFlags "nothing" general
.IP
General flags for FORTRAN compiler.
.LP
.Sy FortranDebugFlags "nothing" general
.IP
Flags for FORTRAN compiler to turn on debugging information.
.LP
.Sy FortranScript "$(SCRIPTSRC)/fortran.sh (!HasFortran)/nothing" general
.IP
Flags for FORTRAN script.
.LP
.Sy CompressCmd "compress" general
.IP
Command to run
.I compress .
.LP
.Sy CppCmd "/lib/cpp" general
.IP
Command to run C preprocessor.
.LP
.Sy PreProcessCmd "CcCmd \-E" general
.IP
Command to preprocess input.
This is used by the script version of
.B makedepend .
.LP
.Sy InstallCmd "$(SCRIPTSRC)/bsdinst.sh / install" general
.IP
Command to install files.
It should be compatible with the BSD version of
.I install .
.LP
.Sy LdCmd "$(CC)" general
.IP
Command to run the loader.
Default is to use CC as defined to be cc or gcc.
.LP
.Sy LibraryLdCmd "LdCmd" general
.IP
Command to run the loader for libraries.
.LP
.Sy CpCmd "cp" general
.IP
Command to copy files.
.LP
.Sy LnCmd "ln (SystemV) / ln \-s" general
.IP
Command to link files.
Symbolic links are used if available (not System V).
.LP
.Sy MakeCmd "make" general
.IP
Command to run
.B make .
.LP
.Sy MvCmd "mv" general
.IP
Command to rename files.
.LP
.Sy RanlibCmd "/bin/true (SystemV) / ranlib" general
.IP
Command to run
.I ranlib .
On System V platforms this command is missing.
.I /bin/true ,
a nop, is used instead.
.I /bin/true "" (
always succeeds, which is important for
.B make .)
.LP
.Sy RanlibInstFlags nothing general
.IP
Flags to pass to
.I ranlib
when run on libraries that have already been installed.
``\-t'' is a good option here, if you have it.
.LP
.Sy RmCmd "rm \-f" general
.IP
Command to remove files.
.LP
.Sy StandardCppDefines "\-DSYSV (SystemV) / nothing" general
.IP
\-D's for C preprocessor.
.LP
.Sy LocalDefines nothing general
.IP
Local defines.
.LP
.Sy StandardIncludes nothing general
.IP
\-I's for C compiler.
.LP
.Sy XIncludes nothing general
.IP
Includes for X11.
.LP
.Sy ExtraIncludes nothing general
.IP
For other includes.
.LP
.Sy StandardDefines "\-DSYSV (SystemV) / nothing" general
.IP
\-D's for C compiler.
.LP
.Sy ExtraLibs nothing general
.IP
Extra libraries needed to get programs to compile.
.LP
.Sy ExtraLoadFlags nothing general
.IP
Extra flags needed to get loader to work.
.LP
.Sy TagsCmd "ctags" general
.IP
Command to generate tags files.
.LP
.Sy LocalLibs "see Library.def file" general
.IP
Specifies the standard Khoros libraries.
.LP
.Sy LocalDependLibs "see Library.def file" general
.IP
Specifies the Khoros depend libraries.
.LP
.Sy XLocalLibs "see Library.def file" general
.IP
Specifies the X libraries that Khoros depends on.
.LP
.Sy XLocalDependLibs "see Library.def file" general
.IP
Specifies the X depend libraries that Khoros uses.
.LP
.Sy LoaderLibPrefix "\-L" general
.IP
Flags to specify before libraries (see
.I cray.cf ).
Cray uses \-l
.LP
.Sy BaseName "/usr/bin/basename" general
.IP
Specifies where basename lives on your machine.
.LP
.Sy SrcTop "KHOROS_HOME/src"
.IP
Specifies the top of the Khoros source tree.
.LP
.Sy FilesToClean "*.o core *.a tags TAGS" general
.IP
List of files to be removed by ``make clean''.
.LP
.Sy HasCache "NO" general
.IP
Specifies whether to use cache.
.LP
.Sy HasTempnam "YES" general
.IP
Specifies whether to use temporary file names.
.LP
.Sy GhostWriter "$(BINDIR)/ghostwriter" general
.IP
Specifies the path to the Khoros
.I ghostwriter
program.
.LP
.Sy GhostReader "$(BINDIR)/ghostreader" general
.IP
Specifies the path to the Khoros
.I ghostreader
program.
.LP
.Sy GhostAns "./ghost.ans" general
.IP
Sepeifies the filename of the
.I ghost routine
answer file.
.LP
.Sy ManSuffix 1 general
.IP
Suffix for the Khoros program manual pages.
.LP
.Sy LibManSuffix 3 general
.IP
Suffix for the Khoros library manual pages.
.LP
.Sy LibraryDefines StandardDefines general
.IP
\-D's for compiling libraries.
.LP
.Sy BinDir KHOROS_HOME/bin general
.IP
Where to install Khoros programs.
.LP
.Sy IncRoot KHOROS_HOME/include general
.IP
Where to find Khoros include files.
.LP
.Sy LibDir KHOROS_HOME/lib general
.IP
Khoros library installation directory.
.LP
.Sy SysLibs \-lm \-ll general
.IP
Specifies the system libraries that your machine uses.
The definition of
.I SysLibs
in the machine.cf file will override this definition.
.LP
.Sy XLibs \-lXaw \-lXmu \-Xt \-lXext \-lX11 general
.IP
Specifies the X libraries that your machine uses.
If
.I XLibs
is defined in the machine.cf file, that will override this definition.
.LP
.Sy ConfigDir KHOROS_HOME/repos/config/imake_conf general
.IP
Where to install Khoros configuration files.
.LP
.Sy ManDir KHOROS_HOME/man/man1 general
.IP
Where to install Khoros manual page files.
.LP
.Sy LibManDir KHOROS_HOME/man/man3 general
.IP
Where to install Khoros library manual page files.
.LP
.Sy UseCCMakeDepend NO boolean
.IP
Whether to use the slow shell cc \-E script version of
.B makedepend
(uses
.I "cc \-E" ).
It's best to use the compiled version if it works on your system.
If the compiled version does not work as supplied with the distribution,
it's probably
worth a little effort to see if you can get it to work
(particularly if you can't get the shell script version to work,
either, which sometimes happens!).
Possible problems:
.I /usr/include
is hardwired into the code; if you use
.I gcc ,
the library path is hardwired, too.
.LP
.Sy DependDir "varies" general
.IP
Path to
.B makedepend
sources.
The default is dependent on UseCCMakeDepend.
If UseCCMakeDepend is set, then
.I DepenDir
is $(SCRIPTSRC).
Otherwise
.I DepenDir
is $(TOP)/bootstrap/makedepend.
.LP
.Sy DependCmd $(DEPENDSRC)/makedepend general
.IP
Command to run
.B makedepend.
.LP
.Sy RemoveTargetProgramByMoving NO boolean
.IP
This symbol affects expansion of the RemoveProgramTarget() rule.
``Program'' in that rule's name is misleading; it can be used to remove any
file, not just programs.
.LP
.Sy AllocateLocalDefines nothing general
.IP
\-D's to turn on
.I alloca ().
.sp 2
.NH 2 "MAKE VARIABLES"
.XS
      \*(SN  MAKE VARIABLES
.XE
.PP
Many of the
.B make
variables in
.I Khoros.tmpl
are simply set to the preprocessor variable of the same name (e.g.,
INSTBINFLAGS = InstBinFlags).
.LP
Most
.B make
variables referring to commands are set to the preprocessor symbol having
the same name and a suffix ``Cmd''.
For instance, CC and MAKE are set to CcCmd and MakeCmd, respectively.
.LP
The rest of the variables are set to
preprocessor symbols with names that differ more from the variable
name (e.g., SHELL = BourneShell), or are defined in terms of other
.B make
variables (e.g., MFLAGS = -$(MAKEFLAGS)), or a combination of
preprocessor symbols and
.B make
variables (e.g., RM_CMD = $(RM) FilesToClean).
.sp 2
.NH 2 "IMAKE RULES"
.XS
      \*(SN  IMAKE RULES
.XE
.PP
The 
.I Khoros.rules
file rule definitions make heavy use of the following techniques:
.IP (1)
Use of the ``::'' construct is quite prevalent.
In a
.B make
rule, if a target name is followed by ``:'', it's assumed to be the
only rule for that target.
If another rule with the same target is found, it's an error.
If target names are followed by ``::'', there may be multiple rules
for the targets.
The Khoros configuration files rely on this property of ``::'' in the
following ways:
.RS
.IP (a)
To make sure that certain targets are always present in the
.I Makefile ,
even if they are not otherwise generated from expansion of the macros
in
.I Imakefile .
This way, subdirectory-traversing
.I make
operations can rely on those targets being present.
For instance, many rules that build programs automatically generate a
``clean'' target to remove the program.
But if no such rule is used in the
.I Imakefile ,
there might be no ``clean'' target in the
.I Makefile ,
and ``make clean'' fails.
That's not a disaster, but a ``make clean'' from the root of the
source tree can result in a lot of apparent errors.
To avoid this, an empty ``clean'' target is written to the
.I Makefile ,
using ``clean::''.
If there is another ``clean'' target, the empty one doesn't hurt anything.
If there isn't, the empty one prevents error messages.
.IP
Other default targets generated are ``tags'', ``install'',
``install.man'', ``Makefile'', ``Makefiles'' and ``includes''.
.IP (b)
To allow commands like ``make all'' to trigger builds of an arbitrary
number of targets.
Without the ``::'' construct, the configuration process would need to
be able to determine exactly which targets ``make all'' should
generate, and produce a single ``all: target1 target2 ...'' rule.
This would be a difficult task.
Using ``::'', each program-building rule can generate its own ``all::
target'' and they are all triggered.
.RE
.IP (2)
Definitions are allowed to be overridden.
All rules are defined using the following construct:
.Ds .IP
# ifndef \fIrulename\fR
# define \fIrulename(arguments)\fR ...
# endif
.De .IP
This should look familiar because it's the same construct used
in the other configuration files to allow symbol values to be overridden.
Since
.I Khoros.rules
is the last configuration file read during a
.I Makefile
build,
.I any
of its rules may be redefined.
Doing so can have far-reaching consequences, of course, so that's not
something you want to do without thinking it through first.
Nevertheless, it's sometimes useful, or even necessary.
.IP
The likely places for such overriding to occur are:
.IP
.I platform.cf \*-if
a system does things in some strange way that's
not easy to compensate for by defining the usual configuration symbols
properly.
For example, the file
.I sgi.cf
redefines a couple of rules, to account for non-standard file
extensions.
.IP
.I Site.def \*-if
a rule just isn't right for your site, for some reason.
.IP
.I Imakefile \*-it's
sometimes useful to override a rule in a particular directory, which
can be done by defining the rule in that directory's
.I Imakefile .
.IP (3)
If a directory has subdirectories, and
.I make
operations in that directory should recurse down through the
subdirectories, there should be a line that says
.Ds .IP
# define IHaveSubdirs
.De .IP
at the top of the
.I Imakefile .
This causes recursive ``install'', ``install.man'',
``clean'', ``tags'', ``Makefile'' and ``includes'' target rules to be
written into the
.I Makefile
(see end of
.I Khoros.tmpl ;
the
.I make
variable SUBDIRS should set to the names of the subdirectories involved, as
well).
If you want CDEBUGFLAGS passed along to subdirectories, put another
line at the top of the
.I Imakefile
that says
.Ds .IP
# define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
.De
.IP (4)
As you scan through the rules, you'll notice that
.I if
constructs are not written like this:
.Ds .IP
if \fIcondition\fR then; \fIaction\fR; fi
.De .IP
Instead, they're written like this:
.Ds .IP
if \fIcondition\fR then; \fIaction\fR; else exit 0; fi
.De .IP
The reason for this is to deal with differing behaviors of
.I if
on various systems.
On some systems, if you write ``if \fIcondition\fR; then \fIaction\fR; fi''
and
.I condition
is false, the value of the statement is zero (on the grounds that the
test executed to completion without error).
On other systems, the value of the statement is non-zero (on the grounds
that the test failed).
.IP
In the Khoros rules,
.I if
tests are usually used to check whether some preliminary action needs to be
performed before proceeding to the next step.
Systems that return false when the
.I if
test fails cause
.I make
to exit early if the preliminary action does not need to be done, and
the next step is\*-incorrectly\*-never executed.
.IP
In order to get around this, all
.I if
statements explicitly include an
.I else
clause to return zero when the condition fails, so that
.I make
will continue whether the condition is true or not.
.sp 2
.NH 2 "COMMONLY USED RULES"
.XS
      \*(SN  COMMONLY USED RULES
.XE
.LP
Rules for building programs
.Ds
NormalProgramTarget()
SimpleProgramTarget()
ComplexProgramTarget()
ComplexProgramTarget_1()
ComplexProgramTarget_2()
ComplexProgramTarget_3()
.De
Rules for building shell scripts
.Ds
CppScriptTarget()
MakeScriptFromCpp()
.De
Rules for building libraries
.Ds
NormalLibraryObjectRule()
NormalLibraryTarget()
.De
Rules for installing files
.Ds
InstallProgram()
InstallLibrary()
InstallManPage()
InstallNonExec()
InstallSubdirs()
.De
Rules for cleaning up
.Ds
RemoveTargetProgram()
CleanTarget()
CleanSubdirs()
.De
Rules for generating Makefiles and dependencies
.Ds
MakefileTarget()
MakefileSubdirs()
DependTarget()
DependSubdirs()
.De
Many rules that compile programs also generate ``clean'' and ``all''
targets.
.sp 2
.NH 2 "RULE DESCRIPTIONS"
.XS
      \*(SN  RULE DESCRIPTIONS
.XE
.LP
Most of the common rule-generating macros in
.I Khoros.rules
are described below.
.LP
.Ru SaberProgramTarget(program,srclist,objlist)
.IP
Generates rules to make Saber-C read in sources and objects.
If HasSaberC is NO, this is a nop, otherwise it expands to a rule for
``saber-\fIprogram\fR'' and causes Saber C to load source and object
files for the program.
Odd that ``#'' is in front of the rules, though.
.LP
.Ru RemoveTargetProgram(program)
.IP
Removes
.I program
(actually this symbol is misnamed because it can be used to remove any
file, not just programs).
If RemoveTargetProgramByMoving (from
.I Project.tmpl )
is YES,
.I program
is moved to
.I program~
instead.
This allows you to keep the previous version around.
Note that ``*~'' is in the list of files removed by CleanTarget(), so
unless you override FilesToClean, ``make clean'' will remove these
previous target versions.
.LP
.Ru NormalProgramTarget(program,objects,deplibs)
.IP
Builds one program.
All object files and libraries are explicitly listed in the macro invocation.
.I program
is the program to be built.
.I objects
names the object files needed to build it from, e.g.,
.I junk.o .
.I deplibs
names the libraries that must exist before linking is done.
.LP
.Ru ComplexProgramTarget(program)
.IP
This macro is used in an
.I Imakefile
that builds a single program.
Given the name of the program, rules are generated to build it, as well as
generate ``all'', ``install'', ``install.man'', ``depend'' and ``lint''
targets, and to remove the program.
Several assumptions are made by this macro:
.RS
.IP (1)
You have set SRCS to the list of source files (so the ``depend'' target works).
.IP (2)
You have set OBJS to the list of object files (so the program build works).
.IP (3)
The
.I deplibs ,
.I locallibs
and
.I syslibs
arguments as used in NormalProgramTarget() are assumed to be DEPLIBS,
LOCAL_LIBRARIES and LDLIBS.
.RE
.LP
.Ru FortranScriptTarget(program)
.IP
Generates rules for placing a "sh" script in place of a binary when
Fortran is not available on the machine.
.LP
.Ru InstallLibrary(libname,dest)
.IP
Installs
.I liblibname.a
into
.I dest/liblibname.a
and runs the command named by RANLIB on it.
The installation flags INSTLIBFLAGS are used.
.LP
.Ru MergeIntoInstalledLibrary(tolib,fromlib)
.IP
Merges
.I fromlib
into
.I tolib
using the
.I mergelib
script in the SCRIPTSRC directory.
.LP
.Ru InstallSharedLibrary(libname,rev,dest)
.IP
Installs
.I liblibname.so.rev
into
.I dest/liblibname.so.rev ,
using INSTLIBFLAGS.
.LP
.Ru InstallSharedLibraryData(libname,rev,dest)
.IP
Installs
.I liblibname.sa.rev
into
.I dest/liblibname.sa.rev ,
using INSTLIBFLAGS.
.LP
.Ru InstallLibraryAlias(libname,alias,dest)
.IP
In
.I dest ,
makes
.I libalias.a
an alias for
.I liblibname.a
by generating a link.
.LP
.Ru InstallManPage(file,dest)
.IP
Generate rule to install the manual page
.I file.man
in
.I dest/file. ManSuffix
using installation flags INSTMANFLAGS.
.LP
.Ru InstallLibManPage(file,dest)
.IP
Generate rule to install the library manual page
.I lfile.man
in
.I dest/lfile. ManSuffix
using installation flags INSTMANFLAGS.
.LP
.Ru InstallNonExec(file,dest)
.IP
Generate rules to install a non-executable file using installation
flags INSTDATFLAGS.
.LP
.Ru InstallProgramWithFlags(program,dest,flags)
.IP
Generate rules to install an executable program using the specified
flags.
.LP
.Ru InstallProgram(program,dest)
.IP
Generate rules to install an executable program.
.LP
.Ru InstallFortranScript(program,forscript,dest)
.IP
Generate rules to install a 
.I shell script
using special install flags set in 
.I $(INSTALLFLAGS). This is called when Fortran is not available
on the machine.
.LP
.Ru InstallScript(program,dest)
.IP
Generate rules to install
.I program.script
into
.I dest/program
using installation flags INSTPGMFLAGS.
.IP
This rule is obsolete.
Use CppScriptTarget() and InstallProgram().
.LP
.Ru InstallMultiScripts(list,dest)
.IP
Generate a rule to install a shell script using special install flags set
in
.I $(INSTALLFLAGS).
.LP
.Ru LinkFileList(step,list,dir,sub)
.IP
Generates rules for a target
.I step
to make links to all files in
.I list
in directory
.I dir .
The links are created in directory
.I sub .
Judging from the definition of this macro,
.I sub
is presumably so named because the rule changes directories into
.I dir
first and appears to expect
.I sub
to be a subdirectory.
However, that need not be true, strictly speaking, since
(i)
.I sub
could legally be an absolute path;
(ii)
.I sub
could have a value such as ``../..''.
But both those possibilities probably subvert the intent of the
macro.
.LP
.Ru InstallMultipleDestFlags(step,list,dest,flags)
.IP
Generates rules for a target
.I step
(e.g., ``install'') to install all the files in
.I list
into the directory
.I dir
using installation flags
.I flags .
The files in
.I list
are made the rule dependencies.
.LP
.Ru InstallMultipleDest(step,list,dest)
.IP
Like InstallMultipleDestFlags(), but assuming INSTALLFLAGS as the
installation flags.
As noted above for InstallProgram(), INSTALLFLAGS appears to be set
nowhere in the X configuration files.
Perhaps it is something you are expected to give a value to in your
.I Imakefile .
.LP
.Ru InstallMultiple(list,dest)
.IP
Like InstallMultipleDest(), but assuming ``install'' as the
.I step
argument.
.LP
.Ru InstallMultipleFlags(list,dest,flags)
.IP
Like InstallMultipleDestFlags(), but assuming ``install'' as the
.I step
argument.
.LP
.Ru InstallMultipleMan(list,dest)
.IP
Like InstallMultipleDest(), but assuming ``install.man'' as the
.I step
argument.
.LP
.Ru InstallAppDefaults(class)
.IP
If InstallAppDefFiles (from
.I Project.tmpl )
is #define'd, generates an ``install'' target to install
.I class.ad
into
.I $(XAPPLOADDIR)/class
using installation flags INSTAPPFLAGS.
.IP
INSTAPPFLAGS appears to be deprecated in
.I Project.tmpl .
.LP
.Ru DependDependency()
.IP
If UseInstalled is not #define'd, this macro generates rules to check for the
existence of
.I makedepend
in the source tree and build it if it's missing.
.LP
.Ru DependTarget()
.IP
Generate rule to determine dependencies for source files named by SRCS.
You have to define the value of SRCS yourself, unless you are using
rules such as
SimpleProgramTarget() or ComplexProgramTarget_{1,2,3}(), which do it
for you.
In the latter case, you need to define SRCS1, SRCS2 and SRCS3.
.IP
This macro uses DependDependency() to check for the existence of
.I makedepend
and build it if necessary.
.LP
.Ru CleanTarget()
.IP
Removes all the files named by FilesToClean and files whose names
begin with ``#''.
.IP
To understand how this rule works, see how RM_CMD is defined in
.I Imake.tmpl .
.LP
.Ru TagsTarget()
.IP
Generate rule to build a
.I TAGS
file from all
.I *.c
and
.I *.h
files.
.LP
.Ru ImakeDependency(target)
.IP
If UseInstalled is not #define'd, this macro generates rules to check for the
existence of
.I imake
in the source tree and build it if it's missing.
.LP
.Ru BuildMakefileTarget(imakefile,imakeflags)
.IP
Generate rules to build
.I Makefile .
The
.I imakefile
argument is superfluous (a bug?).
Since it's ignored,
.I Imakefile
is assumed as the source from which to build
.I Makefile .
.I imakeflags
is any special flags you want passed to the
.I imake
command.
.IP
This macro uses ImakeDependency() to check for the existence of
.I imake
and build it if necessary.
.IP
You don't use this rule explicitly unless you've #define'd
IHaveSpecialMakefileTarget in your
.I Imakefile .
.LP
.Ru BuildImakefileDirLocal()
.IP
Generate a rule to update Imakefiles located in sub-directories using
the imkmf utility.  This is generally done automatically by the template
or by any special Imakefiles.
.LP
.Ru BuildImakefileDir(list)
.IP
Generate rules to update an Imakefile for a directory using the
imkmf utility.  This is generally done automatically by the
template or by any special Imakefiles.
.LP
.Ru BuildImakefileProg()
.IP
Generate rules to update an Imakefile for programs, X programs,
libraries and scripts using the imkmf utility.  This is
generally done automatically by the template or by any special Imakefiles.
.LP
.Ru GenImakefileDirLocal()
.IP
Generate a rule to build Imakefiles located in
sub-directories using the imkmf utility.  This is generally done
automatically by the template or by any special Imakefiles.
.LP
.Ru GenImakefileDir(list)
.IP
Generate rules to build an Imakefile for a directory
using the imkmf utility.  This is generally done automatically by the
template or by any special Imakefiles.
.LP
.Ru GenImakefileProg()
.IP
Generate rules to build an Imakefile for programs,
X programs, libraries and scripts using the imkmf utility.  This is
generally done automatically by the template or by any special Imakefiles.
.LP
.Ru MakefileTarget()
.IP
Generate rules to build a
.I Makefile
target from
.I Imakefile ,
so you can say ``make Makefile''.
This target is automatically included in your
.I Makefile
when it is rebuilt by
.I imake ,
unless ``#define IHaveSpecialMakefileTarget'' is present
in your
.I Imakefile ,
in which case you should include an invocation of
BuildMakefileTarget() to build
.I Makefile .
.LP
.Ru NormalLibraryObjectRule()
.IP
Generate rule to turn a
.I .c
file into a
.I .o
file.
Include this macro (once) in your
.I Imakefile
if you're building a library from C source.
.LP
.Ru NormalFortranObjectRule()
.IP
Generate rule to turn a
.I .f
file into a
.I .o
file.
Include this macro (once) in your
.I Imakefile
if you're building a library from FORTRAN source.
.LP
.Ru ProfiledLibraryObjectRule()
.IP
Like NormalLibraryObjectRule(), but in addition to building the normal
target, a profiled target is built in the
.I profiled
subdirectory of the current directory.
.I profiled
is created if necessary.
A ``clean'' target to remove profiled objects is also generated.
.LP
.Ru DebuggedLibraryObjectRule()
.IP
Like ProfiledLibraryObjectRule(), but instead of profiled targets in
.I profiled ,
debuggable targets are built in the
.I debugger
subdirectory.
.LP
.Ru DebuggedAndProfiledLibraryObjectRule()
.IP
A combination of ProfiledLibraryObjectRule() and DebuggedLibraryObjectRule().
.LP
.Ru SharedLibraryObjectRule()
.IP
Like ProfiledLibraryObjectRule(), but instead of profiled targets in
.I profiled ,
sharable targets are built in the
.I shared
subdirectory.
.LP
.Ru SharedFortranObjectRule()
.IP
Generates make rules to build shared and normal object files.
.LP
.Ru SharedAndDebuggedLibraryObjectRule()
.IP
A combination of SharedLibraryObjectRule() and DebuggedLibraryObjectRule().
.LP
.Ru SpecialSharedAndDebuggedObjectRule(objs,depends,options)
.IP
Like SharedAndDebuggedLibraryObjectRule(), but allows targets
.I objs ), (
dependencies and special compiler flags to be specified.
.LP
.Ru SpecialSharedObjectRule(objs,depends,options)
.IP
Like SharedLibraryObjectRule(), but allows targets
.I objs ), (
dependencies and special compiler flags to be specified.
.LP
.Ru SpecialObjectRule(objs,depends,options)
.IP
Like NormalLibraryObjectRule(), but allows targets
.I objs ), (
dependencies and special compiler flags to be specified.
.LP
.Ru SpecialProfiledObjectRule(objs,depends,options)
.IP
Like ProfiledLibraryObjectRule(), but allows targets
.I objs ), (
dependencies and special compiler flags to be specified.
.LP
.Ru SpecialDebuggedObjectRule(objs,depends,options)
.IP
Like DebuggedLibraryObjectRule(), but allows targets
.I objs ), (
dependencies and special compiler flags to be specified.
.LP
.Ru SpecialDebuggedAndProfiledObjectRule(objs,depends,options)
.IP
Like DebuggedAndProfiledLibraryObjectRule(), but allows targets
.I objs ), (
dependencies and special compiler flags to be specified.
.LP
.Ru NormalLibraryTarget(libname,objlist)
.IP
Generate rules to create the library
.I liblibname.a
from the object files named by
.I objlist .
The library is RANLIB'd after being created.
.LP
.Ru NormalSharedLibraryTarget(libname,rev,solist)
.IP
Generate rules to create a shared library
.I liblibname.so.rev .
The library is created under a different name and then moved onto the
target name to maximize availability of any existing version.
.LP
.Ru NormalSharedLibraryDataTarget(libname,rev,salist)
.IP
Like NormalSharedLibraryTarget(), but for shared data
.I liblibname.sa.rev .
The comments claim
the library is created under a different name and then moved onto the
target name as for NormalSharedLibraryTarget() but that doesn't appear
to be true from the text of the macro.
.LP
.Ru NormalLibraryTarget2(libname,objlist1,objlist2)
.IP
Like NormalLibraryTarget(), but adds two lists of files to the
library, in two steps.
Used to create libraries with large numbers of files.
.LP
.Ru ProfiledLibraryTarget(libname,objlist)
.IP
Generate rules to create the library
.I liblibname_p.a
from the profiled objects in the
.I profiled
subdirectory.
.LP
.Ru DebuggedLibraryTarget(libname,objlist)
.IP
Generate rules to create the library
.I liblibname_d.a
from the debuggable objects in the
.I debugger
subdirectory.
.LP
.Ru AliasedLibraryTarget(libname,alias)
.IP
Generate rules to make
.I libalias.a
a link to
.I liblibname.a .
.LP
.Ru NormalRelocatableTarget(objname,objlist)
.IP
Generate rules to produce a relocatable object file
.I objname.o
from the object files named in
.I objlist .
This is built using the loader LD, called with flags LDCOMBINEFLAGS.
.LP
.Ru ProfiledRelocatableTarget(objname,objlist)
.IP
Like NormalRelocatableTarget(), but builds
.I objname_p.o
and uses loader flag
\-X instead of LDCOMBINEFLAGS, to produce a profiled relocatable
object file.
.LP
.Ru DebuggedRelocatableTarget(objname,objlist)
.IP
Like NormalRelocatableTarget(), but builds
.I objname_d.o
and uses loader flag
\-X instead of LDCOMBINEFLAGS, to produce a debuggable relocatable
object file.
.LP
.Ru LinkSourceFile(src,dir)
.IP
Generate rule to make a link to a file in another directory.
The macro can be used to create links
to non-source files, too, of course.
.LP
.Ru MakeSubincludesForBuild(step,dir,srclist)
.IP
Generate rules for target
.I step
to ... to ... uh, I don't know!
.LP
.Ru NamedTargetSubdirs(name,dirs,verb,flags,subname)
.IP
Generate rules for a target
.I name
(e.g., ``depend'', ``install'') that causes the target
.I subname
to be built in the subdirectories named by
.I dirs .
This is done by changing into each subdirectory in turn and invoking
.I make
for the
.I subname
target.
.I flags
is any extra flags that should be passed to those
.I make
processes.
.I verb
is the -ing form of
.I name ,
e.g., if
.i name
is ``make'', then
.I verb
is ``making''.
This is used to echo an indication of what
.I make
is doing in each directory as it proceeds.
.IP
This macro is used by virtually all other macros that have names like
XXXSubdirs().
.LP
.Ru NamedMakeSubdirs(name,dirs)
.IP
Invokes NamedTargetSubdirs() to generate rules for a target
.I name
that causes the ``all'' target to be built in the
subdirectories named by
.I dirs .
.IP
If you want CDEBUGFLAGS passed to the
.I make
processes forked in each subdirectory, the
.I Imakefile
should have a line at the top that says:
.RS
.Ds
# define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
.De
.RE
.LP
.Ru MakeSubdirs(dirs)
.IP
Equivalent to NamedMakeSubdirs(all,dirs).
.LP
.Ru DependSubdirs(dirs)
.IP
Invokes NamedTargetSubdirs() to generate rules for a ``depend''
target that causes the ``depend'' target to be built in the
subdirectories named by
.I dirs .
.LP
.Ru InstallSubdirs(dirs)
.IP
Invokes NamedTargetSubdirs() to generate rules for a ``install''
target that causes the ``install'' target to be built in the
subdirectories named by
.I dirs .
.IP
This macro is automatically invoked if IHaveSubdirs is #define'd in
.I Imakefile ,
in which case SUBDIRS should be set to the names of the subdirectories
involved.
.LP
.Ru InstallManSubdirs(dirs)
.IP
Invokes NamedTargetSubdirs() to generate rules for a ``install.man''
target that causes the ``install.man'' target to be built in the
subdirectories named by
.I dirs .
.IP
This macro is automatically invoked if IHaveSubdirs is #define'd in
.I Imakefile ,
in which case SUBDIRS should be set to the names of the subdirectories
involved.
.LP
.Ru IncludesSubdirs(dirs)
.IP
Invokes NamedTargetSubdirs() to generate rules for a ``includes''
target that causes the ``includes'' target to be built in the
subdirectories named by
.I dirs .
.IP
This macro is automatically invoked if IHaveSubdirs is #define'd in
.I Imakefile ,
in which case SUBDIRS should be set to the names of the subdirectories
involved.
.LP
.Ru NamedCleanSubdirs(name,dirs)
.IP
Invokes NamedTargetSubdirs() to generate rules for a target
.I name
that causes the ``clean'' target to be built in the
subdirectories named by
.I dirs .
.LP
.Ru CleanSubdirs(dirs)
.IP
Equivalent to NamedCleanSubdirs(clean,dirs).
.IP
This macro is automatically invoked if IHaveSubdirs is #define'd in
.I Imakefile ,
in which case SUBDIRS should be set to the names of the subdirectories
involved.
.LP
.Ru NamedTagSubdirs(name,dirs)
.IP
Invokes NamedTargetSubdirs() to generate rules for a target
.I name
that causes the ``tags'' target to be built in the
subdirectories named by
.I dirs .
.LP
.Ru TagSubdirs(dirs)
.IP
Equivalent to NamedTagSubdirs(tags,dirs).
.IP
This macro is automatically invoked if IHaveSubdirs is #define'd in
.I Imakefile ,
in which case SUBDIRS should be set to the names of the subdirectories
involved.
.LP
.Ru MakeMakeSubdirs(dirs,target)
.IP
Generate rules for a target
.I target
to generate a
.I Makefile
in the subdirectories named by
.I dirs .
.LP
.Ru MakeNsubdirMakefiles()
.IP
Generate a set of very very very ugly but quite wonderful rules for
use by MakeMakeSubdirs().
.LP
.Ru MakefileSubdirs(dirs)
.IP
Generate rules to build ``Makefiles''
targets in the given subdirectories.
.IP
This macro is automatically invoked if IHaveSubdirs is #define'd in
.I Imakefile ,
in which case SUBDIRS should be set to the names of the subdirectories
involved.
.LP
.Ru CppScriptTarget(dst,src,defs,deplist)
.IP
Generate rules to build a shell script
.I dst
from
.I src .
It figures out how to do this correctly for the current platform
depending on the value of ExecableScripts.
.I defs
is any extra flags, such as \-D's, to pass through to the
preprocessor.
.I deplist
names any targets that must exist before
.I dst
can be built.
.LP
.Ru MakeScriptFromCpp(name,defs)
.IP
Generate rule to build a script
.I name
from
.I name.cpp .
.I defs
is as for CppScriptTarget().
.LP
.Ru MakeDirectories(step,dirs)
.IP
Generate rules for target
.I step
to create the directories named by
.I dirs .
This is often used to make sure that installation directories exist.
.LP
.Ru AllTarget(depends)
.IP
Generate rules for an ``all'' target to build targets named by
.I depends .
.LP
.Ru MakeGhostWriter(program, ansfile)
.IP
Generate rules for using ghostwriter in the makefile.
.LP
.Ru MakeGhostWriterDir(list)
.IP
Generate rules for using ghostwriter at the directory level.
.LP
.Ru MakeGhostReader(program, ansfile)
.IP
Generate rules for using ghostreader in the makefile.
.LP
.Ru MakeGhostReaderDir(list)
.IP
Generate rules for using ghostreader at the directory level.
.LP
.Ru MakeHelppage(program)
.IP
Generate rules for using helppage in the makefile.
.LP
.Ru MakeHelppageDir(list)
.IP
Generate rules for using helppage at the dir level.
.LP
.Ru MakeRCSDir(list)
.IP
Generate rules for using RCS at the directory level.
.LP
.Ru RCSRule(list)
.IP
Generate rules for using RCS co and ci.
.LP
.sp 2
.NH 1 "REFERENCES"
.XS
\s12\*(SN  REFERENCES\s0
.XE
.PP
This document was derived from the Appendix written by:
.nf

	Paul DuBois
	dubois@primate.wisc.edu

	Wisconsin Regional Primate Research Center
	Revision date: 24 January 1991
	
.fi
.TC "APPENDIX C - IMAKE"
