Provided by: dist_3.5-30-3.3_all bug

NAME

       jmake - a generic makefile builder

SYNOPSIS

       jmake [ cpp options ]

DESCRIPTION

       Jmake  builds  a  makefile out of a rather high level description held in a Jmakefile file. The generated
       file is a Makefile.SH rather than a simple makefile, which means it is ready to be  used  in  conjonction
       with  metaconfig.  In particular, parameters such as "where to install executables" will be automatically
       determined by Configure and only the needed parameters will be taken into account.

       To use jmake you have to write a Jmakefile first, which describes the way things are to  be  built.  Your
       Jmakefile will be included inside a generic template through the C pre-processor.  This means you may use
       the usual C /**/ comments, but not the shell # comments.  The C comments will not appear in the generated
       Makefile.SH  but  lines  starting with ;# will finally appear as shell comments. If you have to write the
       string /* in the generated Makefile.SH then you have to escape it (otherwise jmake will think  of  it  as
       the start of a C comment). Simply put a # in front of the *, as in /#*.

       You  have a set of macros at your disposal, and all these macros are listed in the Index file, along with
       the piece of code they will expand to. Usually, a Jmakefile is fairly small and thus easier  to  maintain
       than  a  huge  Makefile.   Some  internal powerful commands allow you to write portable makefiles easily,
       without having to spend many efforts, because someone else already did the job for you :-).

       When you want to generate your makefile, you usually do not run jmake but use the jmkmf script which is a
       wrapper and will invoke jmake with the correct options.

       All the knowledge of jmake is held in two files: the template Jmake.tmpl and the  macro  definition  file
       Jmake.rules.  The first file includes the second, along with the Jmakefile.  It is sometimes necessary to
       know  how  things works to be able to correctly use all the features provided. For instance, you may have
       to write your own rules for a specific project. Although you cannot overwrite the predefined  rules,  you
       can  extent  the Jmake.rules file or simply add your macros in your Jmakefile.  You may also use #include
       statements when you want to share these macros and do not want to duplicate the code.

       The syntax in Jmake.rules is not elegant at all, but:

       -      It is easy to parse (like sendmail.cf or troff files).
       -      The rules are not supposed to change very often.
       -      It is simple enough to be mastered in five minutes. :-)

              Here is a small description:

       1)     To deal with various cpp implementations:

              •      Final @!\ means: end of line, next line starts at the left margin.
              •      Final @@\ means: end of line, next line is to be indented by one tab.

              There should always be one of @!\ or @@\ at the end of each  line.   The  only  exception  is  for
              macros  that  are  to be used as part of a rule body (e.g. RemoveTargetProgram). In that case, the
              first line (which holds the #define) should end with a single backslash.

       2)     Symbol definitions:

              •      >SYMBOL: defines the symbol.
              •      ?SYMBOL:<text>: keeps <text> iff SYMBOL is defined.
              •      %SYMBOL:<text>: keeps <text> iff SYMBOL is not defined.

              The ?SYM can be nested (logical AND), as in:

                   ?SYMBOL:%TOKEN:text

              which will keep text if SYMBOL is defined and TOKEN undefined.  To implement  a  logical  OR,  see
              below.

       3)     Commands:

              Commands can be passed to jmake. They start with a leading '|'.  Available commands are:

              •      |suffix <sx>: adds <sx> to the .SUFFIXES: list in the makefile.

              •      |rule:<text>: adds <text> to the building rule section.

              •      |rule: <text>: same as before, with a leading tab.

              •      |skip: skips text until a line starting with '-skip' is found.

              •      |subst: begins section where lines will be subject to variable substitution, until '-subst'
                     is  found.   This  means that when the Makefile.SH is run, all instances of $var within the
                     subst section will be substituted by the shell.

              •      |shell: emits section until matching '-shell' as-is in the generated Makefile.SH.  This can
                     be useful to prepare |case sections.  It is not allowed to nest shell sections.

              •      |case: this command must be followed by a shell variable  name  (without  its  leading  '$'
                     sign)  and a case-style pattern, for instance the string "var in f*".  It will generate the
                     corresponding "case" test in the Makefile.SH on the "$var" value and only if this  test  is
                     true  will  the  section  until  the  matching  '-case'  be  generated in the Makefile when
                     Makefile.SH is run.  It is possible to nest case sections freely.

              •      |expand <pattern>: expand lines until '-expand' with <pattern>. A complete example is shown
                     below.

              •      |once <symbol>: text up to '-once' appears only the first time.

              The '|' commands cannot be nested, unless otherwise noted.   In  particular,  due  to  the  simple
              implementation  of  |skip,  it  is impossible to put |skip inside a skipped part. However, a |once
              section may have |skip sections.  It is allowed to nest |case sections at will.

              Here is a way to implement a logical OR:

                   /* Implements SYMBOL or not TOKEN */
                   ?SYMBOL:text        /* Keeps text if SYMBOL */
                   %SYMBOL:|skip
                        %TOKEN:text         /* Keeps text if not TOKEN */
                   -skip

              Actually, this is ugly, because the text has to appear twice.  Fortunately, I did not use it. :-)

              But actually, as you have surely already guessed, the best way to implement a logical OR is to use
              De Morgan's Law:

                   not (p or q) <=> not p and not q

                   /* Implements SYMBOL or not TOKEN (attempt #2) */
                   %SYMBOL:?TOKEN:|skip
                   text                     /* If SYMBOL or not TOKEN */
                   -skip

              Who said they didn't care ? ;-)

              Expansion is done with the expand command.  It has been provided to avoid some cumbersome writings
              in makefiles when you have to repeat some  silly  lines  that  only  differ  in  file  names,  for
              instance.  Let's look at an example first:

                   |expand a!foo bar! b!yes no!
                   !a::
                        echo !a, !b
                   -expand

              Then  two rules will be printed, and the values of (a,b) for the first will be (foo, yes), for the
              second (bar, no).  Substitution is controled by the '!' character.  If the word to be  substituted
              is  part  of  another  one,  detach  with  the  ^^ construct as in:  !b^^c.  It is possible to use
              Makefile macros in the <pattern>, and they will be expanded by jmake.  If this  is  not  what  you
              want,  escape  the  first  '$'  sign (this is a Makefile escape, i.e. you must double the '$', not
              precede it with a backslash). A // stands for the null substitution value.
              The ^^^ construct behaves like ^^, i.e. it is stripped out, but  it  also  removes  any  following
              white  space after the ^^^.  If you prepend something to a macro argument, and that macro argument
              was written with spaces before it, then this will let you concatenate something right before  that
              argument's final value.

              Here  is  another  example  which  shows  how  the  macro  Expand  can  be used.  It is defined in
              Jmake.rules as:

                   #define Expand(rule, pattern) @!\
                   |expand pattern @!\
                   rule @!\
                   -expand

              So we can write in the Jmakefile:

                   |skip
                   A = foo bar
                   -skip

                   #define Rule @!\
                   $(DIR)/!a^^.o: !a^^.o @@\
                        $(CC) -c !a^^.c @@\
                        $(MV) !a^^.o $(DIR)

                   Expand(Rule, a!$(A)!)

              which will generate in Makefile.SH:

                   $(DIR)/foo.o: foo.o
                        $(CC) -c foo.c
                        $(MV) foo.o $(DIR)

                   $(DIR)/bar.o: bar.o
                        $(CC) -c bar.c
                        $(MV) bar.o $$(DIR)

              The 'A' declaration has been surrounded by skip, so that it  does  not  appear  in  the  generated
              Makefile.SH, but it will be taken into account by jmake for the substitution in the pattern.

              The  number  of expansions is determined by the number of possible values for the first parameter.
              If other parameters have less substitution values, they will get void ones.

              It is possible to add a regular expression at the end of '-expand'. This regular  expression  will
              be  removed  from  the  final  set of expansion at the end of each line. It is also possible to do
              substitutions in the expanded item, by  using  the  syntax  (if  'f'  is  the  expanded  variable)
              !f:<p>=<q>  where  <p> and <q> are two regular expressions (without spaces).  The pattern <p> will
              be replaced by the pattern <q> (only the first occurrence will be replaced).

              Finally, you may refer in the expanded section to variables whose value is  computed  via  another
              expansion, which makes it easy to define generic Jmakefiles.

              Example:

                   SRC = foo.c bar.c
                   OBJ = \
                   |expand f!$(SRC)!
                        !f:\.c=\.o \
                   -expand \\
                   INC = \
                   |expand f!$(OBJ)!
                        !f:\.o=\.h \
                   -expand \\

              which will generate in Makefile.SH:

                   SRC = foo.c bar.c
                   OBJ = \
                        foo.o \
                        bar.o
                   INC = \
                        foo.h \
                        bar.h

              Do  not forget to protect special characters in your regular expressions such as backslash, point,
              etc...

              The once command is tagged with a name. The first time the name appears,  the  once  construct  is
              ignored  and  the text up to '-once' will be copied in the generated Makefile.SH.  However, future
              occurences of the same name will be ignored (once will behave like skip).

              Example:

                   |once this_is_a_name
                   <text>
                   -once

              The shell command can be used to generate a shell fragment in the Makefile.SH.  For instance,  the
              following section in the Jmakefile:

                   |shell
                   case "$d_usegtk1" in
                   define) glib=1; gtk=1;;
                   esac
                   -shell

              will cause the generation of the enclosed fragment in the Makefile.SH to compute the values of the
              glib and gtk variables based on the configuration variable d_usegtk1 set by running Configure.

              In  turn, this can be used in subsequent case sections to activate parts of the Makefile only when
              building for GTK1 using glib-1.x:

                   |case glib in 1
                   display:
                        echo "Building for glib-1.x"
                   -case

              This section will generate something like this in the Makefile.SH:

                   !NO!SUBS!
                   case "$glib" in
                   1)
                        $spitshell >>Makefile <<'!NO!SUBS!'
                   display:
                        echo "Building for glib-1.x"
                   !NO!SUBS!
                        ;;
                   esac
                   $spitshell >>Makefile <<'!NO!SUBS!'

              And when running Makefile.SH, the  "display"  rule  above  will  only  appear  when  building  for
              glib-1.x.  The form of the final Makefile can therefore depend on the configuration options chosen
              when Configure was run.

       4)     Initializations:

              •      +<line>: Puts the whole line in the initialization section.
              •      ++SYMBOL <value>: Adds <value> to the SYMBOL macro.

       5)     User-defined variables:

              The  user  may  define CFLAGS, LDFLAGS or DPFLAGS as additional flags to be used in C compilation,
              linking phase or depend target. It is thus possible  to  add  some  extra  flags  such  as  -I  or
              libraries for Makefiles in specific sub-directories.

AUTHOR

       Raphael Manfredi <Raphael_Manfredi@pobox.com>

FILES

       Jmakefile           High level description of Makefile.SH
       Jmake.rules         File holding the macro definitions
       Jmake.tmpl          Template used to mould Makefile.SH

BUGS

       On  systems  whose cpp reduces multiple tabs and spaces to a single space, jmake attempts to put back any
       necessary tabs (which make expects in front of rules) but does not properly formats the body of the  rule
       itself.

       There  is a bootstraping problem when creating the first Makefile.SH, because you cannot run it through a
       shell until there is a decent  Configure  script,  but  you  can't  run  metaconfig  before  there  is  a
       Makefile.SH or some needed symbols will not be defined.

SEE ALSO

       jmkmf(1), metaconfig(1).

                                                       ram                                              JMAKE(1)