% (C) Copyright International Business Machines Corporation 23 January 
% 1990.  All Rights Reserved. 
%  
% See the file USERAGREEMENT distributed with this software for full 
% terms and conditions of use. 
\subsection{Make facility}
The {\tt Makehermes} program helps automate the compilation of a set
of interdependent modules.  Makehermes is easier to use than the unix
make program because it automatically determines module dependencies
from the {\tt using( )} and {\tt linking( ) } lists in Hermes modules.
The user need not create a ``makefile.''

makehermes is invoked by the command:
$$\hbox{\tt makehermes {\em [options]} {\em filename} $\ldots$ }$$

Makehermes determines and performs (depending on its options) the
necessary compilations (both {\tt dcom} and {\tt pcom}) to produce the
requested compiled module files.  Process modules and definitions
modules may both be specified, with the appropriate file extentions
({\tt .do} for definitions modules, {\tt .po} for process modules).
For example, the following command would compile one definition module
and three process modules, as well as any other modules on which they
depend and which are out-of-date.
\begin{verbatim}
makehermes foo.do goo.po /u/hermes/bar.po zip.po
\end{verbatim}

\subsubsection{Module dependencies and consistency}

A module {\tt bar} {\em depends on} another module {\tt foo} if either
{\tt foo} is a definitions module imported by {\tt bar} (in its {\tt
using( )} list), or {\tt foo} is a process module statically linked by
{\tt bar} (in its {\tt linking( ) } list).  {\tt bar} is {\em
inconsistent} if its source file was modified since it was last
compiled, or if it depends on any other module that is inconsistent or
was compiled more recently than {\tt bar}.

The {\tt makehermes} program determines all the modules on which each
of the {\tt filename} arguments depends, and then all the modules on
which those modules depend, and so on.  In this way it creates a {\em
dependency graph} where nodes represent modules and edges represent
dependencies between modules.  {\tt makehermes} then recompiles all
the inconsistent files represented in the graph, in an order that
ensures that all files will be consistent when everything is finished,
and no module needs to be compiled twice.  Inconsistencies are
determined by examining the modification times maintained for the
source and object files by Unix.

Makehermes searches for files (both compiled modules and source files)
in the directories listed in the Unix environment variable {\tt
HPATH}.  If {\tt HPATH} is not defined, makehermes searches on the
path {\tt .:{\em hermes-root}/bin}, where {\em hermes-root} is where
the Hermes system has been installed.  The object files produced by
compilations are always placed in the current working directory,
regardless of where the source files may have been found.

If a required object file ({\tt .do} or {\tt .po} file) is missing,
{\tt makehermes} will consider that module inconsistent and will
therefore recompile it.

\subsubsection{Options}

Makehermes recognizes three categories of options.  Options are
specified on the command line by means of one or more option letters
preceded by a hyphen.  The options are as follows; defaults are marked
with asterisks:

\begin{enumerate}
\item The {\em action} options determine what makehermes will do with 
an inconsistent file.
\begin{verbatim}
 *c      (compile)          compile (pcom or dcom) the file
  p      (print)            print the filename and compilation
                            command, but do not compile
\end{verbatim}
\item The {\em error} options control makehermes's response to
    errors encountered while building the dependency graph and 
    applying the required actions.
\begin{verbatim}
 *s      (Stop)             halt immediately on any error
  g      (Ignore)           ignore all errors
  o      (Continue Others)  on an error stop processing successors but 
                            continue processing other paths 
\end{verbatim}
\item The {\em selection} options help select the files to which
makehermes will apply its actions. 
\begin{verbatim}
 *i      (Inconsistent)     apply the action to all inconsistent files
  n      (None)             take no action (just build the dependency graph)
  a      (All)              do action to all files (in order)
\end{verbatim}
\end{enumerate}

These options can be combined, as in:
\begin{itemize}
\item{\tt hermes makehermes -agp bar.po}  will print out all the dependencies 
      for {\tt bar.po} and ignore errors.
\item{\tt hermes makehermes -og foo.do} will compile all inconsistent files
      used by {\tt foo.do}.  If a compilation error occurs when compiling
      a dependency {\tt guppy.d}, then files dependent on {\tt guppy.d}
      will not be compiled but other files are compiled.  
\end{itemize}
  
\subsubsection{Delimiting the scope of makes}

It is sometimes the case that one does not want makehermes to recompile
all inconsistent files.  This may be due to several reasons: for instance,
you may be importing your friend's definitions modules, and she is in
the process of updating source files.  Any attempt to compile those
source files would fail, because they are in a changing and
inconsistent state.  Instead, you wish to simply use the most recent
compiled versions of the modules and prevent {\tt makehermes} from
attempting to update them.

{\tt Makehermes} uses a list of directories to limit the set of files
it compiles.  It compiles {\tt only} those files stored in directories
in the list.  The directory list is specified as a standard unix path
specification in the environment variable {\tt MKSCOPE}.  Any file
{\em not stored in} a directory listed in {\tt MKSCOPE} is considered
consistent regardless of its modification time.  That is, makehermes
pretends that the modification time for a file not within {\tt
MKSCOPE} is infinity.

For example, suppose that {\tt MKSCOPE} is set to
{.:/hermes/lib:/u/pip}, and that process module {\tt bar} imports the
definitions module {\tt foo}.  Assume further that {\tt bar.po}'s full
pathname is {\tt /u/pip/bar.po} and that the module {\tt foo.do} is in
a directory not listed in {\tt MKSCOPE}.  Then makehermes will compare
the timestamp of {\tt bar.po} with the timestamp of {\tt foo.do} and
recompile {\tt bar} if necessary.  However, it will not recompile {\tt
foo}, even if {\tt foo.do} has a timestamp that is earlier than its
source file or any module on which it depends.

If not defined, MKSCOPE defaults to the current working directory, so
that {\tt makehermes} will not normally attempt to recompile anything
that does not appear in the current directory.

\subsubsection{Bugs}
\label{bugs}

Be cautious about file system links interacting with {\tt MKSCOPE} and
{\tt HPATH}.  If links cause a file to appear in one directory
according to {\tt HPATH} and another directory according to {\tt
MKSCOPE}, then makehermes will never recompile the file.

Hermes supports two kinds of comments: \verb+ --+ and \verb+ /* */+.
If the latter type of comment appears in a source file before the {\tt
using} list or before the {\tt linking} list, makehermes will behave
unreliably.
