tools/build/v1/allyourbase.jam
#
# /+\
# +\ Copyright 1993, 2000 Christopher Seiwald.
# \+/
#
# This file is part of Jam - see jam.c for Copyright information.
#
# This file is ALSO:
# (C) Copyright David Abrahams 2001.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
#
# JAMBASE - jam 2.3 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 '?=' 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
# 07/19/99 (sickel) - Support for Mac OS X Server (and maybe client)
# 02/18/00 (belmonte)- Support for Cygwin.
# 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 (not supported):
#
# FAppendSuffix f1 f2 ... : $(SUF) ; return $(<) with suffixes
# join value ... ; return contatenated values
# FDirName d1 d2 ... ; return path from root to dir
# FGrist d1 d2 ... ; return d1!d2!...
# FGristFiles value ; return $(value:G=$(SOURCE_GRIST))
# FGristSourceFiles value ; return $(value:G=$(SOURCE_GRIST))
# FRelPath d1 : d2 ; return rel path from d1 to d2
# FSubDir d1 d2 ... ; return path to root
#
# 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
# bind vars - subject to binding before expanding in actions
#
# 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 :)
# $(xxx) - true on xxx (UNIX, VMS, NT, OS2, MAC)
# $(OS) - name of OS - varies wildly
# $(JAMVERSION) - version number (2.3)
#
# 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
#
#
# OS specific variable settings
#
# dwa 6/4/01 - removed all settings of the following variables for boost:
# CC, CCFLAGS, C++, C++FLAGS, LINK, LINKFLAGS, LINKLIBS
# probably a lot more could be cleared away
if $(NT)
{
CP ?= copy ;
RM ?= del /f/q ;
SLASH ?= \\ ;
SPLITPATH ?= ";" ; # dwa -- added missing SPLITPATH
SUFLIB ?= .lib ;
SUFOBJ ?= .obj ;
SUFEXE ?= .exe ;
SUFDLL ?= .dll .lib ;
gLINK_VARIABLE(.dll) = ; # dlls are NOT linked to directly
gLINK_VARIABLE(.lib) = NEEDLIBS ; # instead, users link to import libs
PREDLL ?= "" ;
NOARSCAN ?= true ;
SHELL_EXPORT ?= ;
SHELL_SET ?= "set " ;
# dwa 6/4/01 - removed compiler determination for boost
# added some yacc/lex stuff, assuming cygwin for now.
LEX ?= flex ;
YACC ?= bison -y ;
YACCFILES ?= y.tab ;
YACC_OUTPUT ?= --output= ;
LEX_OUTPUT ?= -o ;
LN ?= $(CP) ;
NULL_OUT ?= >NUL: ;
}
else if $(OS2)
{
WATCOM ?= $(watcom) ;
if ! $(WATCOM)
{
EXIT On OS2, set WATCOM to the root of the Watcom directory. ;
}
AR ?= wlib ;
BINDIR ?= \\os2\\apps ;
CP ?= copy ;
DOT ?= . ;
DOTDOT ?= .. ;
MV ?= move ;
NOARSCAN ?= true ;
OPTIM ?= ;
RM ?= del /f ;
SLASH ?= \\ ;
SPLITPATH ?= ";" ; # dwa -- added missing SPLITPATH
STDHDRS ?= $(WATCOM)\\h ;
SUFEXE ?= .exe ;
SUFLIB ?= .lib ;
SUFOBJ ?= .obj ;
UNDEFFLAG ?= "/u _" ;
}
else if $(VMS)
{
CHMOD ?= set file/prot= ;
CP ?= copy/replace ;
CRELIB ?= true ;
DOT ?= [] ;
DOTDOT ?= [-] ;
EXEMODE ?= (w:e) ;
FILEMODE ?= (w:r) ;
HDRS ?= ;
MKDIR ?= create/dir ;
MV ?= rename ;
OPTIM ?= "" ;
RM ?= delete ;
RUNVMS ?= mcr ;
SHELLMODE ?= (w:er) ;
SLASH ?= . ;
STDHDRS ?= decc$library_include ;
SUFEXE ?= .exe ;
SUFLIB ?= .olb ;
SUFOBJ ?= .obj ;
switch $(OS)
{
case VMS : LINKLIBS ?= sys$library:vaxcrtl.olb/lib ;
}
}
else if $(MAC)
{
local OPT ;
CW ?= "{CW}" ;
MACHDRS ?=
"$(UMACHDRS):Universal:Interfaces:CIncludes"
"$(CW):MSL:MSL_C:MSL_Common:Include"
"$(CW):MSL:MSL_C:MSL_MacOS:Include" ;
MACLIBS ?=
"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Interfacelib"
"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Mathlib" ;
MPWLIBS ?=
"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib"
"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW.Lib" ;
MPWNLLIBS ?=
"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib"
"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW(NL).Lib" ;
SIOUXHDRS ?= ;
SIOUXLIBS ?=
"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL RuntimePPC.lib"
"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL SIOUX.PPC.Lib"
"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC.Lib" ;
CP ?= duplicate -y ;
DOT ?= ":" ;
DOTDOT ?= "::" ;
HDRS ?= $(MACHDRS) $(MPWHDRS) ;
MKDIR ?= newfolder ;
MV ?= rename -y ;
NOARSCAN ?= true ;
OPTIM ?= ;
RM ?= delete -y ;
SLASH ?= ":" ;
STDHDRS ?= ;
SUFLIB ?= .lib ;
SUFOBJ ?= .o ;
}
else if $(OS) = BEOS && $(METROWERKS)
{
AR ?= mwld -xml -o ;
BINDIR ?= /boot/apps ;
FORTRAN ?= "" ;
LIBDIR ?= /boot/develop/libraries ;
MANDIR ?= /boot/documentation/"Shell Tools"/HTML ;
NOARSCAN ?= true ;
STDHDRS ?= /boot/develop/headers/posix ;
}
else if $(OS) = BEOS
{
BINDIR ?= /boot/apps ;
FORTRAN ?= "" ;
LIBDIR ?= /boot/develop/libraries ;
NOARSCAN ?= true ;
STDHDRS ?= /boot/develop/headers/posix ;
}
else if $(UNIX)
{
switch $(OS)
{
case AIX :
IMPLIB_FLAGS ?= -bI: ;
SUFDLL ?= .so ;
gLINK_VARIABLE(.so) = NEEDLIBS ; # shared libs should be added to the list of libs needed
gLINK_VARIABLE(.imp) = NEEDIMPS ; # import libs are handled separately.
gSHELL_LIBPATH = LIBPATH ;
case AMIGA :
YACC ?= bison -y ;
case CYGWIN :
LEX ?= flex ;
RANLIB ?= "" ;
SUFEXE ?= .exe ;
YACC ?= bison -y ;
MKDIR ?= mkdir -p ;
SUFDLL ?= .dll ;
case DGUX :
RANLIB ?= "" ;
RELOCATE ?= true ;
case HPUX :
RANLIB ?= "" ;
case INTERIX :
RANLIB ?= "" ;
case IRIX :
RANLIB ?= "" ;
case LINUX :
CLONE ?= cp -fpd ;
case MPEIX :
HDRS += /usr/include ;
RANLIB ?= "" ;
NOARSCAN ?= true ;
NOARUPDATE ?= true ;
case MVS :
RANLIB ?= "" ;
case NEXT :
AR ?= libtool -o ;
RANLIB ?= "" ;
case MACOSX :
MANDIR ?= /usr/local/share/man ;
SUFDLL ?= .dylib ;
gSHELL_LIBPATH ?= DYLD_LIBRARY_PATH ;
NOARSCAN ?= true ;
case NCR :
RANLIB ?= "" ;
case PTX :
RANLIB ?= "" ;
case QNX :
AR ?= wlib ;
NOARSCAN ?= true ;
RANLIB ?= "" ;
case SCO :
RANLIB ?= "" ;
RELOCATE ?= true ;
case SINIX :
RANLIB ?= "" ;
case SOLARIS :
RANLIB ?= "" ;
AR ?= "/usr/ccs/bin/ar ru" ;
case UNICOS :
NOARSCAN ?= true ;
OPTIM ?= -O0 ;
case UNIXWARE :
RANLIB ?= "" ;
RELOCATE ?= true ;
case OSF :
gLINK_VARIABLE(.so) = NEEDLIBS ; # shared objects should be added to the list of libs needed
}
# UNIX defaults
CHMOD ?= chmod ;
LEX ?= lex ;
OPTIM ?= -O ;
RANLIB ?= ranlib ;
YACC ?= yacc ;
YACCFILES ?= y.tab ;
YACCFLAGS ?= -d ;
SHELL_EXPORT ?= "export " ;
SHELL_SET ?= "" ;
gSHELL_LIBPATH ?= LD_LIBRARY_PATH ;
}
#
# General defaults; a lot like UNIX
#
AR ?= ar ru ;
AS ?= as ;
ASFLAGS ?= ;
AWK ?= awk ;
BINDIR ?= /usr/local/bin ;
CLONE ?= $(CP) ;
CLONE ?= cp -fp ;
CP ?= cp -f ;
CRELIB ?= ;
DOT ?= . ;
DOTDOT ?= .. ;
EXEMODE ?= 711 ;
DLLMODE ?= 755 ;
FILEMODE ?= 644 ;
FORTRAN ?= f77 ;
FORTRANFLAGS ?= ;
HDRS ?= ;
JAMFILE ?= Jamfile ;
JAMRULES ?= Jamrules ;
LEX ?= ;
LIBDIR ?= /usr/local/lib ;
LN ?= ln ;
MANDIR ?= /usr/local/man ;
MKDIR ?= mkdir ;
MV ?= mv -f ;
OPTIM ?= ;
RCP ?= rcp ;
RM ?= rm -f ;
RSH ?= rsh ;
SED ?= sed ;
SHELLHEADER ?= "#!/bin/sh" ;
SHELLMODE ?= 755 ;
SHELL_EXPORT ?= ;
SHELL_SET ?= "" ;
SLASH ?= / ;
SPLITPATH ?= ":" ; # dwa -- added missing SPLITPATH
STDHDRS ?= /usr/include ;
SUFEXE ?= "" ;
SUFDLL ?= .so ;
SUFLIB ?= .a ;
SUFOBJ ?= .o ;
PREDLL ?= lib ;
PRELIB ?= lib ;
UNDEFFLAG ?= "-u _" ;
YACC ?= ;
YACCFILES ?= ;
YACCFLAGS ?= ;
BIN_DIRECTORY ?= bin ;
#~ HDRPATTERN =
#~ "^[ ]*#[ ]*include[ ]*([<\"][^\">]*[\">]).*$" ;
HDRPATTERN =
"^[ ]*#[ ]*include[ ]*([<\"][^\">]*[\">]).*$" ;
#" My Jam mode gets its syntax highlighting confused without this comment
OSFULL = $(OS)$(OSVER)$(OSPLAT) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ;
#
# Rule to automate patching of singleton variables from the user so that
# they are correctly interpreted as a single entry instead of as a list if
# they happen to contain spaces.
#
# This also remembers the first(global) value so that it can be reset
# when cleared, but used again.
#
rule set-as-singleton ( variables + )
{
for local variable in $(variables)
{
$(variable) = $($(variable):J=" ") ;
#~ if ! $(gSINGLETON_SET($(variable)))
#~ {
#~ gSINGLETON($(variable)) = $($(variable)) ;
#~ gSINGLETON_SET($(variable)) = true ;
#~ }
#~ $(variable) ?= $(gSINGLETON($(variable))) ;
}
}
#
# "Fix" the known possibly directory variables.
#
set-as-singleton
BINDIR
CW
JAMFILE
JAMRULES
JAMSHELL
LIBDIR
MANDIR
WATCOM
;
#
# Base dependencies - first for "bootstrap" kinds of rules
#
# dwa 6/17/01 - added test
DEPENDS all : shell files lib dll exe obj ;
DEPENDS all shell files lib dll exe obj test : first ;
NOTFILE all first shell files lib dll exe obj dirs clean uninstall test ;
ALWAYS clean uninstall ;
#
# Rules
#
# dwa 6/4/01 - added for boost
# type-DEPENDS type : targets...
#
# Use this to create a dependency between a fake type-target and other targets. Will prevent
# targets in dependee subprojects from being added to the type-target's dependencies.
rule type-DEPENDS # type-target : targets...
{
if ! $(gSUPPRESS_FAKE_TARGETS) && ! $(gIN_LIB_INCLUDE)
{
DEPENDS $(<) : $(>) ;
}
}
# dwa 6/4/01 - added for boost
# Archive file-target : sources
#
# Used to dispatch through Archive-action, which should be redefined in toolset
# description files.
rule Archive
{
Archive-action $(<) : $(>) ;
}
rule As
{
DEPENDS $(<) : $(>) ;
ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
}
rule Bulk
{
local i ;
for i in $(>)
{
File $(i:D=$(<)) : $(i) ;
}
}
# dwa 6/4/01 - modified for boost
# factored out stuff from the builtin Cc and C++ rules
rule Cc-platform-specifics
{
# If the compiler's -o flag doesn't work, relocate the .o
if $(RELOCATE)
{
CcMv $(<) : $(>) ;
}
local _h = $(SEARCH_SOURCE) $(HDRS) ;
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)\" ;
}
}
# dwa 6/4/01 - added for boost
# always-c++ filename...
#
# declares that the given files should be compiled as C++, regardless of their
# filename extension.
rule always-c++
{
gALWAYS_C++ += [ FGristFiles $(<) ] ;
}
# dwa 6/4/01 - modified for boost
rule Cc
{
DEPENDS $(<) : $(>) ;
Cc-platform-specifics $(<) : $(>) ;
if $(>) in $(gALWAYS_C++)
{
C++-action $(<) : $(>) ;
}
else
{
Cc-action $(<) : $(>) ;
}
}
# dwa 6/4/01 - modified for boost
rule C++
{
DEPENDS $(<) : $(>) ;
Cc-platform-specifics $(<) : $(>) ;
C++-action $(<) : $(>) ;
}
rule Chmod
{
if $(CHMOD) { Chmod1 $(<) ; }
}
# dwa 6/4/01 - added for boost
# conditional <cond> : <true-value> : <false-value>
# returns <true-value> if <cond>, <false-value> otherwise
rule conditional
{
if $(1) { return $(2) ; } else { return $(3) ; }
}
# dwa 6/4/01 - modified for boost
rule File
{
type-DEPENDS files : $(<) ;
DEPENDS $(<) : $(>) ;
SEARCH on $(>) = $(SEARCH_SOURCE) ;
MODE on $(<) = $(FILEMODE) ;
Chmod $(<) ;
}
rule FileClone
{
type-DEPENDS files : $(<) ;
DEPENDS $(<) : $(>) ;
SEARCH on $(>) = $(SEARCH_SOURCE) ;
}
rule Fortran
{
DEPENDS $(<) : $(>) ;
}
rule GenFile
{
local _t = [ FGristSourceFiles $(<) ] ;
local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;
Depends $(_t) : $(_s) $(>[2-]) ;
GenFile1 $(_t) : $(_s) $(>[2-]) ;
Clean clean : $(_t) ;
}
rule GenFile1
{
MakeLocate $(<) : $(LOCATE_SOURCE) ;
SEARCH on $(>) = $(SEARCH_SOURCE) ;
}
# dwa 6/4/01 - modified for boost
rule HardLink
{
type-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 angle-includes = [ MATCH "[<]([^>]+)[>]" : $(>) ] ;
local quoted-includes = [ MATCH "[\"]([^\"]+)[\"]" : $(>) ] ;
local s ;
if $(HDRGRIST)
{
angle-includes = $(angle-includes:G=$(HDRGRIST)) ;
quoted-includes = $(quoted-includes:G=$(HDRGRIST)) ;
}
local s = $(angle-includes) $(quoted-includes) ;
INCLUDES $(<) : $(s) ;
SEARCH on $(angle-includes) = $(HDRSEARCH) ;
SEARCH on $(quoted-includes) = $(gBINDING($(<)):D) $(HDRSEARCH) ;
NOCARE $(s) ;
BINDRULE on $(s) = remember-binding ;
# Propagate on $(<) to $(>)
HDRSEARCH on $(s) = $(HDRSEARCH) ;
HDRSCAN on $(s) = $(HDRSCAN) ;
HDRRULE on $(s) = $(HDRRULE) ;
HDRGRIST on $(s) = $(HDRGRIST) ;
}
# dwa 6/4/01 - modified for boost
rule InstallInto
{
local i t ;
t = $(>:G=installed) ;
type-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) ;
}
Chmod $(t) ;
if $(UNIX)
{
if $(OWNER) { Chown $(t) ; OWNER on $(t) = $(OWNER) ; }
if $(GROUP) { Chgrp $(t) ; GROUP on $(t) = $(GROUP) ; }
}
}
rule InstallBin
{
local _t = [ FAppendSuffix $(>) : $(SUFEXE) ] ;
InstallInto $(<) : $(_t) ;
MODE on $(_t: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) ;
}
# dwa 6/4/01 - modified for boost
rule Lex # file.c : file.l
{
# If we don't have a way of specifying the lex output file, we'll have to move it
# We'd rather not do this if possible because: a. lex generates #line
# directives for the output file which would refer to the wrong place and
# b. the Jam invocation directory could be read-only
if ! $(LEX_OUTPUT)
{
LexMv $(<) : $(>) ;
}
DEPENDS $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_SOURCE) ;
SEARCH on $(<) = $(LOCATE_SOURCE) ;
Clean clean : $(<) ;
}
# dwa 6/4/01 - modified for boost
rule Library
{
LibraryFromObjects $(<) : [ Objects $(>) ] ;
}
# dwa 6/4/01 - modified for boost
rule LibraryFromObjects
{
local _i _l ;
_l = $(<:S=$(SUFLIB)) ;
# library depends on its member objects
if $(KEEPOBJS)
{
type-DEPENDS obj : $(>) ;
}
else
{
type-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)($(>: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) : $(>) ;
}
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)($(>:BS)) ;
for _i in $(>)
{
DEPENDS $(_l)($(_i:BS)) : $(_i) ;
}
}
Clean clean : $(_l) ;
if $(CRELIB) { CreLib $(_l) : $(>[1]) ; }
Archive $(_l) : $(>) ;
if $(RANLIB) { Ranlib $(_l) ; }
# If we can't scan the library, we have to leave the .o's around.
if ! ( $(NOARSCAN) || $(KEEPOBJS) ) { RmTemps $(_l) : $(>) ; }
}
# dwa 6/4/01 - modified for boost to dispatch through Link-action and to pass
# the target-type through. *** NOW UNUSED BY BOOST ***
#
# Link executable-target : object-target...
rule Link
{
MODE on $(<) = $(EXEMODE) ;
Link-action $(<) : $(>) : $(3) ;
Chmod $(<) ;
}
rule LinkLibraries
{
# make library dependencies of target
# set NEEDLIBS variable used by 'actions Main'
local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
DEPENDS $(_t) : $(>:S=$(SUFLIB)) ;
NEEDLIBS on $(_t) += $(>:S=$(SUFLIB)) ;
}
# dwa 6/4/01 - modified for boost
rule Main
{
MainFromObjects $(<) : [ Objects $(>) ] ;
}
# dwa 6/4/01 - modified for boost
rule MainFromObjects
{
local _s _t ;
# Add grist to file names
# Add suffix to exe
_s = $(>) ;
_t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
if $(_t) != $(<)
{
DEPENDS $(<) : $(_t) ;
NOTFILE $(<) ;
}
# make compiled sources a dependency of target
type-DEPENDS exe : $(_t) ;
DEPENDS $(_t) : $(_s) ;
MakeLocate $(_t) : $(LOCATE_TARGET) ;
Clean clean : $(_t) ;
Link $(_t) : $(_s) ;
}
# dwa 6/4/01 - modified for boost
rule MakeLocate
{
if $(>)
{
LOCATE on $(<) = $(>) ;
# provide a way to get back the location from a built target name.
gLOCATE($(<)) = $(>) ;
# We add directory-grist here so that implicitly-created directory
# target names don't collide with user-specified targets.
Depends $(<) : [ MkDir $(>[1]:G=directory-grist) ] ;
}
}
# now returns the created directory target -- dwa
rule MkDir
{
# If dir exists, don't update it
# Do this even for $(DOT).
local dir = $(<) ;
if $(NT)
{
# make sure slashes all go the right way
dir = [ split-path $(dir) ] ;
dir = $(dir:J=$(SLASH)) ;
}
local result = $(dir) ;
while $(dir) && ( $(dir) != $(DOT) ) && ! $($(dir)-mkdir)
{
# Cheesy gate to prevent multiple invocations on same dir
# MkDir1 has the actions
# Arrange for jam dirs
$(dir)-mkdir = true ;
MkDir1 $(dir) ;
Depends dirs : $(dir) ;
NOUPDATE $(dir) ;
# Recursively make parent directories.
# $(dir:P) = $(dir)'s parent, & we recurse until root
local s = $(dir:P) ;
if $(NT)
{
switch $(s)
{
case *: : s = ;
case *:\\ : s = ;
}
}
if $(s) && $(s) != $(dir)
{
Depends $(dir) : $(s) ;
dir = $(s) ;
}
else
{
dir = ; # stop iterating
if $(s) { NOTFILE $(s) ; }
}
}
return $(result) ;
}
# dwa 6/4/01 - modified for boost
rule Object
{
local h ;
type-DEPENDS obj : $(<) ;
set-target-variables $(<) ;
# Make it possible to compile a given source file by giving its
# object file name as a target.
type-DEPENDS $(<:G=) : $(<) ;
# 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).
# Use unique to clean up confusing duplicates a bit
HDRS on $(<) = [ unique $(LOCATE_SOURCE) $(HDRS) ] ;
# Set STDHDRS on the object so that multi-compiler builds will search for
# headers in the right places.
STDHDRS on $(<) = $(STDHDRS) ;
SYSHDRS on $(<) = $(SYSHDRS) ;
# 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)$(SLASH)$(>:D) ;
}
else
{
h = $(>:D) ;
}
HDRRULE on $(>) = HdrRule ;
HDRSCAN on $(>) = $(HDRPATTERN) ;
HDRSEARCH on $(>) = $(HDRS) $(h) $(STDHDRS) $(SYSHDRS) ;
HDRGRIST on $(>) = $(HDRGRIST) ;
# if source is not .c, generate .c with specific rule
# make sure we don't generate the same object twice.
if ! $(gGENERATED_TARGET($(<)))
{
switch $(>:S)
{
case .asm : As $(<) : $(>) ;
case .c : Cc $(<) : $(>) ;
case .C : C++ $(<) : $(>) ;
case .cc : C++ $(<) : $(>) ;
case .cpp : C++ $(<) : $(>) ;
case .cxx : C++ $(<) : $(>) ;
case .f : Fortran $(<) : $(>) ;
case .s : As $(<) : $(>) ;
case * : UserObject $(<) : $(>) ;
}
gGENERATED_TARGET($(<)) = true ;
}
}
# dwa 6/4/01 - added for boost
# Return the corresponding object file target names given a list of source file
# target names.
rule object-name # sources...
{
return $(<:D=:S=$(SUFOBJ):G=$(TARGET_GRIST)) ;
}
# dwa 6/4/01 - added for boost
# Build a generated source file from input-target, and build whatever that file generates.
# Return a list of all object target names ultimately generated by recursively
# building the products of input-target.
rule gen-source # source => object-file-names
{
local suffix = .c ;
if $(<:S) in .lpp .ypp
{
suffix = .cpp ;
}
local immediate-target = $(<:D=:S=$(suffix):G=$(SOURCE_GRIST)) ;
# make sure we don't regenerate sources twice.
if ! $(gGENERATED_TARGET($(immediate-target)))
{
switch $(<:S)
{
case .l* : Lex $(immediate-target) : $(<) ; SEARCH on $(<) = $(SEARCH_SOURCE) ;
case .y* : Yacc $(immediate-target) : $(<) ; SEARCH on $(<) = $(SEARCH_SOURCE) ;
}
gGENERATED_TARGET($(immediate-target)) = true ;
}
return [ Objects $(immediate-target) ] ;
}
# dwa 6/4/01 - added for boost
# A list of all file extensions which generate source files when built.
SOURCE_GENERATING_EXTENSIONS ?= .lpp .ypp .l .y ;
# dwa 6/4/01 - modified for boost
# Build all object files generated by building $(<), and return a list of the
# names of those object file targets.
rule Objects
{
local _i _n _r ;
for _i in $(<)
{
if $(_i:S) in $(SOURCE_GENERATING_EXTENSIONS)
{
_n = [ gen-source $(_i) ] ;
}
else
{
_n = [ object-name $(_i) ] ;
Object $(_n) : $(_i) ;
}
_r += $(_n) ;
}
return $(_r) ;
}
rule RmTemps
{
TEMPORARY $(>) ;
}
rule Setuid
{
MODE on [ FAppendSuffix $(<) : $(SUFEXE) ] = 4711 ;
}
# dwa 6/4/01 - modified for boost
rule Shell
{
type-DEPENDS shell : $(<) ;
DEPENDS $(<) : $(>) ;
SEARCH on $(>) = $(SEARCH_SOURCE) ;
MODE on $(<) = $(SHELLMODE) ;
Clean clean : $(<) ;
Chmod $(<) ;
}
# dwa 6/7/01 - added for boost
# subproject path
#
# Invokes SubDir with a path description
rule subproject
{
SubDir TOP [ split-path $(<) ] ;
}
# dwa 6/18/01 - added for boost
# project-root
#
# Declares this directory to be the project root.
rule project-root ( )
{
local project-location ;
if $(gTOP)
{
project-location = [ root-paths $($(gTOP)) : [ PWD ] ] ;
}
else
{
project-location = [ PWD ] ;
}
local name ;
name = $(PROJECT($(project-location))) ;
name ?= $(project-location:B) ;
PROJECT = $(name) ;
gPROJECT($(name)) = $(project-location) ;
SubDir TOP ;
}
# grafik.
#
# Declare either your own project, or an external project.
#
rule project ( name : location ? )
{
if ! $(location)
{
gPROJECT($(name)) = $(gPROJECT($(PROJECT))) ;
PROJECT($(gPROJECT($(name)))) = $(name) ;
PROJECT = $(name) ;
}
else
{
gPROJECT($(name)) = [ root-paths $(location) : [ root-paths $($(gTOP)) : [ PWD ] ] ] ;
local [ protect-subproject ] ;
enter-subproject @$(name) ;
}
}
# grafik.
#
# Returns the set of vars to localize to prevent changes from
# affecting the current project. Also remembers the current values
# to use by enter-subproject to set the defaults for the new vars.
#
rule protect-subproject ( )
{
.TOP = $(TOP) ;
.TOP_TOKENS = $(TOP_TOKENS) ;
.gTOP = $(gTOP) ;
.PROJECT = $(PROJECT) ;
return TOP TOP_TOKENS gTOP PROJECT [ protect-subdir ] ;
}
# grafik.
#
# Sets up the environment as if the context is another project in
# preparation to include the external projects targets. This also
# works for refering to the current project.
#
rule enter-subproject ( project-path )
{
TOP = $(.TOP) ;
TOP_TOKENS = $(.TOP_TOKENS) ;
gTOP = $(.gTOP) ;
PROJECT = $(.PROJECT) ;
local project-name = [ MATCH "^@([^/\\]+)" : $(project-path) ] ;
project-name ?= $(PROJECT) ;
project-name ?= "" ;
local project-subdir = [ MATCH "^@[^/\\]+[/\\](.*)" : $(project-path) ] ;
local project-top ;
if $(project-name)
{
project-top = [ split-path $(gPROJECT($(project-name))) ] ;
if $(project-subdir)
{
project-top +=
[ split-path [ relative-path $(project-subdir) ] ]
[ split-path [ FSubDir [ split-path [ relative-path $(project-subdir) ] ] ] ] ;
}
TOP = [ join-path $(project-top) ] ;
TOP_TOKENS = $(project-top) ;
gTOP = TOP ;
PROJECT = $(project-name) ;
}
project-subdir ?= . ;
subproject $(project-subdir) ;
return $(project-name) $(project-subdir) ;
}
# dwa 6/7/01 - added for boost
# subinclude path...
#
# Invokes SubInclude for each path
rule subinclude
{
local d ;
for d in $(<)
{
SubInclude TOP [ split-path $(d) ] ;
}
}
# dwa 10/6/01 - added for boost
#
# path-global variable-name : path... ;
#
# if $(variable-name) is unset, sets variable-name to path...
# variable-name will be adjusted on a per-subproject basis to refer to the same path.
rule path-global
{
$(<) ?= $(>) ;
gPATH_GLOBAL_VALUE($(<)) = $($(<)) ;
if ! ( $(<) in $(gPATH_GLOBALS) )
{
gPATH_GLOBALS += $(<) ;
}
}
# dwa 6/4/01 - modified for boost
rule SubDir
{
local _r ;
#
# 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 ;
}
$(<[1]) = [ FSubDir $(<[2-]) ] ;
$(<[1])_TOKENS = [ split-path $($(<[1])) ] ;
gTOP = $(<[1]) ; # not sure why someone would want to use anything
# other than TOP, but just in case...
}
#
# If $(TOP)/Jamrules hasn't been included, do so.
#
local top = [ root-paths $($(gTOP)) : [ PWD ] ] ;
if ! $(gINCLUDED($(JAMRULES:R=$(top))))
{
# Gated entry.
gINCLUDED($(JAMRULES:R=$(top))) = TRUE ;
# Include it.
project-root ;
include $(JAMRULES:R=$(top)) ;
}
# Get path to current directory from root using SubDir.
# Save dir tokens for other potential uses.
SUBDIR_TOKENS = $(<[2-]) ;
# This allows us to determine whether we're in the directory where jam was
# invoked from so that we can make locally named targets
gINVOCATION_SUBDIR_TOKENS ?= $(SUBDIR_TOKENS) ;
gINVOCATION_SUBDIR_TOKENS ?= $(DOT) ;
# SUBDIR is the path from the invocation directory to the subproject
# directory.
SUBDIR = [ tokens-to-simple-path $($(gTOP)_TOKENS) $(SUBDIR_TOKENS) ] ;
SEARCH_SOURCE = $(SUBDIR) ;
# This will strip off any leading dot on SUBDIR_TOKENS
local nodot_subdir = [ simplify-path-tokens $(SUBDIR_TOKENS) ] ;
if $(ALL_LOCATE_TARGET) && ! $(first_ALL_LOCATE_TARGET)
{
normalized_ALL_LOCATE_TARGET = [ join-path $($(gTOP)) $(ALL_LOCATE_TARGET) ] ;
}
else
{
normalized_ALL_LOCATE_TARGET ?= [ join-path $($(gTOP)) $(ALL_LOCATE_TARGET) ] ;
}
first_ALL_LOCATE_TARGET ?= $(ALL_LOCATE_TARGET) ;
LOCATE_SOURCE = [ FDirName $(normalized_ALL_LOCATE_TARGET) $(BIN_DIRECTORY) $(PROJECT) $(nodot_subdir) ] ;
LOCATE_TARGET = $(LOCATE_SOURCE) ;
HCACHEFILE = [ FDirName $(normalized_ALL_LOCATE_TARGET) $(BIN_DIRECTORY) .jamdeps ] ;
SOURCE_GRIST = [ FGrist @$(PROJECT) $(SUBDIR_TOKENS) ] ;
# Reset per-directory ccflags, hdrs
SUBDIRCCFLAGS = ;
SUBDIRC++FLAGS = ;
# This variable holds the path from the directory of Jam's invocation to the
# directory of the current subproject.
RELATIVE_SUBDIR_TOKENS = [ simplify-path-tokens $($(gTOP)_TOKENS) $(SUBDIR_TOKENS) : $(DOT) ] ;
RELATIVE_SUBDIR = [ join-path $(RELATIVE_SUBDIR_TOKENS) ] ;
adjust-path-globals ;
}
rule in-invocation-subdir
{
local subdir-tokens = $(SUBDIR_TOKENS) ;
subdir-tokens ?= $(DOT) ;
if $(subdir-tokens) = $(gINVOCATION_SUBDIR_TOKENS)
{
return true ;
}
}
# These are the global variables that get set up by SubDir. If you need to
# invoke SubDir temporarily and then restore them, declare
# local $(gSUBDIR_GLOBALS) ;
gSUBDIR_GLOBALS = SUBDIR SUBDIR_TOKENS SEARCH_SOURCE LOCATE_SOURCE LOCATE_TARGET
SOURCE_GRIST RELATIVE_SUBDIR RELATIVE_SUBDIR_TOKENS ;
rule protect-subdir
{
return $(gSUBDIR_GLOBALS) $(gPATH_GLOBALS) ;
}
# prepends root to any unrooted elements of paths, and simplifies
rule root-paths ( paths * : root )
{
local path result ;
for path in $(paths)
{
local rooted = $(path:R=$(root)) ;
path = [ tokens-to-simple-path [ split-path $(rooted:G=) ] ] ;
path = $(path:G=$(rooted:G)) ;
result += $(path) ;
}
return $(result) ;
}
# Adjust all path globals so that they are relative to the current subproject.
rule adjust-path-globals
{
# compute path tokens from current subproject to root
local tokens-to-root = [ split-path [ FSubDir $(SUBDIR_TOKENS) ] ] ;
# compute path tokens from current subproject to invocation
# directory. $(DOT) is added just in case we're building from the project
# root
local tokens-to-invocation
= $(tokens-to-root) $(gINVOCATION_SUBDIR_TOKENS) ;
local variable ;
for variable in $(gPATH_GLOBALS)
{
local paths = $(gPATH_GLOBAL_VALUE($(variable))) ;
$(variable) = ;
local path ;
for path in $(paths)
{
# is path already rooted?
if $(path:R=x) = $(path)
{
$(variable) += $(path) ;
}
else
{
local tokens = $(tokens-to-invocation) [ split-path $(path) ] ;
$(variable) += [ tokens-to-simple-path $(tokens) ] ;
}
}
}
}
# dwa 6/4/01 - added for boost
# strip-grist value
#
# strip all leading gristed elements from value and return the result.
rule strip-grist
{
local x = $(<:G=) ;
if ! $(x:G)
{
return $(x) ;
}
else
{
return [ strip-grist $(x) ] ;
}
}
# dwa 6/4/01 - added for boost
# Breaks $(<) into path components
# This could certainly be improved now that we have David Turner's regular expression features.
#
# split-path <foo>bar/<bee>baz/mumble => <foo>bar <bee>baz mumble
rule split-path
{
local result = $(gSPLIT-PATH.$(<)) ;
if ! $(result)
{
local parent = $(<:P) ;
if $(NT)
{
switch $(<:G=)
{
# It turns out that to match a backslash, you need a /quadruple/ slash
# in the case clause!
case *\\\\*:* : # continue splitting
case *:\\\\*\\\\* : # continue splitting
case *:/*\\\\* : # continue splitting
case *:\\\\*/* : # continue splitting
case *:/*/* : # continue splitting
case *:/* : result = $(<) ;
case *:\\\\* : result = $(<) ;
case *: : result = $(<) ;
}
}
if ( ! $(<:B) ) && ( $(<) != $(DOT) ) # handle the case where $(<) is all grist.
{
result ?= $(<:G) ;
}
else if ( ! $(parent:G=) )
{
result ?= $(<) ;
}
else
{
local p = [ split-path $(parent) ] ;
local b = [ strip-grist $(<) ] ;
p += $(b:D=) ; # can't use :B here because it destroys . and ..
result ?= $(p) ;
}
gSPLIT-PATH.$(<) = $(result) ;
}
return $(result) ;
}
rule split ( string separator )
{
local result ;
local s = $(string) ;
while $(s)
{
local match = [ MATCH ^(.*)$(separator)(.*) : $(s) ] ;
local tail = $(match[2]) ;
tail ?= $(s) ;
result = $(tail) $(result) ;
s = $(match[1]) ;
}
return $(result) ;
}
rule split-path ( path )
{
if ! $(gSPLIT_PATH_CACHE($(path)))
{
gSPLIT_PATH_CACHE($(path)) =
[ MATCH "^([/$(SLASH)]+).*" : $(path) ] # rooting slash(es), if any
[ split $(path) "[/$(SLASH)]" ] # the rest.
;
}
return $(gSPLIT_PATH_CACHE($(path))) ;
}
# dwa 6/4/01 - added for boost
# reverse item1 item2...
#
# Returns ...item2 item1
rule reverse
{
local result ;
for x in $(<)
{
result = $(x) $(result) ;
}
return $(result) ;
}
# dwa 6/28/01 - added for boost
# strip-initial tokens... : input
#
# if input begins with tokens, remove the initial sequence of tokens and return
# the rest. Otherwise return input unchanged.
rule strip-initial
{
local result = $(>) ;
local t ;
local matched = true ;
for t in $(<)
{
if $(matched) && ( $(t) = $(result[1]) )
{
result = $(result[2-]) ;
}
else
{
matched = ;
result = $(>) ;
}
}
return $(result) ;
}
# dwa 6/4/01 - added for boost
# simplify-path-tokens token1 token2 ... tokenN : DOT-opt
#
# Remove redundant information from the given path elements
# if DOT-opt is supplied, empty results are replaced with
# $(DOT-opt).
#
# [ simplify-path-tokens a b . c .. .. d e ] => a d e
# [ simplify-path-tokens a b .. .. .. d e ] => .. d e
# [ simplify-path-tokens .. .. d e : xxx ] => .. .. d e (provided TOP != ../..)
# [ simplify-path-tokens a b .. .. : xxx ] => xxx
rule simplify-path-tokens
{
local reverse-path = [ reverse $(<) ] ;
local dotdots ;
local result ;
local token ;
for token in $(reverse-path)
{
if $(token) = $(DOT)
{
}
else if $(token) = $(DOTDOT)
{
dotdots += $(token) ;
}
else if $(dotdots)
{
dotdots = $(dotdots[2-]) ;
}
else
{
result = $(token) $(result) ;
}
}
result = $(dotdots) $(result) ;
result = [ strip-initial $($(gTOP)_TOKENS) $(gINVOCATION_SUBDIR_TOKENS) : $(result) ] ;
result ?= $(>) ;
return $(result) ;
}
rule tokens-to-simple-path
{
return [ FDirName [ simplify-path-tokens $(<) ] ] ;
}
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]) ;
}
_s = [ FDirName $(<[2-]) ] ;
# protect variables from being permanently set by SubDir invocations
# in included files.
local project = $(PROJECT) ;
local [ protect-subdir ] ;
PROJECT = $(project) ;
local jamfile-path
= [ tokens-to-simple-path
[ split-path $(JAMFILE:D=$(_s):R=$($(<[1]))) ] ] ;
load-jamfiles $(jamfile-path) ;
}
# Load a user's Jamfile(s).
#
rule load-jamfiles ( jamfiles * )
{
# First we load the Jamfiles without generation of main targets so that
# dependencies are preloaded. Then we reload the files with target
# generation enabled.
local jamfile ;
local as-dependant = $(gIN_LIB_INCLUDE) ;
local gIN_LIB_INCLUDE ;
gIN_LIB_INCLUDE = TRUE ;
for jamfile-path in $(jamfiles)
{
if ! $(gINCLUDED_AS_DEPENDANT($(jamfile-path)))
{
gINCLUDED_AS_DEPENDANT($(jamfile-path)) = TRUE ;
include $(jamfile-path) ;
}
}
if ! $(as-dependant)
{
gIN_LIB_INCLUDE = ;
for jamfile-path in $(jamfiles)
{
if ! $(gINCLUDED($(jamfile-path)))
{
gINCLUDED($(jamfile-path)) = TRUE ;
include $(jamfile-path) ;
}
}
}
}
rule Undefines
{
UNDEFS on [ FAppendSuffix $(<) : $(SUFEXE) ] += $(UNDEFFLAG)$(>) ;
}
rule UserObject
{
EXIT "Unknown suffix on" $(>) "- see UserObject rule in Jamfile(5)." ;
}
# dwa 6/4/01 - modified for boost
rule Yacc
{
local _h ;
# Can't just replace .cpp with .h, because bison seems to generate a .cpp.h file
_h = $(<).h ;
# Some places don't have a yacc.
MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ;
SEARCH on $(<) $(_h) = $(LOCATE_SOURCE) ;
if $(YACC)
{
DEPENDS $(<) $(_h) : $(>) ;
# if YACC can accept an output file, we'll just generate the file there.
YACCFILES on $(<) $(_h) = [ join-path $(LOCATE_SOURCE) $(<[1]) ] ;
Yacc1 $(<) $(_h) : $(>) ;
if ! $(YACC_OUTPUT)
{
YaccMv $(<) $(_h) : $(>) ;
}
Clean clean : $(<) $(_h) ;
}
# make sure someone includes $(_h) else it will be
# a deadly independent target
INCLUDES $(<) : $(_h) ;
}
rule remember-binding ( target : bound-path ) {
gBINDING($(target)) = $(bound-path) ;
}
#
# Utility rules; no side effects on these
#
rule FGrist
{
# Turn individual elements in $(<) into grist.
local _g _i ;
_g = $(<[1]) ;
for _i in $(<[2-])
{
_g = $(_g)!$(_i) ;
}
return $(_g) ;
}
rule FGristFiles
{
if ! $(SOURCE_GRIST)
{
return $(<) ;
}
else
{
return $(<:G=$(SOURCE_GRIST)) ;
}
}
# dwa 6/4/01 - modified for boost
rule FGristSourceFiles
{
# Produce source file name name with grist in it,
# if SOURCE_GRIST is set.
# Leave header files alone, because they have a global
# visibility.
if ! $(SOURCE_GRIST)
{
return $(<) ;
}
else
{
local _i _o ;
for _i in $(<)
{
switch $(_i)
{
case *.h : _o += $(_i) ;
case *.hpp : _o += $(_i) ;
case * : _o += $(_i:G=$(SOURCE_GRIST)) ;
}
}
return $(_o) ;
}
}
# dwa 6/4/01 - modified for boost
# join values... : [separator]
#
# Pastes values together into a single list element, separated by an optional separator.
rule join ( values * : sep ? )
{
sep ?= "" ;
return $(values:J=$(sep)) ;
}
# Given $(<), the tokens comprising a relative path from D1 to a subdirectory
# D2, return the relative path from D2 to D1, using ../../ etc.
rule FSubDir
{
local _d ;
if ! $(<[1])
{
_d = $(DOT) ;
}
else
{
_d = $(DOTDOT) ;
local _i ;
for _i in $(<[2-])
{
_d = $(_d:R=$(DOTDOT)) ;
}
}
return $(_d) ;
}
# dwa 6/4/01 - added for boost
# Turn individual elements in $(<) into a usable path. If $(<) is empty, $(>) is
# returned.
rule join-path
{
local _s _i ;
if ! $(<)
{
_s = $(>) ;
}
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]) ;
local _r = $(<[2-]) ;
# Jam doesn't handle the root directory properly
if $(_s) in / $(SLASH)
{
_s = $(_s)$(_r[1]) ;
_r = $(_r[2-]) ;
}
for _i in $(_r)
{
_s = $(_i:R=$(_s)) ;
}
}
return $(_s) ;
}
# dwa 6/4/01 - modified for boost
rule FDirName
{
# Turn individual elements in $(<) into a usable path.
return [ join-path $(<) : $(DOT) ] ;
}
rule _makeCommon
{
# strip common initial elements
if $($(<)[1]) && $($(<)[1]) = $($(>)[1])
{
$(<) = $($(<)[2-]) ;
$(>) = $($(>)[2-]) ;
_makeCommon $(<) : $(>) ;
}
}
rule FRelPath
{
local _l _r ;
# first strip off common parts
_l = $(<) ;
_r = $(>) ;
_makeCommon _l : _r ;
# now make path to root and path down
_l = [ FSubDir $(_l) ] ;
_r = [ FDirName $(_r) ] ;
# Concatenate and save
# XXX This should be better
if $(_r) = $(DOT) {
return $(_l) ;
} else {
return $(_r:R=$(_l)) ;
}
}
# dwa 6/17/01 - modified for boost to handle multiple suffixes
rule FAppendSuffix
{
# E.g., "FAppendSuffix yacc lex foo.bat : $(SUFEXE) ;"
# returns (yacc,lex,foo.bat) on Unix and
# (yacc.exe,lex.exe,foo.bat) on NT.
if $(>)
{
local _i _o ;
for _i in $(<)
{
if $(_i:S)
{
_o += $(_i) $(_i:S=$(>[2-])) ;
}
else
{
_o += $(_i:S=$(>)) ;
}
}
return $(_o) ;
}
else
{
return $(<) ;
}
}
rule unmakeDir
{
if $(>[1]:D) && $(>[1]:D) != $(>[1]) && $(>[1]:D) != \\\\
{
unmakeDir $(<) : $(>[1]:D) $(>[1]:BS) $(>[2-]) ;
}
else
{
$(<) = $(>) ;
}
}
#
# Actions
#
#
# First the defaults
#
actions As
{
$(AS) $(ASFLAGS) -I$(HDRS) -o $(<) $(>)
}
actions Chgrp
{
chgrp $(GROUP) $(<)
}
actions Chmod1
{
$(CHMOD) $(MODE) "$(<)"
}
actions Chown
{
chown $(OWNER) $(<)
}
actions piecemeal together existing Clean
{
$(RM) "$(>)" $(NULL_OUT)
}
actions File
{
$(CP) "$(>)" "$(<)" $(NULL_OUT)
}
actions FileClone
{
$(CLONE) "$(>)" "$(<)" $(NULL_OUT)
}
actions GenFile1
{
$(>[1]) $(<) $(>[2-])
}
actions Fortran
{
$(FORTRAN) $(FORTRANFLAGS) -o $(<) $(>)
}
actions HardLink
{
$(RM) "$(<)" 2$(NULL_OUT) $(NULL_OUT)
$(LN) "$(>)" "$(<)" $(NULL_OUT)
}
actions Install
{
$(CP) $(>) $(<)
}
# dwa 6/4/01 - modified for boost
actions together Lex
{
$(LEX) $(LEXFLAGS) $(LEX_OUTPUT)$(<) $(>)
}
# dwa 6/4/01 - modified for boost
actions together LexMv
{
$(MV) lex.yy.c $(<)
}
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 }
' < $(>) > $(<)
}
# dwa 6/4/01 - modified for boost
actions together Yacc1
{
$(YACC) $(YACCFLAGS) $(YACC_OUTPUT)$(<[1]) $(>)
}
# dwa 6/4/01 - modified for boost
actions together YaccMv
{
$(MV) $(YACCFILES).c $(<[1])
$(MV) $(YACCFILES).h $(<[2])
}
# dwa 6/4/01 - killed all platform-specific actions for boost
# dwa 6/4/01 - modified for boost
actions together Yacc-fix-line-directives
{
$(YACC_FIX_LINES) $(<) > $(<)
}