jmake

JMAKE(1)                    General Commands Manual                   JMAKE(1)



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.
              ·      |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.

              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. :-)

              The '|' commands cannot be nested. 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.

              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 don'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.

              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
              Xoccurrence 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


       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 <ram@hptnos02.grenoble.hp.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)