home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume27
/
jam
/
part01
next >
Wrap
Text File
|
1993-11-14
|
57KB
|
2,345 lines
Newsgroups: comp.sources.unix
From: seiwald@vix.com (Christopher Seiwald)
Subject: v27i081: jam - just another make, Part01/05
Message-id: <1.753385306.22859@gw.home.vix.com>
Sender: unix-sources-moderator@gw.home.vix.com
Approved: vixie@gw.home.vix.com
Submitted-By: seiwald@vix.com (Christopher Seiwald)
Posting-Number: Volume 27, Issue 81
Archive-Name: jam/part01
Jam - make(1) redux
FEATURES
Jam is a make-like program that supplants make's implicit rules
with a real language for defining dependencies and update
actions. Its features include:
o Jam finds header file dependencies using regexp(3)
patterns.
o Jam has a real language, including conditionals and
list valued variables.
o A central Jambase defines the rules, which can be
customized for large products.
o Per directory Jamfiles are simple and are normally
system independent.
o Jam can build large systems without recursing.
o Jam never tries to store state in any funny files.
o Jam runs on UNIX and VMS, and is portable.
PORTING
Build jam with make(1) on:
BSDI BSD/386 1.0
DEC 3000/500 OSF/1
DG AViiON DGUX 5.4
HP 9000/700 HPUX 9.0
IBM RS/6000 AIX *
SGI R4000 IRIX 5.0
Sequent 2000 PTX V2.1.0
Sun 3 SunOS4.0
Sun 4 Solaris 2 *+
Sun 4 SunOS4.1
VAX Ultrix 4.2
* requires editing Makefile
+ only works with SUNSwpro CC (dirent confusion)
Build jam with @build.com on:
VAX VMS 5.4
DEC 3000/500 OPENVMS *
* requires editing build.com
See the "Porting" file for info on more wildcat ports.
Comments to the author!
Christopher Seiwald
Seiwald@vix.com
November, 1993
Submitted-by: seiwald@vix.com
Archive-name: jam - make(1) redux/part01
#!/bin/sh
# This is jam - make(1) redux, a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 11/15/1993 03:06 UTC by seiwald@vix.com
# Source directory /usr/team/seiwald/jam
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 1709 -r--r--r-- README
# 6280 -r--r--r-- Jambase.5
# 13472 -r--r--r-- jam.1
# 619 -r--r--r-- Build.com
# 3419 -r--r--r-- Examples
# 320 -r--r--r-- Makefile
# 2355 -r--r--r-- Porting
# 9400 -r--r--r-- Jambase
# 8788 -r--r--r-- Jambase.VMS
# 532 -r--r--r-- Jamfile
# 13686 -r--r--r-- compile.c
# 1082 -r--r--r-- compile.h
# 182 -r--r--r-- execcmd.h
# 772 -r--r--r-- execunix.c
# 1733 -r--r--r-- execvms.c
# 8227 -r--r--r-- expand.c
# 128 -r--r--r-- expand.h
# 842 -r--r--r-- filesys.h
# 6593 -r--r--r-- fileunix.c
# 8453 -r--r--r-- filevms.c
# 5071 -r--r--r-- hash.c
# 311 -r--r--r-- hash.h
# 2368 -r--r--r-- headers.c
# 119 -r--r--r-- headers.h
# 2752 -r--r--r-- lists.c
# 427 -r--r--r-- lists.h
# 14415 -r--r--r-- make.c
# 131 -r--r--r-- make.h
# 1671 -r--r--r-- newstr.c
# 148 -r--r--r-- newstr.h
# 1584 -r--r--r-- option.c
# 428 -r--r--r-- option.h
# 923 -r--r--r-- parse.c
# 354 -r--r--r-- parse.h
# 39 -r--r--r-- patchlevel.h
# 31610 -r--r--r-- regexp.c
# 728 -r--r--r-- regexp.h
# 4141 -r--r--r-- rules.c
# 4149 -r--r--r-- rules.h
# 3568 -r--r--r-- scan.c
# 312 -r--r--r-- scan.h
# 1438 -r--r--r-- search.c
# 129 -r--r--r-- search.h
# 3402 -r--r--r-- timestamp.c
# 137 -r--r--r-- timestamp.h
# 4103 -r--r--r-- variable.c
# 213 -r--r--r-- variable.h
# 4003 -r--r--r-- jam.c
# 3290 -r--r--r-- jam.h
# 22556 -r--r--r-- jamgram.c
# 680 -r--r--r-- jamgram.h
# 5366 -r--r--r-- jamgram.y
# 4795 -r--r--r-- jamgram.yy
# 655 -r--r--r-- jamgramtab.h
# 1301 -r--r--r-- yyacc
#
# ============= README ==============
if test -f 'README' -a X"$1" != X"-c"; then
echo 'x - skipping README (File already exists)'
else
echo 'x - extracting README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
XJam - make(1) redux
X
XFEATURES
X
X Jam is a make-like program that supplants make's implicit rules
X with a real language for defining dependencies and update
X actions. Its features include:
X
X o Jam finds header file dependencies using regexp(3)
X patterns.
X
X o Jam has a real language, including conditionals and
X list valued variables.
X
X o A central Jambase defines the rules, which can be
X customized for large products.
X
X o Per directory Jamfiles are simple and are normally
X system independent.
X
X o Jam can build large systems without recursing.
X
X o Jam never tries to store state in any funny files.
X
X o Jam runs on UNIX and VMS, and is portable.
X
XPORTING
X
X Build jam with make(1) on:
X
X BSDI BSD/386 1.0
X DEC 3000/500 OSF/1
X DG AViiON DGUX 5.4
X HP 9000/700 HPUX 9.0
X IBM RS/6000 AIX *
X SGI R4000 IRIX 5.0
X Sequent 2000 PTX V2.1.0
X Sun 3 SunOS4.0
X Sun 4 Solaris 2 *+
X Sun 4 SunOS4.1
X VAX Ultrix 4.2
X
X * requires editing Makefile
X + only works with SUNSwpro CC (dirent confusion)
X
X Build jam with @build.com on:
X
X VAX VMS 5.4
X DEC 3000/500 OPENVMS *
X
X * requires editing build.com
X
X See the "Porting" file for info on more wildcat ports.
X
XOTHER FILES
X
X Aside from source files, there is:
X
X Build.com VMS command script
X Examples sample Jamfiles
X Makefile a bootstrap makefile
X Porting notes on porting jam
X Jambase.5 Jambase man page
X jam.1 jam man page
X yyacc a yacc pre-preprocessor
X
XComments to the author!
X
XChristopher Seiwald
XSeiwald@vix.com
XNovember, 1993
SHAR_EOF
chmod 0444 README ||
echo 'restore of README failed'
Wc_c="`wc -c < 'README'`"
test 1709 -eq "$Wc_c" ||
echo 'README: original size 1709, current size' "$Wc_c"
fi
# ============= Jambase.5 ==============
if test -f 'Jambase.5' -a X"$1" != X"-c"; then
echo 'x - skipping Jambase.5 (File already exists)'
else
echo 'x - extracting Jambase.5 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Jambase.5' &&
X.TH JAM 5 "30 August 1993"
X.SH NAME
XJambase \-
X.BR jam (1)
Xboilerplate
X.SH SYNOPSIS
X.B /usr/share/lib/jam/Jambase
X.br
X.B Jamfile
X.SH DESCRIPTION
X.PP
X.B Jambase
Xcontains a set of
X.B jam
Xrule definitions that provide roughly
X.BR make (1)-like
Xfunctionality.
X.B Jam
Xreads
X.BR Jambase ,
Xwhich in turn includes the
X.B Jamfile
Xfrom the current directory.
XThe rules defined and variables used for the
X.B Jamfile
Xare as follows:
X.SS Rules
X.PP
X.IP "MAIN image : sources ;"
X.IP
XCompiles
X.I sources
Xand links them into
X.IR image .
X.I Image
Xbecomes a dependency of
X.IR exe ,
Xitself a dependency of
X.IR all .
X.IP "LIBS image : libraries ;"
X.IP
XAdds
X.I libraries
Xas dependencies of
X.I image
Xand includes them during the linking.
X.IP "SETUID image ;"
X.IP
XSets the setuid bit on
X.I image
Xafter linking.
X.IP "UNDEFINES image : symbols ;"
X.IP
XTries to convice the loader that symbols need to be "undefined" for
Xthe linking to work.
X.IP "LIBRARY library : sources ;"
X.IP
XCompiles
X.I sources
Xand archives them into
X.IR library .
XThe intermediate objects are deleted.
X.I Library
Xbecomes a dependency of
X.IR lib ,
Xitself a dependency of
X.IR all .
X.IP "OBJECT object : source ;"
X.IP
XCompiles a single source file
X.I source
Xinto
X.IR object .
XThis rule is used by
X.B MAIN
Xand
X.BR LIBRARY .
XArranges for
X.I source
Xto be scanned for header file includes when then become dependencies of
X.IR object .
XSuch dependencies are "soft": missing headers are not an error.
X.IP
XFor
X.IR source ,
Xthe following suffixes are recognised:
X.RS
X.IP .c
XC source file
X.IP .l
X.IR lex (1)
Xsource file.
XThe resuling lex.yy.c is renamed to be the same base as the
X.IR source .
X.IP .y
X.IR yacc (1)
Xsource file.
XThe resulting y.tab.c and y.tab.h are renamed to the same base as
X.IR source .
X.PP
XAll other suffixes are passed to the rule
X.IP
XCCUSER object : source ;
X.PP
Xto be defined in the user's
X.I Jamfile
X(or elsewhere).
X.RE
X.IP "BULK directory : sources ;"
X.IP
XCopies
X.I sources
Xinto
X.IR directory .
XAll targets become dependencies of
X.IR files ,
Xitself a dependency of
X.IR all .
X.IP "FILE target : source ;"
X.IP
XCopies
X.I source
Xinto
X.IR target .
X.I Target
Xbecome a dependency of
X.IR files ,
Xitself a dependency of
X.IR all .
X.IP "SHELL image : source ;"
X.IP
XCopies
X.I source
Xinto the executable
X.IR sh(1)
Xscript
X.IR image .
X.I Image
Xbecome a dependency of
X.IR shell ,
Xitself a dependency of
X.IR all .
X.IP "INSTALLBIN sources ; "
X.IP
XCopy
X.I sources
Xinto /usr/local/bin.
XAll targets become dependencies of
X.IR install .
X.IP "INSTALLLIB sources ;"
X.IP
XCopy
X.I sources
Xinto /usr/local/lib.
XAll targets become dependencies of
X.IR install .
X.IP "INSTALLMAN sources ;"
X.IP
XCopy
X.I sources
Xinto the appropriate subdirectory of /usr/local/man.
XAll targets become dependencies of
X.IR install .
X.IP "RMTEMPS targets : sources ;"
X.IP
XMarks
X.I sources
Xas temporary with the
X.I TEMPORARY
Xrule, and deletes
X.I sources
Xonce
X.I targets
Xare built.
XMust be the last rule invoked on
X.IR targets .
XUsed internally by
X.BR OBJECT .
X.SS Variables
X.PP
XAR (default
X.IR "ar ru" )
X.IP
XThe archiver used for
X.BR LIBRARY .
X.PP
XBINDIR (default
X.IR "/usr/local/bin" )
X.IP
XThe install directory for
X.BR INSTALLBIN .
X.PP
XCC (default
X.IR cc )
X.IP
XC compiler used for
X.BR OBJECT .
X.PP
XCCFLAGS (no default)
X.IP
XFlags handed to the C compiler for
X.BR OBJECT .
XN.B.
X.I OPTIM
Xis also handed to the C compiler.
X.PP
XEXEMODE (default
X.IR 711 )
X.IP
XPermissions for executables linked with
X.BR MAIN .
X.PP
XFILEMODE (default
X.IR 644 )
X.IP
XPermissions for files copied by
X.B FILE
Xor
X.BR BULK .
X.PP
XHDRPATTERN (default ^#[\\t ]*include[\\t ]*[<"](.*)[">].*$)
X.IP
XThe
X.IR regexp (3)
Xpattern for finding header file includes in source files.
XThe
X.B OBJECT
Xrule sets the
X.I Jam
Xspecial variable
X.I HDRSCAN
Xto
X.I $(HDRPATTERN)
Xfor all of its sources.
XThe found header files are made dependencies of the target to
X.BR OBJECT .
X.PP
XHDRS (no default)
X.IP
XDirectories to be scanned for header files and handed to the C
Xcompiler with -I. The
X.B OBJECT
Xrule sets
X.I HDRS
Xto
X.I $(HDRS)
Xfor each of its sources.
X.PP
XLEX (default
X.IR lex )
X.IP
XThe
X.IR lex (1)
Xcommand and flags.
X.PP
XLIBDIR (default
X.IR /usr/local/lib )
X.IP
XThe target directory for
X.BR INSTALLLIB .
X.PP
XLINK (default
X.IR cc )
X.IP
XThe linker.
X.PP
XLINKFLAGS (default
X.IR $(CCFLAGS) )
X.IP
XFlags handed to the linker.
X.PP
XLINKLIBS (no default)
X.IP
XLibraries to hand to the linker.
XThese libraries are not dependencies of the target image.
X.PP
XLOCATE_TARGET (no default)
X.IP
XThe directory for object modules and other intermediate files generated by
X.BR OBJECT .
XThis works by setting the
X.I Jam
Xspecial variable
X.I LOCATE
Xto the value of
X.I $(LOCATE_TARGET)
Xfor each of
X.BR OBJECT 's
Xtargets.
X.PP
XMV (default
X.IR "mv -f" )
X.IP
XThe file rename command and options.
X.PP
XOPTIM (default
X.IR -O )
X.IP
XMore flags handed to the C compiler.
X.PP
XRANLIB (default
X.IR ranlib )
X.IP
XIf set, the command string to be invoked on each library after archiving.
X.PP
XRM (default
X.IR "rm -f" )
X.IP
XThe command and options to remove a file.
X.PP
XSEARCH_SOURCE (no default)
X.IP
XThe directory to find sources listed with
X.BR MAIN ,
X.BR LIBRARY ,
X.BR OBJECT ,
X.BR BULK ,
X.BR FILE ,
X.BR SHELL ,
X.BR INSTALLBIN ,
X.BR INSTALLLIB ,
Xand
X.BR INSTALLMAN
Xrules.
XThis works by setting the
X.I Jam
Xspecial variable
X.I SEARCH
Xto the value of
X.I $(SEARCH_SOURCE)
Xfor each of the rules' sources.
X.PP
XSHELLHEADER (default
X.IR "#!/bin/sh" )
X.IP
XA string inserted to the first line of every file created by the
X.B SHELL
Xrule.
X.PP
XSHELLMODE (default
X.IR 755 )
X.IP
XPermissions for files installed by
X.BR SHELL .
X.PP
XSTDHDRS (default
X.IR /usr/include )
X.IP
XDirectories where headers can be found without resorting to using the
X-I flag to the C compiler.
X.PP
XUNDEFFLAG (default
X.IR "\-u _" )
X.IP
XThe flag prefixed to each symbol for the
X.B UNDEFINES
Xrule.
X.PP
XYACC (default
X.IR "yacc -d" )
X.IP
XThe
X.IR yacc (1)
Xcommand and flags.
X.PP
XJAMFILE (default
X.IR Jamfile )
X.IP
XThe user provided file listing the sources to be built.
X
X.SH BUGS
X.PP
XBecause libraries are passed unbound to the
X.B LINK
Xrule as
X.IR $(NEEDLIBS) ,
Xthey cannot be located with
X.IR $(LOCATE) ,
Xbecause
X.I $(LOCATE)
Xaffects only changes the bound file name.
X.PP
XThere's no
X.IR yacc (1)
Xon VMS, so the guts of the rules are commented out.
SHAR_EOF
chmod 0444 Jambase.5 ||
echo 'restore of Jambase.5 failed'
Wc_c="`wc -c < 'Jambase.5'`"
test 6280 -eq "$Wc_c" ||
echo 'Jambase.5: original size 6280, current size' "$Wc_c"
fi
# ============= jam.1 ==============
if test -f 'jam.1' -a X"$1" != X"-c"; then
echo 'x - skipping jam.1 (File already exists)'
else
echo 'x - extracting jam.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'jam.1' &&
X.TH JAM 1 "30 August 1993"
X.SH NAME
Xjam \-
X.BR make (1)
Xredux
X
X.SH SYNOPSIS
X.B jam
X[
X.B \-n
X] [
X.BI \-d " debug"
X] [
X.BI \-f " Jambase"
X] ... [
X.BI \-t " target"
X] ... [
X.I target
X] ...
X
X.SH DESCRIPTION
X.PP
X.B Jam
Xrecursively builds target files from their source files, using a
X.B Jambase
Xto define rules and a
X.B Jamfile
Xto lists the targets and sources in terms of those rules. Together
Xthey define the dependency tree and the updating actions for all
Xtargets:
X.B jam
Xdoes not rely on suffix-driven implicit rules or directory contents.
XA default
X.BR Jambase
Xis provided with
X.BR jam ;
Xthe user supplies the
X.BR Jamfile .
X.PP
XSee
X.BR Jambase (5)
Xfor information on writing Jamfiles.
XThis manual page describes the program which interprets
X.BR Jambase .
X
X.SH OPTIONS
X.PP
X.B Jam
Xsupports the following options:
X.IP "-n"
XDon't actually execute the updating actions, but do everything else.
X.IP "-d<n>"
XSet the debug level to <n>. Interesting values are:
X.PP
X.RS
X0 Emit only errors
X.br
X1 Emit update action tracing (default)
X.br
X2 Emit update commands
X.br
X3 Produce dependency information
X.br
X4 Show timestamps of bound files
X.br
X5 Show rule invocation
X.br
X6-9 debugging
X.RE
X.IP "-f<file>"
XRead <file> instead of
X.BR Jambase .
X.IP "-t<target>"
XPretend <target> is new, regardless of its actual timestamp.
X
X.SH "THE JAM LANGUAGE"
X.PP
XThe
X.B jam
Xlanguage supports defining and using rules, setting variables, and flow
Xof control structures. The
X.B Jambase
Xand
X.B Jamfile
Xshare this common language.
X.SS "Lexical Features"
X.B Jam
Xtreats its input files as whitespace separated tokens, with two
Xexceptions: double quotes (") can enclose whitespace to embed it into a
Xtoken, and everything between the matching curly braces ({}) in the
Xdefinition of a rule action is treated as a single string.
XA backslash (\\) can escape a double quote.
X.SS Targets
XTargets and sources (collectively "targets") are files to be updated
Xand the files used in updating those targets. A target is simply a
Xfilename, either rooted or relative to the directory of
X.BR Jam 's
Xinvocation. The special syntax,
X.IR "file(member)" ,
Xrefers to an
X.BR ar (1)
Xlibrary member.
XThe special syntax,
X.IR "<grist>file" ,
Xperturbs a file name to distinguish it from other files
Xwith the same name. The <grist> is stripped from the name during
Xbinding (see below).
X.SS Rules
X.BR Jam 's
Xbasic entity is called a rule, which is used to relate targets to their
Xsources. A rule is defined in two parts: the
X.B jam
Xstatements to execute when the rule is invoked (essentially a procedure
Xcall), and the actions (shell commands) to execute in order to update
Xthe targets of the rule. A rule may have a procedure definition, actions,
Xor both.
X.PP
XThe
X.B jam
Xstatements for defining and invoking rules are as follows, where
X<targets> and <sources> are lists of filenames, <statements> are
X.B jam
Xstatements, and <string> is a shell script:
X.IP
Xrule <rulename> { <statements> }
X.IP
Xactions [ modifiers ] <rulename> { <string> }
X.IP
X<rulename> <targets> [ : <sources> ] ;
X.PP
XThe first form defines a rule's procedure; the second defines the rule's
Xupdating actions; the third invokes the rule. Redefining a rule's
Xprocedure or actions replaces the previous definition.
X.PP
XInvoking a rule executes the procedure for the rule (if any) and associates
Xany update actions for the targets. More than one update action may be
Xassociated with a target: they are executed in the order in which they
Xare added.
X.PP
XIn both the rule's precedure definition and the rule's actions, the
Xspecial variables $(<) and $(>) refer to the <targets> and <sources>
Xgiven at rule invocation. However, in the rule's actions $(<) and $(>)
Xrefer to the <targets> and <sources> after they have been bound by the
Xbinding phase (see below).
X.B Jam
Xissues a warning if $(<) or $(>) have elements not in the dependency tree.
X.PP
XThe following action modifiers are understood:
X.IP "actions ignore"
XThe return status of the shell commands is ignored.
X.IP "actions piecemeal"
XThe shell commands are repeatedly invoked with a subset of $(>)
Xsmall enough to fit in a command buffer.
X.IP "actions quietly"
XThe action is not echoed to the standard output.
X.IP "actions together"
XThe $(>) from multiple instances of the same action on the same
Xtarget are glommed together.
X.IP "actions updated "
X$(>) includes only targets marked for updating.
X.SS "Builtin Rules"
X.PP
X.B Jam
Xhas six builtin rules, none of which have updating actions:
X.PP
X.IP "DEPENDS <targets> : <sources>"
X.br
XMakes <sources> dependents of <targets>.
X.IP "ECHO <args>"
X.br
XBlurts out the message <args> to stdout.
X.IP "INCLUDES <targets> : <sources>"
X.br
XMakes <sources> dependents of anything of which <targets> is a dependent.
X.IP "NOCARE <targets>"
X.br
XMarks <targets> as possibly being bogus (see binding, below).
X.IP "NOTIME <targets>"
X.br
XMarks <targets> as not being files (see binding, below).
X.IP "TEMPORARY <targets>"
X.br
XMarks <targets> as temporary (see binding, below).
X.SS "Flow of Control"
X.PP
X.B Jam
Xhas several simple flow of control statements:
X.IP
Xinclude <a> ;
X.IP
Xfor <a> in <args> { <statements> }
X.IP
Xswitch <a> { case <v1> : <statements> ; case <v2> : <statements> ; ... }
X.IP
Xif <cond> { <statements> } else { <statements> }
X.PP
XThe
X.B include
Xstatement includes the named file; the path is relative to
Xthe directory from which
X.B jam
Xwas invoked.
X.PP
XThe
X.B for
Xloop executes <statements> for each value in <args>, setting the
Xvariable <a> to the value. <a> is not variable expanded.
X.PP
XThe
X.B switch
Xstatement executes zero or one of the enclosed <statements>,
Xdepending on which value <a> matches. The <v> values are not variable
Xexpanded. A <v> value of * matches anything, but there is no other
Xwildcarding (sorry).
X.PP
XThe
X.B if
Xstatement does the obvious; the
X.B else
Xclause is optional.
X.I <cond>
Xis built of:
X.PP
X.RS
X<a> true if <a> is a non-zero length string
X.br
X<a1> = <b1> strings equal
X.br
X<a1> != <b1> strings not equal
X.br
X<a1> < <b1> string less than
X.br
X<a1> <= <b1> string less than or equal to
X.br
X<a1> > <b1> string greater than
X.br
X<a1> >= <b1> string greater than or equal to
X.PP
X! <cond> condition not true
X.br
X<cond> && <cond> conjunction
X.br
X<cond> || <cond> disjunction
X.br
X( <cond> ) grouping
X.RE
X.PP
XIn comparisons, the arguments may (through variable expansion) be more
Xthan one token, but only the first token takes part in the comparison.
XIf through variable expansion the argument is zero tokens, a single
Xtoken of a zero length string is used instead.
X.SS Variables
X.PP
X.B Jam
Xvariables are lists of strings, with zero or more elements. An unset
Xvariable is indistinguishable from a variable whose value is an empty
Xlist. Variables are either global or target specific.
XAll variables are referenced as $(VARIABLE).
X.PP
XA variable is set with:
X.IP
X<variable> = <values> ;
X.IP
X<variable> default = <values> ;
X.IP
X<variable> on <targets> = <values> ;
X.PP
XThe first form sets <variable> globally to the given <values>;
Xthe second form only sets the variable if it is unset; the
Xthird form arranges for <variable> to take on the <values> only
Xwhen binding and updating <targets>.
X.PP
XOn program startup,
X.B jam
Ximports the environment variable settings into
X.B jam
Xvariables.
X.B Jam
Xvariables are not re-exported.
X.SS "Variable Expansion"
X.PP
XBefore executing a statement
X.B jam
Xperforms variable expansion on each token that is not a keyword or rule
Xname. Such tokens with embedded variable references are replaced with
Xzero or more tokens. Variable references are of the form $(v) or
X$(vm), where v is the variable name and m are optional modifiers.
X.PP
XVariable expansion in a rule's actions is similar to variable expansion
Xin statements, except that the action string is tokenized at whitespace
Xwithout regards for quoting.
X.PP
XThe result of a token after variable expansion is the product of the
Xcomponents of the token, where each component is a literal substring or
Xa list substituting a variable reference. For example:
X.PP
X.RS
X$(X) -> a b c
X.br
Xt$(X) -> ta tb tc
X.br
X$(X)z -> az bz cz
X.br
X$(X)-$(X) -> a-a a-b a-c b-a b-b b-c c-a c-b c-c
X.RE
X.PP
XThe variable name and modifiers can themselves contain a variable
Xreference, and this partakes of the product as well:
X.PP
X.RS
X$(X) -> a b c
X.br
X$(Y) -> 1 2
X.br
X$(Z) -> X Y
X.br
X$($(z)) -> a b c 1 2
X.RE
X.PP
XBecause of this product expansion, if any variable reference in a token
Xis unset then the result of the expansion is an empty list.
X.PP
XModifiers to a variable are of two varieties: subelement selection and
Xfilename editing. They are:
X.PP
X.IP "[<n>]"
XSelect only element number <n> (starting at 1). If the variable contains
Xfewer than <n> elements, the result is a zero element list.
X.IP "[<n>-<m>]"
XSelect only elements number <n> through <m>.
X.IP "[<n>-]"
XSelect only elements number <n> through the last.
X.IP ":G=<grist>"
XReplace the grist of the filename with <grist>.
X.IP ":D=<path>"
XReplace directory component of filename with <path>.
X.IP ":B=<base>"
XReplace base part of filename with <base>.
X.IP ":S=<suf>"
XReplace suffix of filename with <suf>.
X.IP ":M=<mem>"
XReplace archive member name with <mem>.
X.IP ":R=<root>"
XPrepend <root> to whole name, if not already rooted.
X.IP ":<components>"
XReplace all components not listed with an empty string; components
Xis one or more of the string
X.IR GDBSM .
X
X.SH OPERATION
X.B Jam
Xhas three phases of operation: parsing, binding, and updating.
X.SS Parsing
X.PP
X.B Jam
Xparses the file
X.BR Jambase ,
Xwhich by default includes
X.BR Jamfile .
XThe results of parsing are: the dependency tree of targets; update
Xactions associated with the targets; and variables set to specific
Xvalues.
X.PP
X.SS Binding
XAfter parsing,
X.B jam
Xrecursively decends the dependency tree, attempting to locate each
Xtarget file and determine if it is in need of updating.
X.PP
XBy default, a target is located at the actual path of the target,
Xrelative to the directory of
X.BR jam 's
Xinvocation. If $(LOCATE) is set to a directory name,
X.B jam
Xlocates the target in that directory; else if $(SEARCH) is set to
Xa directory list,
X.B jam
Xfirst searches along the directory list for the target file. If the
Xtarget name has a rooted directory component then $(SEARCH) and
X$(LOCATE) do not apply: the target is located at the actual path of the
Xtarget. If a target is marked as not being a file (using the builtin
Xrule NOTIME), it is left unbound to a file name.
X.PP
XA target is marked for updating if either it cannot be found, it's
Xfilesystem modification time is older than any of its dependents, or if
Xany of its dependents are marked for updating. If a target is missing,
Xno updating actions are associated with the target, and the target has
Xnot been marked with the builtin rule NOCARE,
X.B jam
Xemits a warning. If a target is missing and it is marked as temporary
X(with the builtin rule TEMPORARY), then its parent's modification time
Xis used when comparing against dependents. If a target is marked as
Xnot being a file (using the builtin rule NOTIME), it is marked for
Xupdating only if any of its dependents are marked for updating.
X.PP
XIf a target is a source file that includes header files,
X.B jam
Xinvokes the rule $(HDRRULE) on the target giving the (unbound) names of
Xthe headers file as sources. A target is scanned for header file
Xdependencies if $(HDRSCAN) is set to an regexp(3) pattern with ()'s
Xsurrounding the include file name.
X.PP
XBetween binding and updating,
X.B jam
Xannounces the number of targets to be updated.
X.SS Updating
XAfter binding,
X.B jam
Xagain recursively decends the dependency tree, this time executing the
Xupdate actions for each target that was marked for update during the
Xbinding phase. If a target's updating actions fail, then all targets
Xdependent on that target are skipped.
X
X.SH DIAGNOSTICS
X.PP
XIn addition to generic error messages,
X.B jam
Xmay emit one of the following:
X.PP
Xwarning: unknown rule X
X.IP
XA rule was invoked which has never been defined with
Xthe "actions" or the "rule" statements.
X.PP
Xusing N temp target(s)
X.IP
XTargets marked as being temporary (but nonetheless present)
Xhave been found.
X.PP
Xupdating N target(s)
X.IP
XTargets are out of date and will be updated.
X.PP
Xcan't make N target(s)
X.IP
XDue to sources not being found, targets cannot be made.
X.PP
Xwarning: X depends on itself
X.IP
XSomehow a target depends either directly or through its dependents
Xback on itself. This most frequently happens with header file
Xinclusions.
X.PP
Xdon't know how to make X
X.IP
XA needed target is not present and no actions are defined to create
Xthe target.
X.PP
XX skipped for lack of Y
X.IP
XA dependent failed to build, and thus a target cannot be built.
X.PP
Xwarning: using independent target X
X.IP
XA target that is not a dependent of any target being made is
Xbeing referenced with $(<) or $(>).
X.PP
XX removed
X.IP
X.B Jam
Xremoved a partially built target after being interrupted.
X
X.SH FILES
X/usr/local/lib/Jambase
X
X.SH BUGS, LIMITATIONS
X.PP
XBecause the
X.B include
Xstatement works by pushing a new file in the input stream of the
Xscanner rather than recursively invoking the parser on the new file,
Xmultiple include statements in a rule's procedure causes the files
Xto be included in reverse order.
X.PP
XIn a rule's actions, only $(<) and $(>) refer to the bound file names:
Xall other variable references get the unbound names. This mostly
Xaffects
X.IR IILIBRARY .
XSee
X.IR Jambase (5).
X.PP
XSearching for include files is slow.
X
X.SH SEE ALSO
X.IR Jambase (5)
SHAR_EOF
chmod 0444 jam.1 ||
echo 'restore of jam.1 failed'
Wc_c="`wc -c < 'jam.1'`"
test 13472 -eq "$Wc_c" ||
echo 'jam.1: original size 13472, current size' "$Wc_c"
fi
# ============= Build.com ==============
if test -f 'Build.com' -a X"$1" != X"-c"; then
echo 'x - skipping Build.com (File already exists)'
else
echo 'x - extracting Build.com (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Build.com' &&
X! Bootstrap build script for Jam
X! On OPENVMS you need the next line
X! $ cc := cc/stand=vaxc
X$ cc compile.c
X$ cc expand.c
X$ cc execvms.c
X$ cc filevms.c
X$ cc hash.c
X$ cc headers.c
X$ cc lists.c
X$ cc make.c
X$ cc newstr.c
X$ cc option.c
X$ cc parse.c
X$ cc regexp.c
X$ cc rules.c
X$ cc scan.c
X$ cc search.c
X$ cc timestamp.c
X$ cc variable.c
X$ cc jam.c
X$ cc jamgram.c
X$ link/exe=jam.exe compile.obj, execvms.obj, expand.obj, filevms.obj, -
X hash.obj, headers.obj, lists.obj, make.obj, newstr.obj, option.obj, -
X parse.obj, regexp.obj, rules.obj, scan.obj, search.obj, timestamp.obj, -
X variable.obj, jam.obj, jamgram.obj
SHAR_EOF
chmod 0444 Build.com ||
echo 'restore of Build.com failed'
Wc_c="`wc -c < 'Build.com'`"
test 619 -eq "$Wc_c" ||
echo 'Build.com: original size 619, current size' "$Wc_c"
fi
# ============= Examples ==============
if test -f 'Examples' -a X"$1" != X"-c"; then
echo 'x - skipping Examples (File already exists)'
else
echo 'x - extracting Examples (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Examples' &&
XJamfile examples.
X
X(1) A no-frills compile from sources:
X
X MAIN program : source1.c source2.c grammar.y ;
X
X(2) To build xterm (on SunOS):
X
X X11R4 = /usr/local/X11R4 ;
X HDRS = $(X11R4)/include ;
X LINKFLAGS = -L $(X11R4)/lib ;
X LINKLIBS = -lXaw -lXmu -lXt -lX11 -loldX -lcurses -ltermcap ;
X BINDIR = $(X11R4)/bin ;
X MANDIR = $(X11R4)/man ;
X
X MAIN xterm : TekPrsTbl.c Tekproc.c VTPrsTbl.c button.c charproc.c
X cursor.c data.c input.c main.c menu.c misc.c screen.c scrollbar.c
X tabs.c util.c ;
X
X INSTALLBIN xterm ;
X INSTALLMAN xterm.man ;
X
X(3) If the variable settings above were put into a separate customization
X file JAMX, this file could be shrunk to:
X
X include /usr/local/lib/JAMX ;
X
X MAIN xterm : TekPrsTbl.c Tekproc.c VTPrsTbl.c button.c charproc.c
X cursor.c data.c input.c main.c menu.c misc.c screen.c scrollbar.c
X tabs.c util.c ;
X
X INSTALLBIN xterm ;
X INSTALLMAN xterm.man ;
X
X
X(4) To build from source in another directory:
X
X include /usr/local/lib/JAMX ;
X
X SEARCH_SOURCE = /usr/local/X11R4/src/mit/clients/xterm ;
X
X MAIN xterm : TekPrsTbl.c Tekproc.c VTPrsTbl.c button.c charproc.c
X cursor.c data.c input.c main.c menu.c misc.c screen.c scrollbar.c
X tabs.c util.c ;
X
X INSTALLBIN xterm ;
X INSTALLMAN xterm.man ;
X
X(5) Here's an example of defining your own CCUSER to handle source files
X other than .c and .o. Ideally, this would be put into a separate
X customization file to be included by the Jamfile.
X
X # CCUSER object : source ;
X #
X # The OBJECT rule, invoked by MAIN and LIBRARY to handle sources,
X # only knows about .c, .l, and .y. For all other suffixes, it
X # calls CCUSER with the desired object and source name. So this
X # version extends the known suffixes to include .s's.
X
X rule CCUSER
X {
X # switch on suffix
X
X switch $(>:D=:B=)
X {
X case .s : AS $(<) : $(>) ;
X case * : ECHO "unknown suffix on" $(>) ;
X }
X }
X
X # AS object : source ;
X #
X # assemble .s source
X
X rule AS # object : source ;
X {
X # Any rule that builds a target from some sources should
X # relate the sources and targets with DEPENDS.
X
X DEPENDS $(<) : $(>) ;
X }
X
X actions AS
X {
X # This is a shell script.
X
X as -o $(<) $(>)
X }
X
X LIBRARY data.a : fast.s ;
X
X(6) Finally, hooks for building a larger system. These rules should live
X in a file included by the Jamfile.
X
X # XXINCLUDE subdir - include a subdirectory's Jamfile
X #
X # This rule bridges the gap between system independent Jamfiles
X # and the system dependent directory naming (this version for
X # UNIX). This rule simply includes another Jamfile, first
X # figuring out where it is.
X #
X # This assumes BASE is set externally.
X
X rule XXINCLUDE
X {
X INCLUDE $(BASE)/$(<)/Jamfile ;
X }
X
X # XXSUBDIR subdir - set up variables for this subdirectory
X #
X # This rule is the invoked first in a Jamfile to arrange
X # variable settings for headers, source, etc. We want
X # objects and other intermediate files to live in the
X # source directory, hence the similar settings for
X # SEARCH_SOURCE and LOCATE_TARGET.
X
X rule XXSUBDIR
X {
X LIBRARY = $(BASE)/lib/lib$(<).a ;
X SEARCH_SOURCE = $(BASE)/$(<) ;
X LOCATE_TARGET = $(BASE)/$(<) ;
X HDRS = $(BASE)/hdr ;
X }
X
X The $(BASE)/Jamfile may look like:
X
X XXINCLUDE compile ;
X XXINCLUDE parser ;
X XXINCLUDE mailer ;
X
X While an individual $(BASE)/compile/Jamfile may be:
X
X XXSUBDIR compile ;
X
X LIBRARY $(LIBRARY) : com1.c com2.c comhash.c ;
X
X11/1/93
SHAR_EOF
chmod 0444 Examples ||
echo 'restore of Examples failed'
Wc_c="`wc -c < 'Examples'`"
test 3419 -eq "$Wc_c" ||
echo 'Examples: original size 3419, current size' "$Wc_c"
fi
# ============= Makefile ==============
if test -f 'Makefile' -a X"$1" != X"-c"; then
echo 'x - skipping Makefile (File already exists)'
else
echo 'x - extracting Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
X# Makefile for jam
X
X# Special flavors - uncomment appropriate lines
X
X# Solaris 2.0 seem not to have any identifying cpp symbol
X#CFLAGS = -Dsolaris
X
X# AIX needs -lbsd, and has no identifying cpp symbol
X#LINKLIBS = -lbsd
X#CFLAGS = -DAIX
X
Xinstall: jam0
X jam0 -f Jambase install
X
Xjam0:
X cc $(CFLAGS) *.c -o jam0 $(LINKLIBS)
SHAR_EOF
chmod 0444 Makefile ||
echo 'restore of Makefile failed'
Wc_c="`wc -c < 'Makefile'`"
test 320 -eq "$Wc_c" ||
echo 'Makefile: original size 320, current size' "$Wc_c"
fi
# ============= Porting ==============
if test -f 'Porting' -a X"$1" != X"-c"; then
echo 'x - skipping Porting (File already exists)'
else
echo 'x - extracting Porting (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Porting' &&
XNotes on porting Jam
X
X1) Working out system dependencies in the Jam code.
X
X Jam's OS footprint is fairly small. For OS independent work Jam
X liberally uses standard libc functions like stdio, malloc, and
X string. The OS dependent interfaces are:
X
X From filesys.h:
X
X file_parse() - split a file name into dir/base/suffix/member
X file_build() - build a filename given dir/base/suffix/member
X file_dirscan() - scan a directory for files
X file_archscan() - scan an archive for files
X file_time() - get the timestamp of a file, if not already
X done by file_dirscan().
X
X From execcmd.h:
X
X execcmd() - execute a shell script
X
X Porting to another UNIX platform rarely involves more than fixing
X file_dirscan() or, more likely, file_archscan() to work on the rogue
X directory or archive structure. Porting to another OS, such as NT,
X DOS, etc, probably require a completely new implementation of
X fileunix.c and execunix.c.
X
X2) Defining OTHERSYMS in jam.h
X
X So that the Jambase and Jamfile know their host, Jam defines $(OS)
X to be something useful for each platform. Make sure that there is
X code in jam.h to generate a useful value for $(OS), and key it off
X the platform specific C-preprocessor symbol. If the C-preprocessor
X doesn't itself defines such a symbol, add a define to the Makefile.
X
X3) Working out system dependencies in the Jambase
X
X With the value of $(OS) available, the Jambase can be extended to
X support special variables or rules for new platforms. For ports to
X non UNIX platforms, it might pay to make a new Jambase.xxx
X altogether, a la Jambase.VMS.
X
X4) Yacc troubles
X
X The generated files jamgram.y and jamgramtab.h are distributed for
X places without a sufficiently working sh/awk/sed to run yyacc.
X
X The generated files jamgram.h and jamgram.c are distributed for the
X poor souls without yacc.
X
X5) Known problematic systems:
X
X - Solaris 2.0 sucks (still). Jam only works with the SUNWspro cc,
X because the ucb one has bogus headers for dirent.
X
X - Pyramid has no malloc.h, memory.h
X
X - Encore has no stdlib.h
X
X - Bull DPX has sys/file.h problems
X
X6) Send the results back.
X
X If you do porting work, the result can be integrated into future
X releases if you send it back to the author's adress in the README.
SHAR_EOF
chmod 0444 Porting ||
echo 'restore of Porting failed'
Wc_c="`wc -c < 'Porting'`"
test 2355 -eq "$Wc_c" ||
echo 'Porting: original size 2355, current size' "$Wc_c"
fi
# ============= Jambase ==============
if test -f 'Jambase' -a X"$1" != X"-c"; then
echo 'x - skipping Jambase (File already exists)'
else
echo 'x - extracting Jambase (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Jambase' &&
X#
X# /+\
X# +\ Copyright 1993 Christopher Seiwald.
X# \+/
X#
X
X#
X# JAMBASE - jam ruleset providing make(1)-like functionality
X#
X
X# Rules defined by this file:
X#
X# MAIN image : source ; link executable from compiled sources
X# LIBS image : libraries ; bag libraries onto a MAIN
X# UNDEFINES image : symbols ; save undef's for linking
X# SETUID image ; mark an executable SETUID
X# LIBRARY lib : source ; archive library from compiled sources
X# OBJECT objname : source ; compile object from source
X# HDRRULE source : headers ; handle #includes
X# CC obj.o : source.c ; .c -> .o
X# LEX source.c : source.l ; .l -> .c
X# YACC source.c : source.y ; .y -> .c
X# YYACC source.y : source.yy ; .yy -> .y
X# BULK dir : files ; populate directory with many files
X# FILE dest : source ; copy file
X# SHELL exe : source ; install a shell executable
X# RMTEMPS target : sources ; remove temp sources after target made
X# INSTALLBIN sources ; install binaries
X# INSTALLLIB sources ; install files
X# INSTALLMAN source ; install man pages
X#
X
X# Brief review of the jam language:
X#
X# Statements:
X# rule RULE - statements to process a rule
X# actions RULE - system commands to carry out target update
X#
X# Modifiers on actions:
X# together - multiple instances of same rule on target get executed
X# once with their sources ($(>)) concatenated
X# updated - refers to updated sources ($(>)) only
X# ignore - ignore return status of command
X# quietly - don't trace its execution unless verbose
X# piecemeal - iterate command each time with a small subset of $(>)
X#
X# Special rules:
X# DEPENDS - builds the dependency graph
X# ECHO - blurt out targets on stdout
X# INCLUDES - marks sources as headers for target (a codependency)
X# NOCARE - don't panic if the target can't be built
X# NOTIME - ignore the timestamp of the target (it's not a file)
X# TEMPORARY - target need not be present if sources haven't changed
X#
X# Special variables set by jam:
X# $(<) - targets of a rule (to the left of the :)
X# $(>) - sources of a rule (to the right of the :)
X# $(UNIX) - true on UNIX
X# $(VMS) - true on VMS
X# $(OS) - name of OS - varies wildly
X#
X# Special variables used by jam:
X# SEARCH - where to find something (used during binding and actions)
X# LOCATE - where to plop something not found with SEARCH
X# HDRRULE - rule to call to handle include files
X# HDRSCAN - egrep regex to extract include files
X#
X# Special targets:
X# all - default if none given on command line
X
X# Initialize variables
X#
X# "default =" - set only if unset
X
XAR default = ar ru ;
XBINDIR default = /usr/local/bin ;
XCC default = cc ;
XCCFLAGS default = ;
XCHMOD default = chmod ;
XEXEMODE default = 711 ;
XFILEMODE default = 644 ;
XHDRS default = ;
XLEX default = lex ;
XLIBDIR default = /usr/local/lib ;
XLINK default = $(CC) ;
XLINKFLAGS default = $(CCFLAGS) ;
XLINKLIBS default = ;
XMANDIR default = /usr/local/man ;
XMV default = mv -f ;
XOPTIM default = -O ;
XRANLIB default = ranlib ;
XRM default = rm -f ;
XSHELLHEADER default = "#!/bin/sh" ;
XSHELLMODE default = 755 ;
XSTDHDRS default = /usr/include ;
XUNDEFFLAG default = "-u _" ;
XYACC default = yacc -d ;
XJAMFILE default = Jamfile ;
X
XHDRPATTERN = "^#[ ]*include[ ]*[<\"](.*)[\">].*$" ;
X
X#
X# OS specific variable settings
X#
X
Xswitch $(OS)
X{
Xcase AIX : LINKLIBS = -lbsd ;
Xcase DGUX : RANLIB = ;
Xcase IRIX : RANLIB = ;
Xcase HPUX : RANLIB = ;
Xcase PTX : RANLIB = ;
Xcase SOLARIS : RANLIB = ;
X}
X
X#
X# Base dependencies - first for "bootstrap" kinds of rules
X#
X
XDEPENDS all : first shell files lib exe ;
XNOTIME all first shell files lib exe ;
X
X#
X# The rules
X#
X
Xrule MAIN
X{
X # make compiled sources a dependency of target
X
X DEPENDS exe : $(<) ;
X DEPENDS $(<) : $(>:S=.o) ;
X LOCATE on $(<) = $(LOCATE_TARGET) ;
X
X LINK $(<) : $(>:S=.o) ;
X
X # each object gets compiled from sources
X
X for i in $(>)
X {
X OBJECT $(i:S=.o) : $(i) ;
X }
X}
X
Xactions LINK
X{
X if $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
X then chmod $(EXEMODE) $(<)
X else $(RM) $(<); exit 1
X fi
X}
X
Xrule LIBS
X{
X # make library dependencies of target
X # set NEEDLIBS variable used by 'actions MAIN'
X
X DEPENDS $(<) : $(>) ;
X NEEDLIBS on $(<) = $(>) ;
X}
X
Xrule UNDEFINES
X{
X UNDEFS on $(<) = $(UNDEFFLAG)$(>) ;
X}
X
Xrule SETUID
X{
X EXEMODE on $(<) = 4711 ;
X}
X
Xrule LIBRARY
X{
X # library depends on its member objects
X
X DEPENDS lib : $(<) ;
X DEPENDS $(<) : $(<)($(>:BS=.o)) ;
X
X # We wish we could locate the library and it's contents,
X # but the reference to $(NEEDLIBS) in MAIN's actions
X # get the unbound names. Only $(<) and $(>) refer to
X # bound file name in rule actions. Sigh.
X #
X # LOCATE on $(<) $(<)($(>:BS=.o)) = $(LOCATE_TARGET) ;
X
X # each archive member object depends on real object
X # each real object gets compiled from sources
X
X for i in $(>)
X {
X DEPENDS $(<)($(i:BS=.o)) : $(i:S=.o) ;
X OBJECT $(i:S=.o) : $(i) ;
X }
X
X # must call separate ARCHIVE rule so that 'updated' modifier
X # on 'actions' refers to updated .o's.
X # delete objects after archive is made
X
X ARCHIVE $(<) : $(>:S=.o) ;
X RMTEMPS $(<) : $(>:S=.o) ;
X
X if $(RANLIB) { RANLIB $(<) ; }
X}
X
Xactions updated together piecemeal ARCHIVE
X{
X $(AR) $(<) $(>)
X}
X
Xactions together RANLIB
X{
X $(RANLIB) $(<)
X}
X
Xrule OBJECT
X{
X # locate object and search for source, if wanted
X
X LOCATE on $(<) = $(LOCATE_TARGET) ;
X SEARCH on $(>) = $(SEARCH_SOURCE) ;
X
X # Save HDRS for -I$(HDRS) on compile.
X # We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers
X # in the .c file's directory, but generated .c files (from
X # yacc, lex, etc) are located in $(LOCATE_TARGET), possibly
X # different from $(SEARCH_SOURCE).
X
X HDRS on $(<) = $(HDRS) $(SEARCH_SOURCE) ;
X
X # handle #includes for source: Jam scans for headers with
X # the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE)
X # with the scanned file as the target and the found headers
X # as the sources. HDRSEARCH is just grist for HDRRULE.
X
X HDRRULE on $(>) = HDRRULE ;
X HDRSCAN on $(>) = $(HDRPATTERN) ;
X HDRSEARCH on $(>) = $(HDRS) $(STDHDRS) $(SEARCH_SOURCE) ;
X
X # if source is not .c, generate .c with specific rule
X
X switch $(>:S)
X {
X case .c : CC $(<) : $(>) ;
X case .l : CC $(<) : $(<:S=.c) ;
X LEX $(<:S=.c) : $(>) ;
X case .y : CC $(<) : $(<:S=.c) ;
X YACC $(<:S=.c) : $(>) ;
X case .yy : CC $(<) : $(<:S=.c) ;
X YACC $(<:S=.c) : $(<:S=.y) ;
X YYACC $(<:S=.y) : $(>) ;
X case * : CCUSER $(<) : $(>) ;
X }
X}
X
Xrule HDRRULE
X{
X # HDRRULE source : headers ;
X
X # N.B. This rule is called during binding, potentially after
X # the fate of many targets has been determined, and must be
X # used with caution: don't add dependencies to unrelated
X # targets, and don't set variables on $(<).
X
X # Tell Jam that anything depending on $(<) also depends on $(>),
X # set SEARCH so Jam can find the headers, but then say we don't
X # care if we can't actually find the headers (they may have been
X # within ifdefs),
X
X INCLUDES $(<) : $(>) ;
X SEARCH on $(>) = $(HDRSEARCH) ;
X NOCARE $(>) ;
X
X # Propagate on $(<) to $(>)
X
X HDRSEARCH on $(>) = $(HDRSEARCH) ;
X HDRSCAN on $(>) = $(HDRSCAN) ;
X HDRRULE on $(>) = $(HDRRULE) ;
X}
X
Xrule CC
X{
X DEPENDS $(<) : $(>) ;
X RELOCATE $(<) ;
X}
X
Xactions CC
X{
X $(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) $(>)
X}
X
Xactions quietly ignore RELOCATE
X{
X [ $(<) != $(<:D=) ] && $(MV) $(<:D=) $(<)
X}
X
Xrule LEX
X{
X DEPENDS $(<) : $(>) ;
X LOCATE on $(<) = $(LOCATE_TARGET) ;
X}
X
Xactions LEX
X{
X $(LEX) $(>) && $(MV) lex.yy.c $(<)
X}
X
Xrule YACC
X{
X h = $(<:BS=.h) ;
X
X DEPENDS $(<) $(h) : $(>) ;
X YACC1 $(<) $(h) : $(>) ;
X # make sure someone includes $(h) else it will be
X # a deadly independent target
X INCLUDES $(<) : $(h) ;
X LOCATE on $(<) $(h) = $(LOCATE_TARGET) ;
X}
X
Xactions YACC1
X{
X $(YACC) $(>) &&
X {
X $(MV) y.tab.c $(<[1])
X $(MV) y.tab.h $(<[2])
X }
X}
X
Xrule YYACC
X{
X DEPENDS $(<) $(<:B)tab.h : $(>) ;
X YYACC1 $(<) $(<:B)tab.h : $(>) ;
X LOCATE on $(<) $(<:B)tab.h = $(LOCATE_TARGET) ;
X}
X
Xactions YYACC1
X{
X sh yyacc $(>) $(<)
X}
X
Xrule BULK
X{
X for i in $(>)
X {
X FILE $(i:D=$(<)) : $(i) ;
X }
X}
X
Xrule FILE
X{
X DEPENDS files : $(<) ;
X DEPENDS $(<) : $(>) ;
X SEARCH on $(>) = $(SEARCH_SOURCE) ;
X}
X
Xactions FILE
X{
X cp $(>) $(<) &&
X chmod $(FILEMODE) $(<)
X}
X
Xrule SHELL
X{
X DEPENDS shell : $(<) ;
X DEPENDS $(<) : $(>) ;
X SEARCH on $(>) = $(SEARCH_SOURCE) ;
X}
X
Xactions SHELL
X{
X (
X echo "$(SHELLHEADER)"
X sed '/^: /d;/^##/d' $(>)
X ) > $(<)
X chmod $(SHELLMODE) $(<)
X}
X
Xrule RMTEMPS
X{
X TEMPORARY $(>) ;
X}
X
Xactions quietly updated piecemeal RMTEMPS
X{
X $(RM) $(>)
X}
X
Xrule INSTALLBIN
X{
X for i in $(<)
X {
X INSTALL $(i:D=$(BINDIR)) : $(i) ;
X INSTALLMODE on $(i:D=$(BINDIR)) = $(EXEMODE) ;
X }
X}
X
Xrule INSTALLLIB
X{
X for i in $(<)
X {
X INSTALL $(i:D=$(LIBDIR)) : $(i) ;
X INSTALLMODE on $(i:D=$(LIBDIR)) = $(FILEMODE) ;
X }
X}
X
Xrule INSTALLMAN
X{
X # Really this just strips the . from the suffix
X
X for i in $(<)
X {
X switch $(i:S)
X {
X case .1 : S = 1 ; case .2 : S = 2 ; case .3 : S = 3 ;
X case .4 : S = 4 ; case .5 : S = 5 ; case .6 : S = 6 ;
X case .7 : S = 7 ; case .8 : S = 8 ; case .l : S = l ;
X case .n : S = n ; case .man : S = 1 ;
X }
X
X D = $(i:D=$(MANDIR)/man$(S):S=.$(S)) ;
X
X INSTALL $(D) : $(i) ;
X INSTALLMODE on $(D) = $(FILEMODE) ;
X }
X}
X
Xrule INSTALL
X{
X DEPENDS install : $(<) ;
X DEPENDS $(<) : $(>) ;
X SEARCH on $(>) = $(SEARCH_SOURCE) ;
X}
X
Xactions INSTALL
X{
X [ -d "$(<:D)" ] || mkdir $(<:D)
X cp $(>) $(<) &&
X chmod $(INSTALLMODE) $(<)
X}
X
X#
X# Now include the Jamfile.
X#
X
Xinclude $(JAMFILE) ;
SHAR_EOF
chmod 0444 Jambase ||
echo 'restore of Jambase failed'
Wc_c="`wc -c < 'Jambase'`"
test 9400 -eq "$Wc_c" ||
echo 'Jambase: original size 9400, current size' "$Wc_c"
fi
# ============= Jambase.VMS ==============
if test -f 'Jambase.VMS' -a X"$1" != X"-c"; then
echo 'x - skipping Jambase.VMS (File already exists)'
else
echo 'x - extracting Jambase.VMS (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Jambase.VMS' &&
X#
X# /+\
X# +\ Copyright 1993 Christopher Seiwald.
X# \+/
X#
X
X#
X# JAMBASE - jam ruleset providing make(1)-like functionality
X#
X
X# Rules defined by this file:
X#
X# MAIN image : source ; link executable from compiled sources
X# LIBS image : libraries ; bag libraries onto a MAIN
X# UNDEFINES image : symbols ; save undef's for linking
X# SETUID image ; mark an executable SETUID
X# LIBRARY lib : source ; archive library from compiled sources
X# OBJECT objname : source ; compile object from source
X# HDRRULE source : headers ; handle #includes
X# CC obj.obj : source.c ; .c -> .o
X# LEX source.c : source.l ; .l -> .c
X# YACC source.c : source.y ; .y -> .c
X# YYACC source.y : source.yy ; .yy -> .y
X# BULK dir : files ; populate directory with many files
X# FILE dest : source ; copy file
X# SHELL exe : source ; install a shell executable
X# RMTEMPS target : sources ; remove temp sources after target made
X# INSTALLBIN sources ; install binaries
X# INSTALLLIB sources ; install files
X# INSTALLMAN source ; install man pages
X#
X
X# Brief review of the jam language:
X#
X# Statements:
X# rule RULE - statements to process a rule
X# actions RULE - system commands to carry out target update
X#
X# Modifiers on actions:
X# together - multiple instances of same rule on target get executed
X# once with their sources ($(>)) concatenated
X# updated - refers to updated sources ($(>)) only
X# ignore - ignore return status of command
X# quietly - don't trace its execution unless verbose
X# piecemeal - iterate command each time with a small subset of $(>)
X#
X# Special rules:
X# DEPENDS - builds the dependency graph
X# ECHO - blurt out targets on stdout
X# INCLUDES - marks sources as headers for target (a codependency)
X# NOCARE - don't panic if the target can't be built
X# NOTIME - ignore the timestamp of the target (it's not a file)
X# TEMPORARY - target need not be present if sources haven't changed
X#
X# Special variables set by jam:
X# $(<) - targets of a rule (to the left of the :)
X# $(>) - sources of a rule (to the right of the :)
X# $(UNIX) - true on UNIX
X# $(VMS) - true on VMS
X# $(OS) - name of OS - varies wildly
X#
X# Special variables used by jam:
X# SEARCH - where to find something (used during binding and actions)
X# LOCATE - where to plop something not found with SEARCH
X# HDRRULE - rule to call to handle include files
X# HDRSCAN - egrep regex to extract include files
X#
X# Special targets:
X# all - default if none given on command line
X
X# Initialize variables
X
XAS default = as ;
XBINDIR default = sys$system ;
XCC default = cc ;
XCCFLAGS default = ;
XEXEMODE default = (w:e) ;
XFILEMODE default = (w:r) ;
XHDRS default = ;
XLEX default = lex ;
XLIBDIR default = sys$library ;
XLINK default = link ;
XLINKFLAGS default = ;
XLINKLIBS default = ;
XMV default = rename ;
XOPTIM default = ;
XSHELLMODE default = (w:er) ;
XSTDHDRS default = "" decc$library_include ;
XYACC default = yacc -d ;
XJAMFILE default = Jamfile ;
X
XHDRPATTERN = "^#[ ]*include[ ]*[<\"](.*)[\">].*$" ;
X
X#
X# OS specific variable settings
X#
X
Xswitch $(OS)
X{
Xcase OPENVMS : CCFLAGS default = /stand=vaxc ;
Xcase VMS : LINKLIBS default = sys$library:vaxcrtl.olb/lib ;
X}
X
X#
X# Base dependencies - first for "bootstrap" kinds of rules
X#
X
XDEPENDS all : first shell files lib exe ;
XNOTIME all first shell files lib exe ;
X
X#
X# The rules
X#
X
Xrule MAIN
X{
X # make compiled sources a dependency of target
X
X DEPENDS exe : $(<:S=.exe) ;
X DEPENDS $(<:S=.exe) : $(>:S=.obj) ;
X LOCATE on $(<) = $(LOCATE_TARGET) ;
X
X LINK $(<:S=.exe) : $(>:S=.obj) ;
X
X # each object gets compiled from sources
X
X for i in $(>)
X {
X OBJECT $(i:S=.obj) : $(i) ;
X }
X}
X
Xactions LINK
X{
X $(LINK)/exe=$(<) $(LINKFLAGS) $(>[1]) ,$(>[2-]) ,$(NEEDLIBS)/lib ,$(LINKLIBS)
X set file/prot=$(EXEMODE) $(<)
X}
X
Xrule LIBS
X{
X # make library dependencies of target
X # set NEEDLIBS variable used by 'actions MAIN'
X
X DEPENDS $(<:S=.exe) : $(>) ;
X NEEDLIBS on $(<:S=.exe) = $(>) ;
X}
X
Xrule UNDEFINES
X{
X # don't know this one
X}
X
Xrule SETUID
X{
X ECHO "Can't set" $(<) "setuid on VMS." ;
X}
X
Xrule LIBRARY
X{
X # library depends on its member objects
X
X DEPENDS lib : $(<) ;
X DEPENDS $(<) : $(<)($(>:BS=.obj)) ;
X
X # We wish we could locate the library and it's contents,
X # but the reference to $(NEEDLIBS) in MAIN's actions
X # get the unbound names. Only $(<) and $(>) refer to
X # bound file name in rule actions. Sigh.
X #
X # LOCATE on $(<) $(<)($(>:BS=.obj)) = $(LOCATE_TARGET) ;
X
X # each archive member object depends on real object
X # each real object gets compiled from sources
X
X for i in $(>)
X {
X DEPENDS $(<)($(i:BS=.obj)) : $(i:S=.obj) ;
X OBJECT $(i:S=.obj) : $(i) ;
X }
X
X # must call separate ARCHIVE rule so that 'updated' modifier
X # on 'actions' refers to updated .obj's.
X
X LIBCREATE $(<) ;
X ARCHIVE $(<) : $(>:S=.obj) ;
X RMTEMPS $(<) : $(>:S=.obj) ;
X}
X
Xactions together quietly LIBCREATE
X{
X if f$search("$(<)") .eqs. "" then lib/create $(<)
X}
X
Xactions updated together piecemeal ARCHIVE
X{
X lib/replace $(<) $(>[1]) ,$(>[2-])
X}
X
Xrule OBJECT
X{
X # locate object and search for source, if wanted
X
X LOCATE on $(<) = $(LOCATE_TARGET) ;
X SEARCH on $(>) = $(SEARCH_SOURCE) ;
X
X # Save HDRS for -I$(HDRS) on compile.
X # We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers
X # in the .c file's directory, but generated .c files (from
X # yacc, lex, etc) are located in $(LOCATE_TARGET), possibly
X # different from $(SEARCH_SOURCE).
X
X HDRS on $(<) = $(HDRS) $(SEARCH_SOURCE) ;
X
X # handle #includes for source: Jam scans for headers with
X # the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE)
X # with the scanned file as the target and the found headers
X # as the sources. HDRSEARCH is just grist for HDRRULE.
X
X HDRRULE on $(>) = HDRRULE ;
X HDRSCAN on $(>) = $(HDRPATTERN) ;
X HDRSEARCH on $(>) = $(HDRS) $(STDHDRS) $(SEARCH_SOURCE) ;
X
X # if source is not .c, generate .c with specific rule
X
X switch $(>:S)
X {
X case .c : CC $(<) : $(>) ;
X case .l : CC $(<) : $(<:S=.c) ;
X LEX $(<:S=.c) : $(>) ;
X case .y : CC $(<) : $(<:S=.c) ;
X YACC $(<:S=.c) : $(>) ;
X case .yy : CC $(<) : $(<:S=.c) ;
X YACC $(<:S=.c) : $(<:S=.y) ;
X YYACC $(<:S=.y) : $(>) ;
X case * : CCUSER $(<) : $(>) ;
X }
X}
X
Xrule CC
X{
X if $(HDRS[1])
X {
X SLASHINC on $(<) = "/inc=(" $(HDRS[1]) ,$(HDRS[2-]) ")" ;
X }
X DEPENDS $(<) : $(>) ;
X}
X
Xactions CC
X{
X cc/obj=$(<) $(CCFLAGS) $(OPTIM) $(SLASHINC) $(>)
X}
X
Xrule HDRRULE
X{
X # HDRRULE source : headers ;
X
X # N.B. This rule is called during binding, potentially after
X # the fate of many targets has been determined, and must be
X # used with caution: don't add dependencies to unrelated
X # targets, and don't set variables on $(<).
X
X # Tell Jam that anything depending on $(<) also depends on $(>),
X # set SEARCH so Jam can find the headers, but then say we don't
X # care if we can't actually find the headers (they may have been
X # within ifdefs),
X
X INCLUDES $(<) : $(>) ;
X SEARCH on $(>) = $(HDRSEARCH) ;
X NOCARE $(>) ;
X
X # Propagate on $(<) to $(>)
X
X HDRSEARCH on $(>) = $(HDRSEARCH) ;
X HDRSCAN on $(>) = $(HDRSCAN) ;
X HDRRULE on $(>) = $(HDRRULE) ;
X}
X
Xrule LEX
X{
X DEPENDS $(<) : $(>) ;
X LOCATE on $(<) = $(LOCATE_TARGET) ;
X}
X
Xactions LEX
X{
X $(LEX) $(>)
X $(MV) lex.yy.c $(<)
X}
X
Xrule YACC
X{
X h = $(<:BS=.h) ;
X
X # no yacc on VMS (yet)
X # DEPENDS $(<) $(h) : $(>) ;
X # YACC1 $(<) $(h) : $(>) ;
X # make sure someone includes $(h) else it will be
X # a deadly independent target
X INCLUDES $(<) : $(h) ;
X LOCATE on $(<) $(h) = $(LOCATE_TARGET) ;
X}
X
Xactions YACC1
X{
X $(YACC) $(>)
X $(MV) y.tab.c $(<[1])
X $(MV) y.tab.h $(<[2])
X}
X
Xrule YYACC
X{
X # no yyacc on VMS (yet)
X # DEPENDS $(<) $(<:B)tab.h : $(>) ;
X # YYACC1 $(<) $(<:B)tab.h : $(>) ;
X LOCATE on $(<) $(<:B)tab.h = $(LOCATE_TARGET) ;
X}
X
Xactions YYACC1
X{
X ! sh yyacc $(>)
X}
X
Xrule BULK
X{
X for i in $(>)
X {
X FILE $(i:D=$(<)) : $(i) ;
X }
X}
X
Xrule FILE
X{
X DEPENDS files : $(<) ;
X DEPENDS $(<) : $(>) ;
X SEARCH on $(>) = $(SEARCH_SOURCE) ;
X}
X
Xactions FILE
X{
X copy $(>) $(<)
X set file/prot=$(FILEMODE) $(<)
X}
X
Xrule SHELL
X{
X DEPENDS shell : $(<) ;
X DEPENDS $(<) : $(>) ;
X SEARCH on $(>) = $(SEARCH_SOURCE) ;
X}
X
Xactions SHELL
X{
X copy $(>) $(<)
X set file/prot=$(SHELLMODE) $(<)
X}
X
Xrule RMTEMPS
X{
X TEMPORARY $(>) ;
X}
X
Xactions quietly updated piecemeal RMTEMPS
X{
X delete $(>[1]);* ,$(>[2-]);*
X}
X
Xrule INSTALLBIN
X{
X for i in $(<)
X {
X INSTALL $(i:D=$(BINDIR)) : $(i) ;
X INSTALLMODE on $(i:D=$(BINDIR)) = $(EXEMODE) ;
X }
X}
X
Xrule INSTALLLIB
X{
X for i in $(<)
X {
X INSTALL $(i:D=$(LIBDIR)) : $(i) ;
X INSTALLMODE on $(i:D=$(LIBDIR)) = $(FILEMODE) ;
X }
X}
X
Xrule INSTALLMAN
X{
X ECHO "can't install manual pages" $(<) "on VMS." ;
X}
X
Xrule INSTALL
X{
X DEPENDS install : $(<) ;
X DEPENDS $(<) : $(>) ;
X SEARCH on $(>) = $(SEARCH_SOURCE) ;
X}
X
Xactions INSTALL
X{
X copy $(>) $(<)
X set file/prot=$(INSTALLMODE) $(<)
X}
X
X#
X# Now include the Jamfile.
X#
X
Xinclude $(JAMFILE) ;
SHAR_EOF
chmod 0444 Jambase.VMS ||
echo 'restore of Jambase.VMS failed'
Wc_c="`wc -c < 'Jambase.VMS'`"
test 8788 -eq "$Wc_c" ||
echo 'Jambase.VMS: original size 8788, current size' "$Wc_c"
fi
# ============= Jamfile ==============
if test -f 'Jamfile' -a X"$1" != X"-c"; then
echo 'x - skipping Jamfile (File already exists)'
else
echo 'x - extracting Jamfile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Jamfile' &&
X#
X# Jamfile for Jam
X#
X
Xif $(VMS)
X{
X JAMLIB = libjam.olb ;
X OSFILES = execvms.c filevms.c ;
X}
X
Xif $(UNIX)
X{
X JAMLIB = libjam.a ;
X OSFILES = execunix.c fileunix.c ;
X
X LIBDIR = /usr/local/lib/jam ;
X
X INSTALLMAN jam.1 Jambase.5 ;
X INSTALLBIN jam ;
X
X INSTALLLIB Jambase ;
X
X}
X
XMAIN jam : jam.c ;
XLIBS jam : $(JAMLIB) ;
X
XLIBRARY $(JAMLIB) : compile.c expand.c hash.c lists.c make.c
X newstr.c option.c parse.c rules.c scan.c search.c
X timestamp.c variable.c jamgram.yy headers.c regexp.c
X $(OSFILES) ;
X
SHAR_EOF
chmod 0444 Jamfile ||
echo 'restore of Jamfile failed'
Wc_c="`wc -c < 'Jamfile'`"
test 532 -eq "$Wc_c" ||
echo 'Jamfile: original size 532, current size' "$Wc_c"
fi
true || echo 'restore of compile.c failed'
echo End of part 1, continue with part 2
exit 0