% (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}
{\em Makehermes} 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: \\
\hspace{1 in} {\bf hermi makehermes [-options] filename [filename ... ] } \\
Makehermes determines and performs (depending on its options) the necessary
compilations (both dcom and pcom)
to produce the requested compiled modules.
Each filename has the from {\bf filename.extension} where {\bf extension} is
either {\bf do} for a definitions module or {\bf po} for a process module.
For example,
\begin{verbatim}
      makehermes foo.do goo.po /u/hermes/bar.po zip.po
\end{verbatim}
compiles one definitions module and three process modules.

\subsubsection{Module dependencies and consistency}
A module {\bf bar} {\em depends on} another module {\bf foo} if 
either {\bf foo} is a definitions module 
imported by {\bf bar} (in the {\tt using( )} list), or  {\bf foo} is a process module 
statically linked by {\bf bar} (in the {\tt linking( ) } list).
{\bf bar} is {\em inconsistent} if a module {\bf bar}
depends on was compiled more recently than {\bf bar}.

makehermes finds all dependencies of each
{\bf filename} argument, and recompile
inconsistent modules.  Makehermes builds a dependency graph, in which
vertices represent modules and edges represent module dependencies.  
Two vertices represent each module, one for the source code ({\tt .p}
or {\tt .d}) and one for the compiled code ({\tt .po} or {\tt .do}).
In the dependency graph a directed edge points from each vertex
{\tt x.t} to vertex {\tt x.to}, where {\tt t} is either {\tt p} or {\tt d}.
If {\bf x} has {\bf y} in its using or linking lists then the graph 
contains an edge from
{\tt y.so} to {\tt x.to}, where {\tt s} and {\tt t} are
either {\tt p} or {\tt d} as appropriate.
% See figure \ref{dependencygraph}.

Makehermes assigns timestamps to the
dependency graph vertices by 
reading the file's unix modification time.
A vertex V is {\em inconsistent} if it has a timestamp earlier than
that of a vertex W on a path leading into V.
Makehermes traverses the DAG from the leaves towards the target filename,
attempting to compile all inconsistent modules along the way.

Makehermes searches for files in directories listed in
the Unix environment variable HPATH.  If HPATH
is not defined, makehermes searches on the path ``.:/u/hermes/bin''.  

If makehermes cannot find a ``.do'' or a ``.po'' file, then it will search 
for the source and compile it.  Makehermes places the compilation
output file into the current directory, even if the source resides in a 
different directory.  

\subsubsection{Options}
Makehermes recognizes 3 types of options.
The defaults are marked with a {\tt *}.
\begin{enumerate}
\item The {\em action} option which tells makehermes what to do with 
an inconsistent file.
\begin{verbatim}
 *c      (compile)              compile (pcom or dcom) the file
  p      (print)                print the filename and action that would be taken
\end{verbatim}
\item The {\em error} option controls makehermes's response to
    errors encountered while building the dependency graph and 
    applying its action.
\begin{verbatim}
 *s      (Stop)                 halt immediately on an error
  g      (Ignore)               ignore all errors
  o      (Continue Other Paths) on an error stop processing successors but 
                                process other paths 
\end{verbatim}
\item The {\em selection} option helps select the files to which
makehermes applies its action. 
\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:\\
{\tt hermi makehermes -agp bar.po}  will print out all the dependencies 
      for {\tt bar.po} and ignore errors. \\
{\tt hermi 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 would be compiled.  
  
\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,
a change is made to a source file in order to build a new version of a
system, but you do not want this new source to affect the current version,
even though you need to recompile the current version due to some other 
change.  

% Consider 
% a system decomposed into many modules being worked on simultaneously by
% several programmers.
% If one programmer adds a new type definition 
% to a module imported by many other
% modules and located early in the dependency graph then the change
% does not {\em actually} affect the modules that depend on the changed
% module, yet makehermes will recognize them to be inconsistent.
% This could trigger an avalanche of unnecessary compilation.
% Therefore, makehermes provides a means to limit the set of files it compiles.

Makehermes uses a list of directories 
to limit the set of files it compiles. 
It compiles {\bf only} those files stored in directories in the list.
The directory list is a standard unix shell path environment variable
called MKSCOPE.
Any file {\em not stored in} a directory listed in MKSCOPE is
declared to be consistent.
That is, makehermes sets the timestamp to infinity for
files stored in directories not in MKSCOPE.

For example, assume that 
{\tt MKSCOPE = .:/hermes/lib:/u/pip}, 
and that the module {\tt bar} imports the 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 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} it has a timestamp that is earlier than a module that it 
depends upon.  

If not defined, MKSCOPE defaults to the current working directory.



\subsubsection{Bugs}
\label{bugs}
Be cautious about file system links interacting with MKSCOPE and HPATH.  
If links cause a file to appear in one directory in HPATH and another
directory in MKSCOPE then makehermes will not compile the file.

Hermes supports two kinds of comments: \verb+ --+ and \verb+ /* */+.  
If the latter type of comment appears in a source file before the using 
list (listing the imported definitions modules) or before the list of 
static links, makehermes will behave unreliably.  
