#
# /+\
# +\ Copyright 1993, 1995 Christopher Seiwald.
# \+/
#
# This file is part of Jam - see jam.c for Copyright information.
#
#
# JAMBASE - jam 2.1 ruleset providing make(1)-like functionality
#
# Supports UNIX, NT, and VMS.
#
# 12/27/93 (seiwald) - purturb library sources with SOURCE_GRIST
# 04/18/94 (seiwald) - use 'default =' when setting OS specific vars
# 04/21/94 (seiwald) - do RmTemps together
# 05/05/94 (seiwald) - all supported C compilers support -o: relegate
# RELOCATE as an option; set Ranlib to "" to disable it
# 06/01/94 (seiwald) - new 'actions existing' to do existing sources
# 08/25/94 (seiwald) - new ObjectCcFlags rule to append to per-target CCFLAGS
# 08/29/94 (seiwald) - new ObjectHdrs rule to append to per-target HDRS
# 09/19/94 (seiwald) - LinkLibraries and Undefs now append
# - Rule names downshifted.
# 10/06/94 (seiwald) - Dumb yyacc stuff moved into Jamfile.
# 10/14/94 (seiwald) - (Crude) support for .s, .C, .cc, .cpp, and .f files.
# 01/08/95 (seiwald) - Shell now handled with awk, not sed
# 01/09/95 (seiwald) - Install* now take dest directory as target
# 01/10/95 (seiwald) - All entries sorted.
# 01/10/95 (seiwald) - NT support moved in, with LauraW's help.
# 01/10/95 (seiwald) - VMS support moved in.
# 02/06/95 (seiwald) - ObjectC++Flags and SubDirC++Flags added.
# 02/07/95 (seiwald) - Iron out when HDRSEARCH uses "" or SEARCH_SOURCE.
# 02/08/95 (seiwald) - SubDir works on VMS.
# 02/14/95 (seiwald) - MkDir and entourage.
# 04/30/95 (seiwald) - Use install -c flag so that it copies, not moves.
# 07/10/95 (taylor) - Support for Microsoft C++.
# 11/21/96 (peterk) - Support for BeOS
# Special targets defined in this file:
#
# all - parent of first, shell, files, lib, exe
# first - first dependent of 'all', for potential initialization
# shell - parent of all Shell targets
# files - parent of all File targets
# lib - parent of all Library targets
# exe - parent of all Main targets
# dirs - parent of all MkDir targets
# clean - removes all Shell, File, Library, and Main targets
# uninstall - removes all Install targets
#
# Rules defined by this file:
#
# as obj.o : source.s ; .s -> .o
# Bulk dir : files ; populate directory with many files
# Cc obj.o : source.c ; .c -> .o
# C++ obj.o : source.cc ; .cc -> .o
# Clean clean : sources ; remove sources with 'jam clean'
# File dest : source ; copy file
# Fortran obj.o : source.f ; .f -> .o
# GenFile source.c : program args ; make custom file
# Hardlink target : source ; make link from source to target
# HdrRule source : headers ; handle #includes
# InstallInto dir : sources ; install any files
# InstallBin dir : sources ; install binaries
# InstallLib dir : sources ; install files
# InstallFile dir : sources ; install files
# InstallMan dir : sources ; install man pages
# InstallShell dir : sources ; install shell scripts
# Lex source.c : source.l ; .l -> .c
# Library lib : source ; archive library from compiled sources
# LibraryFromObjects lib : objects ; archive library from objects
# LinkLibraries images : libraries ; bag libraries onto Mains
# Main image : source ; link executable from compiled sources
# MainFromObjects image : objects ; link executable from objects
# MkDir dir ; make a directory, if not there
# Object object : source ; compile object from source
# ObjectCcFlags source : flags ; add compiler flags for object
# ObjectC++Flags source : flags ; add compiler flags for object
# ObjectHdrs source : dirs ; add include directories for object
# Objects sources ; compile sources
# RmTemps target : sources ; remove temp sources after target made
# Setuid images ; mark executables Setuid
# SubDir TOP d1 d2 ... ; start a subdirectory Jamfile
# SubDirCcFlags flags ; add compiler flags until next SubDir
# SubDirC++Flags flags ; add compiler flags until next SubDir
# SubDirHdrs dirs ; add include dirs until next SubDir
# SubInclude TOP d1 d2 ... ; include a subdirectory Jamfile
# Shell exe : source ; make a shell executable
# Undefines images : symbols ; save undef's for linking
# UserObject object : source ; handle unknown suffixes for Object
# Yacc source.c : source.y ; .y -> .c
#
# Utility rules that have no side effects:
#
# makeSubDir var : d1 d2 ... ; $(var) = path to root
# addDirName var : d1 d2 ... ; $(var) += path from root to dir
# makeDirName var : d1 d2 ... ; $(var) = path from root to dir
# makeGrist var : d1 d2 ... ; $(var) = grist form of dir
# makeGristedName var : value ; $(var) = $(value:G=$(SOURCE_GRIST))
# makeCommon var1 : var2 ; strip common initial elements
# makeRelPath var d1 : d2 ; $(var) = rel path from d1 to d2
# makeSuffixed var $(SUF) : f1 f2 ... ; $(var) = $(>) with suffixes
# makeString var : value ... ; $(var) = contatenated values
#
# Brief review of the jam language:
#
# Statements:
# rule RULE - statements to process a rule
# actions RULE - system commands to carry out target update
#
# Modifiers on actions:
# together - multiple instances of same rule on target get executed
# once with their sources ($(>)) concatenated
# updated - refers to updated sources ($(>)) only
# ignore - ignore return status of command
# quietly - don't trace its execution unless verbose
# piecemeal - iterate command each time with a small subset of $(>)
# existing - refers to currently existing sources ($(>)) only
#
# Special rules:
# ALWAYS - always build a target
# DEPENDS - builds the dependency graph
# ECHO - blurt out targets on stdout
# EXIT - blurt out targets and exit
# INCLUDES - marks sources as headers for target (a codependency)
# NOCARE - don't panic if the target can't be built
# NOUPDATE - create the target if needed but never update it
# NOTFILE - ignore the timestamp of the target (it's not a file)
# TEMPORARY - target need not be present if sources haven't changed
#
# Special variables set by jam:
# $(<) - targets of a rule (to the left of the :)
# $(>) - sources of a rule (to the right of the :)
# $(UNIX) - true on UNIX
# $(VMS) - true on VMS
# $(NT) - true on NT
# $(OS) - name of OS - varies wildly
# $(JAMVERSION) - version number (2.1)
#
# Special variables used by jam:
# SEARCH - where to find something (used during binding and actions)
# LOCATE - where to plop something not found with SEARCH
# HDRRULE - rule to call to handle include files
# HDRSCAN - egrep regex to extract include files
#
# Special targets:
# all - default if none given on command line
#
# Initialize variables
#
# "default =" - set only if unset
OSFULL = $(OS)$(OSPLAT)$(OSVER) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ;
#
# OS specific variable settings
#
switch $(OS)
{
case AIX : LINKLIBS default = -lbsd ;
case DGUX : RANLIB default = "" ; RELOCATE = true ;
case HPUX : RANLIB default = "" ;
INSTALL default = "" ;
case INTERIX : RANLIB default = "" ;
JAMSHELL default = "sh -c" ;
CC default = gcc ;
case IRIX : RANLIB default = "" ;
INSTALL default = "" ;
case MVS : RANLIB default = "" ;
case NEXT : AR default = libtool -o ;
RANLIB default = "" ;
case NCR : RANLIB default = "" ;
INSTALL default = "" ;
case PTX : RANLIB default = "" ;
case QNX : INSTALL default = "" ;
case SCO : RANLIB default = "" ;
INSTALL default = "" ; RELOCATE = true ;
case SINIX : RANLIB default = "" ;
case SOLARIS : RANLIB default = "" ;
INSTALL default = "install" ;
AR default = "/usr/ccs/bin/ar ru" ;
case UNIXWARE : RANLIB default = "" ; RELOCATE = true ;
}
#if $(OS) = SUNOS && $(TZ)
#{
# Echo Warning: you are running the SunOS jam on Solaris. ;
#}
if $(UNIX)
{
if $(OS) = QNX
{
AR default = wlib ;
CC default = cc ;
CCFLAGS default = -Q ; # quiet
C++ default = $(CC) ;
C++FLAGS default = -Q ; # quiet
LINK default = $(CC) ;
LINKFLAGS default = -Q ; # quiet
NOARSCAN default = true ;
RANLIB default = "" ;
}
else if $(OS) = BEOS && $(METROWERKS)
{
AR default = mwld -xml -o ;
BINDIR default = /boot/bin ;
CC default = mwcc ;
CCFLAGS default = -nosyspath ;
C++ default = $(CC) ;
C++FLAGS default = -nosyspath ;
FORTRAN default = "" ;
LIBDIR default = /boot/develop/libraries ;
LINK default = mwld ;
LINKFLAGS default = "" ;
LEX default = "" ;
MANDIR default = /boot/documentation/"Shell Tools"/HTML ;
NOARSCAN default = true ;
RANLIB default = "" ;
STDHDRS default = /boot/develop/headers/posix ;
YACC default = "" ;
YACCFLAGS default = "" ;
YACCFILES default = "" ;
}
else if $(OS) = BEOS
{
BINDIR default = /boot/bin ;
CC default = gcc ;
C++ default = $(CC) ;
FORTRAN default = "" ;
LIBDIR default = /boot/develop/libraries ;
LINK default = gcc ;
LINKLIBS default = -lnet ;
LEX default = "" ;
NOARSCAN default = true ;
RANLIB default = "" ;
STDHDRS default = /boot/develop/headers/posix ;
YACC default = "" ;
YACCFLAGS default = "" ;
YACCFILES default = "" ;
}
else if $(OS) = AMIGA
{
CC default = gcc ;
YACC default = bison ;
YACCFLAGS default = -d ;
YACCFILES default = y.tab ;
}
AR default = ar ru ;
AS default = as ;
AWK default = awk ;
ASFLAGS default = ;
BINDIR default = /usr/local/bin ;
C++ default = gcc ;
C++FLAGS default = ;
CC default = cc ;
CCFLAGS default = ;
CP default = cp ;
CHMOD default = chmod ;
DOT default = . ;
DOTDOT default = .. ;
EXEMODE default = 711 ;
FILEMODE default = 644 ;
FORTRAN default = f77 ;
FORTRANFLAGS default = ;
HDRS default = ;
INSTALL default = install -c ;
LEX default = lex ;
LIBDIR default = /usr/local/lib ;
LINK default = $(CC) ;
LINKFLAGS default = $(CCFLAGS) ;
LINKLIBS default = ;
LN default = ln ;
MANDIR default = /usr/local/man ;
MKDIR default = mkdir ;
MV default = mv -f ;
OPTIM default = -O ;
RANLIB default = ranlib ;
RCP default = rcp ;
RSH default = rsh ;
RM default = rm -f ;
SED default = sed ;
SHELLHEADER default = "#!/bin/sh" ;
SHELLMODE default = 755 ;
SLASH default = / ;
STDHDRS default = /usr/include ;
SUFLIB default = .a ;
SUFOBJ default = .o ;
SUFEXE default = "" ;
UNDEFFLAG default = "-u _" ;
YACC default = yacc ;
YACCFLAGS default = -d ;
YACCFILES default = y.tab ;
}
else if $(NT)
{
AWK default = awk ;
CHMOD default = chmod ;
CP default = copy ;
DOT default = . ;
DOTDOT default = .. ;
EXEMODE default = 711 ;
FILEMODE default = 644 ;
MKDIR default = mkdir ;
MV default = mv -f ;
OS = NT ; # replace Windows_NT
RCP default = rcp ;
RSH default = rsh ;
RM default = del /f/q ;
SED default = sed ;
SLASH default = \\ ;
SUFLIB default = .lib ;
SUFOBJ default = .obj ;
SUFEXE default = .exe ;
if $(BCCROOT)
{
ECHO "Compiler is Borland C++" ;
AR default = tlib ;
ARFLAGS default = /C /P64 ;
CC default = bcc32 ;
CCFLAGS default = -v -w- -DNT ;
C++ default = bcc32 ;
C++FLAGS default = -v -w- ;
LINK default = $(CC) ;
LINKFLAGS default = $(CCFLAGS) ;
STDLIBPATH default = $(BCCROOT)\\lib ;
STDHDRS default = $(BCCROOT)\\include ;
NOARSCAN default = true ;
}
else if $(MSVC)
{
ECHO "Compiler is Microsoft Visual C++ 16 bit" ;
AR default = lib /nologo ;
CC default = cl /nologo ;
CCFLAGS default = /D \"WIN\" ;
C++ default = $(CC) ;
C++FLAGS default = $(CCFLAGS) ;
LINK default = $(CC) ;
LINKFLAGS default = $(CCFLAGS) ;
LINKLIBS default =
#$(MSVC)\\lib\\advapi32.lib
#$(MSVC)\\lib\\libcmt.lib
$(MSVC)\\lib\\mlibce.lib
#$(MSVC)\\lib\\slibce.lib
$(MSVC)\\lib\\oldnames.lib
#$(MSVC)\\lib\\kernel32.lib
;
LINKLIBS default = ;
NOARSCAN default = true ;
OPTIM default = ;
STDHDRS default = $(MSVC)\\include ;
UNDEFFLAG default = "/u _" ;
}
else if $(MSVCNT)
{
ECHO "Compiler is Microsoft Visual C++" ;
AR default = lib ;
AS default = masm386 ;
CC default = cl /nologo ;
CCFLAGS default = ;
C++ default = $(CC) ;
C++FLAGS default = $(CCFLAGS) ;
LINK default = link ;
LINKFLAGS default = ;
LINKLIBS default = $(MSVCNT)\\lib\\advapi32.lib
$(MSVCNT)\\lib\\libc.lib
$(MSVCNT)\\lib\\oldnames.lib
$(MSVCNT)\\lib\\kernel32.lib ;
OPTIM default = ;
STDHDRS default = $(MSVCNT)\\include ;
UNDEFFLAG default = "/u _" ;
}
else
{
EXIT On NT, set BCCROOT, MSVCNT, or MSVC to the root of the
Borland or Microsoft directories. ;
}
}
else if $(OS2)
{
WATCOM default = $(watcom) ;
CP default = copy ;
DOT default = . ;
DOTDOT default = .. ;
MKDIR default = mkdir ;
MV default = move ;
RM default = del /f ;
SED default = sed ;
SLASH default = \\ ;
SUFLIB default = .lib ;
SUFOBJ default = .obj ;
SUFEXE default = .exe ;
if ! $(WATCOM)
{
EXIT On OS2, set WATCOM to the root of the Watcom directory. ;
}
ECHO "OS2 compiler is Watcom." ;
AR default = wlib ;
CC default = wcc386 ;
CCFLAGS default = /zq /DOS2 /I$(WATCOM)\\h ; # zq=quiet
C++ default = wpp386 ;
C++FLAGS default = $(CCFLAGS) ;
LINK default = wcl386 ;
LINKFLAGS default = /zq ; # zq=quiet
LINKLIBS default = ;
NOARSCAN default = true ;
OPTIM default = ;
STDHDRS default = $(WATCOM)\\h ;
UNDEFFLAG default = "/u _" ;
}
else if $(VMS)
{
AS default = as ;
CC default = cc ;
CCFLAGS default = ;
CP default = copy/replace ;
CRELIB default = true ;
DOT default = [] ;
DOTDOT default = [-] ;
EXEMODE default = (w:e) ;
FILEMODE default = (w:r) ;
HDRS default = ;
LEX default = lex ;
LINK default = link ;
LINKFLAGS default = ;
LINKLIBS default = ;
MV default = rename ;
OPTIM default = ;
RM default = delete ;
RUNVMS default = mcr ;
SED default = sed ;
SHELLMODE default = (w:er) ;
SLASH default = . ;
STDHDRS default = decc$library_include ;
SUFLIB default = .olb ;
SUFOBJ default = .obj ;
SUFEXE default = .exe ;
switch $(OS)
{
case OPENVMS : CCFLAGS default = /stand=vaxc ;
case VMS : LINKLIBS default = sys$library:vaxcrtl.olb/lib ;
}
}
else if $(MAC)
{
CW default = "{CW}" ;
CWMAC default = "$(CW):MacOS Support" ;
CWMSL default = "$(CW):Metrowerks Standard Library" ;
CWGUSI default = "{CWGUSI}" ;
CC default = mwcppc ;
CCFLAGS default = -eol -w off ;
C++ default = mwcppc ;
C++FLAGS default = -eol -w off ;
CP default = copy ;
DOT default = ":" ;
DOTDOT default = "::" ;
HDRS default = "$(CWGUSI):include"
"$(CWMAC):Headers:Universal Headers"
"$(CWMAC):Headers:System Extras Headers:MPW Extras"
"$(CWMSL):MSL C:MSL Common:Public Includes"
"$(CWMSL):MSL C:MSL Mac:Public Includes" ;
LINK default = mwlinkppc ;
LINKFLAGS default = -mpwtool -warn ;
LINKLIBS default = "$(CWGUSI):Lib:GUSIMPW.Lib.PPC"
"$(CWGUSI):Lib:MSLGUSI.Lib.PPC"
"$(CWMAC):Libraries:MacOS Common:Interfacelib"
"$(CWMAC):Libraries:MacOS PPC:PPCToolLibs.o"
"$(CWMAC):Libraries:MacOS Common:PLStringFuncs Glue:PLStringFuncsPPC.lib"
"$(CWMAC):Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib"
"$(CWMSL):MSL C:Bin:MSL C.PPC MPW(NL).Lib"
"$(CWMAC):Libraries:MacOS Common:Mathlib" ;
MKDIR default = newfolder ;
MV default = rename ;
NOARSCAN default = true ;
OPTIM default = ;
RM default = delete ;
SLASH default = ":" ;
STDHDRS default = ; #$(MWCIncludes) ;
SUFLIB default = .lib ;
SUFOBJ default = .o ;
SUFEXE default = "" ;
NOARSCAN default = true ;
}
#
# Define some MS-specific commands for MS-specific actions (which
# are not yet added to Jambase)
#
if $(NT) || $(OS2)
{
MSLIB default = lib ;
MSLINK default = link ;
MSIMPLIB default = implib ;
MSRC default = rc ;
}
JAMFILE default = Jamfile ;
JAMRULES default = Jamrules ;
HDRPATTERN = "^[ ]*#[ ]*include[ ]*[<\"](.*)[\">].*$" ;
#
# Base dependencies - first for "bootstrap" kinds of rules
#
DEPENDS all : shell files lib exe obj ;
DEPENDS all shell files lib exe obj : first ;
NOTFILE all first shell files lib exe obj dirs clean uninstall ;
ALWAYS clean uninstall ;
#
# Rules
#
rule As
{
DEPENDS $(<) : $(>) ;
ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
}
rule Bulk
{
local i ;
for i in $(>)
{
File $(i:D=$(<)) : $(i) ;
}
}
rule Cc
{
local _h ;
DEPENDS $(<) : $(>) ;
# Just to clarify here: this sets the per-target CCFLAGS to
# be the current value of (global) CCFLAGS and SUBDIRCCFLAGS.
CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) ;
# If the compiler's -o flag doesn't work, relocate the .o
if $(RELOCATE)
{
CcMv $(<) : $(>) ;
}
_h = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;
if $(VMS) && $(_h)
{
SLASHINC on $(<) = "/inc=(" $(_h[1]) ,$(_h[2-]) ")" ;
}
else if $(MAC) && $(_h)
{
local _i _j ;
_j = $(_h[1]) ;
for _i in $(_h[2-])
{
_j = $(_j),$(_i) ;
}
MACINC on $(<) = \"$(_j)\" ;
}
}
rule C++
{
local _h ;
DEPENDS $(<) : $(>) ;
C++FLAGS on $(<) += $(C++FLAGS) $(SUBDIRC++FLAGS) ;
if $(RELOCATE)
{
CcMv $(<) : $(>) ;
}
_h = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;
if $(VMS) && $(_h)
{
SLASHINC on $(<) = "/inc=(" $(_h[1]) ,$(_h[2-]) ")" ;
}
else if $(MAC) && $(_h)
{
local _i _j ;
_j = $(_h[1]) ;
for _i in $(_h[2-])
{
_j = $(_j),$(_i) ;
}
MACINC on $(<) = \"$(_j)\" ;
}
}
rule File
{
DEPENDS files : $(<) ;
DEPENDS $(<) : $(>) ;
SEARCH on $(>) = $(SEARCH_SOURCE) ;
MODE on $(<) = $(FILEMODE) ;
Chmod $(<) ;
}
rule Fortran
{
DEPENDS $(<) : $(>) ;
}
rule GenFile
{
local s ;
makeGristedName s : $(<) ;
Depends $(s) : $(>[1]:S=$(SUFEXE)) $(>[2-]) ;
GenFile1 $(s) : $(>[1]:S=$(SUFEXE)) $(>[2-]) ;
Clean clean : $(s) ;
}
rule GenFile1
{
MakeLocate $(<) : $(LOCATE_SOURCE) ;
SEARCH on $(>) = $(SEARCH_SOURCE) ;
}
rule HardLink
{
DEPENDS files : $(<) ;
DEPENDS $(<) : $(>) ;
SEARCH on $(>) = $(SEARCH_SOURCE) ;
}
rule HdrRule
{
# HdrRule source : headers ;
# N.B. This rule is called during binding, potentially after
# the fate of many targets has been determined, and must be
# used with caution: don't add dependencies to unrelated
# targets, and don't set variables on $(<).
# Tell Jam that anything depending on $(<) also depends on $(>),
# set SEARCH so Jam can find the headers, but then say we don't
# care if we can't actually find the headers (they may have been
# within ifdefs),
local s ;
if $(HDRGRIST)
{
s = $(>:G=$(HDRGRIST)) ;
} else {
s = $(>) ;
}
INCLUDES $(<) : $(s) ;
SEARCH on $(s) = $(HDRSEARCH) ;
NOCARE $(s) ;
# Propagate on $(<) to $(>)
HDRSEARCH on $(s) = $(HDRSEARCH) ;
HDRSCAN on $(s) = $(HDRSCAN) ;
HDRRULE on $(s) = $(HDRRULE) ;
HDRGRIST on $(s) = $(HDRGRIST) ;
}
rule InstallInto
{
local i t ;
t = $(>:G=installed) ;
DEPENDS install : $(t) ;
DEPENDS $(t) : $(>) ;
SEARCH on $(>) = $(SEARCH_SOURCE) ;
MakeLocate $(t) : $(<) ;
# Arrange for jam uninstall
Clean uninstall : $(t) ;
for i in $(>)
{
Install $(i:G=installed) : $(i) ;
}
if ! $(INSTALL)
{
Chmod $(t) ;
if $(OWNER) { Chown $(t) ; OWNER on $(t) = $(OWNER) ; }
if $(GROUP) { Chgrp $(t) ; GROUP on $(t) = $(GROUP) ; }
}
}
rule InstallBin
{
InstallInto $(<) : $(>) ;
MODE on $(>:G=installed) = $(EXEMODE) ;
}
rule InstallFile
{
InstallInto $(<) : $(>) ;
MODE on $(>:G=installed) = $(FILEMODE) ;
}
rule InstallLib
{
InstallInto $(<) : $(>) ;
MODE on $(>:G=installed) = $(FILEMODE) ;
}
rule InstallMan
{
# Really this just strips the . from the suffix
local i s d ;
for i in $(>)
{
switch $(i:S)
{
case .1 : s = 1 ; case .2 : s = 2 ; case .3 : s = 3 ;
case .4 : s = 4 ; case .5 : s = 5 ; case .6 : s = 6 ;
case .7 : s = 7 ; case .8 : s = 8 ; case .l : s = l ;
case .n : s = n ; case .man : s = 1 ;
}
d = man$(s) ;
InstallInto $(d:R=$(<)) : $(i) ;
}
MODE on $(>:G=installed) = $(FILEMODE) ;
}
rule InstallShell
{
InstallInto $(<) : $(>) ;
MODE on $(>:G=installed) = $(SHELLMODE) ;
}
rule Lex
{
DEPENDS $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_SOURCE) ;
Clean clean : $(<) ;
}
rule Library
{
LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
Objects $(>) ;
}
rule LibraryFromObjects
{
local i l s ;
# Add grist to file names
makeGristedName s : $(>) ;
# library depends on its member objects
l = $(<:S=$(SUFLIB)) ;
if $(KEEPOBJS)
{
DEPENDS obj : $(s) ;
}
else
{
DEPENDS lib : $(l) ;
}
# Set LOCATE for the library and its contents. The bound
# value shows up as $(NEEDLIBS) on the Link actions.
# For compatibility, we only do this if the library doesn't
# already have a path.
if ! $(l:D)
{
MakeLocate $(l) $(l)($(s:BS)) : $(LOCATE_TARGET) ;
}
if $(NOARSCAN)
{
# If we can't scan the library to timestamp its contents,
# we have to just make the library depend directly on the
# on-disk object files.
DEPENDS $(l) : $(s) ;
}
else
{
# If we can scan the library, we make the library depend
# on its members and each member depend on the on-disk
# object file.
DEPENDS $(l) : $(l)($(s:BS)) ;
for i in $(s)
{
DEPENDS $(l)($(i:BS)) : $(i) ;
}
}
Clean clean : $(l) ;
if $(CRELIB) { CreLib $(l) : $(s[1]) ; }
Archive $(l) : $(s) ;
if $(RANLIB) { Ranlib $(l) ; }
# If we can't scan the library, we have to leave the .o's around.
if ! ( $(NOARSCAN) || $(KEEPOBJS) ) { RmTemps $(l) : $(s) ; }
}
rule Link
{
MODE on $(<) = $(EXEMODE) ;
Chmod $(<) ;
}
rule LinkLibraries
{
local t ;
# make library dependencies of target
# set NEEDLIBS variable used by 'actions Main'
if $(<:S)
{
t = $(<) ;
} else {
t = $(<:S=$(SUFEXE)) ;
}
DEPENDS $(t) : $(>:S=$(SUFLIB)) ;
NEEDLIBS on $(t) += $(>:S=$(SUFLIB)) ;
}
rule Main
{
MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
Objects $(>) ;
}
rule MainFromObjects
{
local s t ;
# Add grist to file names
makeGristedName s : $(>) ;
makeSuffixed t $(SUFEXE) : $(<) ;
if $(t) != $(<)
{
DEPENDS $(<) : $(t) ;
NOTFILE $(<) ;
}
# make compiled sources a dependency of target
DEPENDS exe : $(t) ;
DEPENDS $(t) : $(s) ;
MakeLocate $(t) : $(LOCATE_TARGET) ;
Clean clean : $(t) ;
Link $(t) : $(s) ;
}
rule MakeLocate
{
if $(>)
{
LOCATE on $(<) = $(>) ;
Depends $(<) : $(>[1]) ;
MkDir $(>[1]) ;
}
}
rule MkDir
{
if $(<) != $(DOT) && ! $($(<)-mkdir)
{
local s ;
# Cheesy gate to prevent multiple invocations on same dir
# MkDir1 has the actions
# If dir exists, don't update it
# Arrange for jam dirs
$(<)-mkdir = true ;
MkDir1 $(<) ;
NOUPDATE $(<) ;
Depends dirs : $(<) ;
# Recursively make parent directories.
# $(<:P) = $(<)'s parent, & we recurse until root
s = $(<:P) ;
if $(NT)
{
switch $(s)
{
case *: : s = ;
case *:\\ : s = ;
}
}
if $(s) && $(s) != $(<)
{
Depends $(<) : $(s) ;
MkDir $(s) ;
}
else if $(s)
{
NOTFILE $(s) ;
}
}
}
rule Object
{
local h ;
# locate object and search for source, if wanted
Clean clean : $(<) ;
MakeLocate $(<) : $(LOCATE_TARGET) ;
SEARCH on $(>) = $(SEARCH_SOURCE) ;
# Save HDRS for -I$(HDRS) on compile.
# We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers
# in the .c file's directory, but generated .c files (from
# yacc, lex, etc) are located in $(LOCATE_TARGET), possibly
# different from $(SEARCH_SOURCE).
HDRS on $(<) = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;
# handle #includes for source: Jam scans for headers with
# the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE)
# with the scanned file as the target and the found headers
# as the sources. HDRSEARCH is the value of SEARCH used for
# the found header files. Finally, if jam must deal with
# header files of the same name in different directories,
# they can be distinguished with HDRGRIST.
# $(h) is where cc first looks for #include "foo.h" files.
# If the source file is in a distant directory, look there.
# Else, look in "" (the current directory).
if $(SEARCH_SOURCE)
{
h = $(SEARCH_SOURCE) ;
}
else
{
h = "" ;
}
HDRRULE on $(>) = HdrRule ;
HDRSCAN on $(>) = $(HDRPATTERN) ;
HDRSEARCH on $(>) = $(HDRS) $(SUBDIRHDRS) $(h) $(STDHDRS) ;
HDRGRIST on $(>) = $(HDRGRIST) ;
# if source is not .c, generate .c with specific rule
switch $(>:S)
{
case .asm : As $(<) : $(>) ;
case .c : Cc $(<) : $(>) ;
case .C : C++ $(<) : $(>) ;
case .cc : C++ $(<) : $(>) ;
case .cpp : C++ $(<) : $(>) ;
case .f : Fortran $(<) : $(>) ;
case .l : Cc $(<) : $(<:S=.c) ;
Lex $(<:S=.c) : $(>) ;
case .s : As $(<) : $(>) ;
case .y : Cc $(<) : $(<:S=.c) ;
Yacc $(<:S=.c) : $(>) ;
case * : UserObject $(<) : $(>) ;
}
}
rule ObjectCcFlags
{
local s ;
# Add grist to file names
makeGristedName s : $(<:S=$(SUFOBJ)) ;
CCFLAGS on $(s) += $(>) ;
}
rule ObjectC++Flags
{
local s ;
# Add grist to file names
makeGristedName s : $(<:S=$(SUFOBJ)) ;
C++FLAGS on $(s) += $(>) ;
}
rule ObjectHdrs
{
local s ;
# Add grist to file names
makeGristedName s : $(<:S=$(SUFOBJ)) ;
HDRS on $(s) += $(>) ;
}
rule Objects
{
local i s ;
# Add grist to file names
makeGristedName s : $(<) ;
for i in $(s)
{
Object $(i:S=$(SUFOBJ)) : $(i) ;
DEPENDS obj : $(i:S=$(SUFOBJ)) ;
}
}
rule RmTemps
{
TEMPORARY $(>) ;
}
rule Setuid
{
local t ;
if $(<:S)
{
t = $(<) ;
} else {
t = $(<:S=$(SUFEXE)) ;
}
MODE on $(t) = 4711 ;
}
rule Shell
{
DEPENDS shell : $(<) ;
DEPENDS $(<) : $(>) ;
SEARCH on $(>) = $(SEARCH_SOURCE) ;
MODE on $(<) = $(SHELLMODE) ;
Clean clean : $(<) ;
Chmod $(<) ;
}
rule SubDir
{
local r s ;
#
# SubDir TOP d1 [ ... ]
#
# This introduces a Jamfile that is part of a project tree
# rooted at $(TOP). It (only once) includes the project-specific
# rules file $(TOP)/Jamrules and then sets search & locate stuff.
#
# If the variable $(TOPRULES) is set (where TOP is the first arg
# to SubDir), that file is included instead of $(TOP)/Jamrules.
#
# d1 ... are the directory elements that lead to this directory
# from $(TOP). We construct the system dependent path from these
# directory elements in order to set search&locate stuff.
#
if ! $($(<[1]))
{
if ! $(<[1])
{
EXIT SubDir syntax error ;
}
makeSubDir $(<[1]) : $(<[2-]) ;
}
#
# If $(TOP)/Jamrules hasn't been included, do so.
#
if ! $($(<[1])-included)
{
# Gated entry.
$(<[1])-included = TRUE ;
# File is $(TOPRULES) or $(TOP)/Jamrules.
r = $($(<[1])RULES) ;
if ! $(r)
{
r = $(JAMRULES:R=$($(<[1]))) ;
}
# Include it.
include $(r) ;
}
# Get path to current directory from root using makeSubDir.
# Save dir tokens for other potential uses.
makeDirName s : $(<[2-]) ;
SUBDIR = $(s:R=$($(<[1]))) ;
SUBDIR_TOKENS = $(<[2-]) ;
# Now set up SEARCH_SOURCE, LOCATE_TARGET, SOURCE_GRIST
# These can be reset if needed. For example, if the source
# directory should not hold object files, LOCATE_TARGET can
# subsequently be redefined.
SEARCH_SOURCE = $(SUBDIR) ;
LOCATE_SOURCE = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
LOCATE_TARGET = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
makeGrist SOURCE_GRIST : $(<[2-]) ;
# Reset per-directory ccflags, hdrs
SUBDIRCCFLAGS = ;
SUBDIRC++FLAGS = ;
SUBDIRHDRS = ;
}
rule SubDirCcFlags
{
SUBDIRCCFLAGS += $(<) ;
}
rule SubDirC++Flags
{
SUBDIRC++FLAGS += $(<) ;
}
rule SubDirHdrs
{
SUBDIRHDRS += $(<) ;
}
rule SubInclude
{
local s ;
# That's
# SubInclude TOP d1 [ d2 [ d3 [ d4 ] ] ]
#
# to include a subdirectory's Jamfile.
if ! $($(<[1]))
{
EXIT Top level of source tree has not been set with $(<[1]) ;
}
makeDirName s : $(<[2-]) ;
include $(JAMFILE:D=$(s):R=$($(<[1]))) ;
}
rule Undefines
{
local t ;
if $(<:S)
{
t = $(<) ;
} else {
t = $(<:S=$(SUFEXE)) ;
}
UNDEFS on $(t) += $(UNDEFFLAG)$(>) ;
}
rule UserObject
{
EXIT "Unknown suffix on" $(>) "- see UserObject rule in Jamfile(5)." ;
}
rule Yacc
{
local h ;
h = $(<:BS=.h) ;
# Some places don't have a yacc.
MakeLocate $(<) $(h) : $(LOCATE_SOURCE) ;
if $(YACC)
{
DEPENDS $(<) $(h) : $(>) ;
Yacc1 $(<) $(h) : $(>) ;
Clean clean : $(<) $(h) ;
}
# make sure someone includes $(h) else it will be
# a deadly independent target
INCLUDES $(<) : $(h) ;
}
#
# Utility rules; no side effects on these
#
rule makeString
{
local _t ;
$(<) = $(>[1]) ;
for _t in $(>[2-])
{
$(<) = $($(<))$(_t) ;
}
}
rule makeSubDir
{
local _i _d ;
# If $(>) is the path to the current directory, compute the
# path (using ../../ etc) back to that root directory.
# Sets result in $(<)
if ! $(>[1])
{
_d = $(DOT) ;
}
else
{
_d = $(DOTDOT) ;
for _i in $(>[2-])
{
_d = $(_d:R=$(DOTDOT)) ;
}
}
$(<) = $(_d) ;
}
rule addDirName
{
local _s _i ;
# Turn individual elements in $(>) into a usable path.
# Add result to $(<).
if ! $(>)
{
_s = $(DOT) ;
}
else if $(VMS)
{
# This handles the following cases:
# a -> [.a]
# a b c -> [.a.b.c]
# x: -> x:
# x: a -> x:[a]
# x:[a] b -> x:[a.b]
switch $(>[1])
{
case *:* : _s = $(>[1]) ;
case \\[*\\] : _s = $(>[1]) ;
case * : _s = [.$(>[1])] ;
}
for _i in [.$(>[2-])]
{
_s = $(_i:R=$(_s)) ;
}
}
else if $(MAC)
{
_s = $(DOT) ;
for _i in $(>)
{
_s = $(_i:R=$(_s)) ;
}
}
else
{
_s = $(>[1]) ;
for _i in $(>[2-])
{
_s = $(_i:R=$(_s)) ;
}
}
$(<) += $(_s) ;
}
rule makeDirName
{
$(<) = ; addDirName $(<) : $(>) ;
}
rule makeGrist
{
local _g _i ;
# Turn individual elements in $(>) into grist.
# Return result in $(<)
_g = $(>[1]) ;
for _i in $(>[2-])
{
_g = $(_g)!$(_i) ;
}
$(<) = $(_g) ;
}
rule makeGristedName
{
local _i _o ;
# Produce name with grist in it, if SOURCE_GRIST is set.
if ! $(SOURCE_GRIST)
{
$(<) = $(>) ;
}
else
{
_o = ;
for _i in $(>)
{
switch $(_i)
{
case *.h : _o += $(_i) ;
case * : _o += $(_i:G=$(SOURCE_GRIST)) ;
}
}
$(<) = $(_o) ;
}
}
rule makeCommon
{
if $($(<)[1]) && $($(<)[1]) = $($(>)[1])
{
$(<) = $($(<)[2-]) ;
$(>) = $($(>)[2-]) ;
makeCommon $(<) : $(>) ;
}
}
rule makeRelPath
{
local _l _r ;
# first strip off common parts
_l = $(<[2-]) ;
_r = $(>) ;
makeCommon _l : _r ;
# now make path to root and path down
makeSubDir _l : $(_l) ;
makeDirName _r : $(_r) ;
# Concatenate and save
# XXX This should be better
if $(_r) = $(DOT) {
$(<[1]) = $(_l) ;
} else {
$(<[1]) = $(_r:R=$(_l)) ;
}
}
rule makeSuffixed
{
# E.g., "makeSuffixed s_exe $(SUFEXE) : yacc lex foo.bat ;"
# sets $(s_exe) to (yacc,lex,foo.bat) on Unix and
# (yacc.exe,lex.exe,foo.bat) on NT.
if $(<[2])
{
local _i ;
$(<[1]) = ;
for _i in $(>)
{
if $(_i:S)
{
$(<[1]) += $(_i) ;
}
else
{
$(<[1]) += $(_i:S=$(<[2])) ;
}
}
}
else
{
$(<[1]) = $(>) ;
}
}
rule unmakeDir
{
if $(>[1]:D) && $(>[1]:D) != $(>[1]) && $(>[1]:D) != \\\\
{
unmakeDir $(<) : $(>[1]:D) $(>[1]:BS) $(>[2-]) ;
}
else
{
$(<) = $(>) ;
}
}
#
# Actions
#
if $(UNIX)
{
if $(OS) = QNX
{
actions together piecemeal Archive
{
$(AR) $(<) +-$(>)
}
}
else if $(OS) = BEOS && $(METROWERKS)
{
actions together Archive
{
$(AR) $(<) $(>)
}
}
else
{
actions updated together piecemeal Archive
{
$(AR) $(<) $(>)
}
}
actions As
{
$(AS) $(ASFLAGS) -I$(HDRS) -o $(<) $(>)
}
if $(RELOCATE)
{
actions C++
{
$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) $(>)
}
}
else
{
actions C++
{
$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)
}
}
actions Cc
{
$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)
}
if $(RELOCATE)
{
actions Cc
{
$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) $(>)
}
}
actions ignore CcMv
{
[ $(<) != $(>:BS=$(SUFOBJ)) ] && $(MV) $(>:BS=$(SUFOBJ)) $(<)
}
actions Chgrp
{
chgrp $(GROUP) $(<)
}
actions Chmod
{
chmod $(MODE) $(<)
}
actions Chown
{
chown $(OWNER) $(<)
}
actions piecemeal together existing Clean
{
$(RM) $(>)
}
actions File
{
$(RM) $(<)
$(CP) $(>) $(<)
}
actions GenFile1
{
$(>[1]) $(<) $(>[2-])
}
actions Fortran
{
$(FORTRAN) $(FORTRANFLAGS) -o $(<) $(>)
}
actions HardLink
{
$(RM) $(<) && $(LN) $(>) $(<)
}
if $(INSTALL)
{
actions Install
{
$(INSTALL) -m$(MODE) -o$(OWNER) -g$(GROUP) $(>) $(<)
}
}
else
{
actions Install
{
$(CP) $(>) $(<)
}
}
actions Lex
{
$(LEX) $(>) && $(MV) lex.yy.c $(<)
}
actions Link bind NEEDLIBS
{
$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
}
actions MkDir1
{
$(MKDIR) $(<)
}
actions together Ranlib
{
$(RANLIB) $(<)
}
actions quietly updated piecemeal together RmTemps
{
$(RM) $(>)
}
actions Shell
{
$(AWK) '
NR == 1 { print "$(SHELLHEADER)" }
NR == 1 && /^[#:]/ { next }
/^##/ { next }
{ print }
' < $(>) > $(<)
}
actions Yacc1
{
$(YACC) $(YACCFLAGS) $(>) &&
{
$(MV) $(YACCFILES).c $(<[1])
$(MV) $(YACCFILES).h $(<[2])
}
}
}
else if $(NT) || $(OS2)
{
if $(BCCROOT)
{
actions C++
{
$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
}
actions Link bind NEEDLIBS
{
$(LINK) -e$(<) $(LINKFLAGS) $(UNDEFS) -L$(LINKLIBS) $(NEEDLIBS) $(>)
}
actions updated together piecemeal Archive
{
$(AR) $(ARFLAGS) $(<) -+$(>)
}
actions Cc
{
$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o$(<) $(>)
}
}
else if $(MSVC)
{
actions updated together piecemeal Archive
{
$(AR) $(<) -+$(>) ;
}
actions Cc
{
$(CC) /c $(CCFLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) $(>)
}
actions C++
{
$(C++) /c $(C++FLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /Tp$(>)
}
actions Link bind NEEDLIBS
{
$(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
}
}
else if $(MSVCNT)
{
actions updated together piecemeal Archive
{
if exist $(<) set _$(<:B)_=$(<)
$(AR) /out:$(<) %_$(<:B)_% $(>)
}
actions As
{
$(AS) /Ml /p /v /w2 $(>) $(<) ,nul,nul;
}
actions Cc
{
$(CC) /c $(CCFLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) $(>)
}
actions C++
{
$(C++) /c $(C++FLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) /Tp$(>)
}
actions Link bind NEEDLIBS
{
$(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
}
}
else if $(WATCOM)
{
actions together piecemeal Archive
{
$(AR) $(<) +-$(>)
}
actions Cc
{
$(CC) $(CCFLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)
}
actions C++
{
$(C++) $(C++FLAGS) $(OPTIM) /Fo=$(<) /I$(HDRS) $(>)
}
actions Link bind NEEDLIBS
{
$(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
}
}
actions Chmod
{
}
actions piecemeal together existing Clean
{
$(RM) $(>)
}
actions File
{
copy $(>) $(<)
}
actions GenFile1
{
$(>[1]) $(<) $(>[2-])
}
actions Install
{
copy $(>) $(<)
}
actions MkDir1
{
$(MKDIR) $(<)
}
actions quietly updated piecemeal together RmTemps
{
$(RM) $(>)
}
actions Shell
{
copy $(>) $(<)
}
}
else if $(VMS)
{
actions updated together piecemeal Archive
{
lib/replace $(<) $(>[1]) ,$(>[2-])
}
actions Cc
{
cc/obj=$(<) $(CCFLAGS) $(OPTIM) $(SLASHINC) $(>)
}
actions C++
{
cxx/obj=$(<) $(C++FLAGS) $(OPTIM) $(SLASHINC) $(>)
}
actions Chmod
{
set file/prot=$(MODE) $(<)
}
actions piecemeal together existing Clean
{
$(RM) $(>[1]);* ,$(>[2-]);*
}
actions together quietly CreLib
{
if f$search("$(<)") .eqs. "" then lib/create $(<)
}
actions File
{
copy $(>) $(<)
}
actions GenFile1
{
mcr $(>[1]) $(<) $(>[2-])
}
actions Install
{
copy $(>) $(<)
}
actions Lex
{
$(LEX) $(>)
$(MV) lex.yy.c $(<)
}
actions Link bind NEEDLIBS
{
$(LINK)/exe=$(<) $(LINKFLAGS) $(>[1]) ,$(>[2-]) ,$(NEEDLIBS)/lib ,$(LINKLIBS)
}
actions MkDir1
{
create/dir $(<)
}
actions quietly updated piecemeal together RmTemps
{
$(RM) $(>[1]);* ,$(>[2-]);*
}
actions Shell
{
copy $(>) $(<)
}
actions Yacc1
{
$(YACC) $(YACCFLAGS) $(>)
$(MV) $(YACCFILES).c $(<[1])
$(MV) $(YACCFILES).h $(<[2])
}
}
else if $(MAC)
{
SP = " " ;
actions together Archive
{
$(LINK) -library -o $(<) $(>)
}
actions Cc
{
set MWCincludes $(MACINC)
$(CC) -o $(<) $(CCFLAGS) $(OPTIM) $(>)
}
actions C++
{
set MWCincludes $(MACINC)
$(CC) -o $(<) $(C++FLAGS) $(OPTIM) $(>)
}
rule Chmod
{
# no chmod on mac - could setfile -l/-L to make rw/ro
}
actions piecemeal together existing Clean
{
$(RM) $(>)
}
actions File
{
copy $(>) $(<)
}
actions GenFile1
{
$(>[1]) $(<) $(>[2-])
}
actions Install
{
copy $(>) $(<)
}
actions Link bind NEEDLIBS
{
$(LINK) -o $(<) $(LINKFLAGS) $(>) $(NEEDLIBS) "$(LINKLIBS)"
}
actions MkDir1
{
$(MKDIR) $(<)
}
actions quietly updated piecemeal together RmTemps
{
$(RM) $(>)
}
actions Shell
{
copy $(>) $(<)
}
}
#
# Backwards compatibility with jam 1, where rules were uppercased.
#
rule BULK { Bulk $(<) : $(>) ; }
rule FILE { File $(<) : $(>) ; }
rule HDRRULE { HdrRule $(<) : $(>) ; }
rule INSTALL { Install $(<) : $(>) ; }
rule LIBRARY { Library $(<) : $(>) ; }
rule LIBS { LinkLibraries $(<) : $(>) ; }
rule LINK { Link $(<) : $(>) ; }
rule MAIN { Main $(<) : $(>) ; }
rule SETUID { Setuid $(<) ; }
rule SHELL { Shell $(<) : $(>) ; }
rule UNDEFINES { Undefines $(<) : $(>) ; }
# Old INSTALL* didn't take dest directory.
rule INSTALLBIN { InstallBin $(BINDIR) : $(<) ; }
rule INSTALLLIB { InstallLib $(LIBDIR) : $(<) ; }
rule INSTALLMAN { InstallMan $(MANDIR) : $(<) ; }
#
# Now include the user's Jamfile.
#
{
if $(JAMFILE) { include $(JAMFILE) ; }
}