Jambase #3

  • //
  • guest/
  • dick_dunbar/
  • jam/
  • src/
  • Jambase
  • View
  • Commits
  • Open Download .zip Download (43 KB)
#
# /+\
# +\    Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
# \+/
  JAMBASEDATE = 2004.07.24 ;
#
# This file is part of Jam - see jam.c for Copyright information.
# 05/17/04 (dunbar)- Support for Siebel 
#
#
# JAMBASE - jam 2.5 ruleset providing make(1)-like functionality
#
# 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 and Actions defined by this file:
#
# Archive lib : source ;                archive library from compiled sources
# ArchiveFromObjects lib : objects ;    archive library from objects
# 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
# 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 ;                shared library from compiled sources
# LibraryFromObjects lib : objects ;    shared 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
# ObjectDefines
# ObjectHdrs source : dirs ;            add include directories for object
# Objects sources ;                     compile sources
# Resource  xxx : yyy ;                 resource compiler
# RmTemps target : sources ;            remove temp sources after target made
# Setuid images ;                       mark executables Setuid
# Shell exe : source ;                  make a shell executable
# SoftLink target : source ;            make symlink from source to target
# 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 d1 d2 ... ;                add include dir until next SubDir
# SubInclude TOP d1 d2 ... ;            include a subdirectory Jamfile
# SubRules
# 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
# Fdefines
# 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))
# FStripCommon v1 : v2 ;                strip common initial parts of v1 v2
# FSubDirPath
# FReverse a1 a2 ... ;                  return ... a2 a1
# FRelPath d1 : d2 ;                    return rel path from d1 to d2
# FSubDir d1 d2 ... ;                   return path to root
# FDefines
# FIncludes
# FQuote

# 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.5)
#
# 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
#
if $(NT) {
        MV              ?= move /y ;
        CP              ?= xcopy ;
        RM              ?= del /f/q ;
        RMDIR           ?= rmdir /s/q ;
        SLASH           ?= \\ ;
        SUFDLL          ?= .dll ;
        SUFLIB          ?= .lib ;
        SUFOBJ          ?= .obj ;
        SUFEXE          ?= .exe ;
     if $(MSVCDIR) { # Visual C++ 6.0 uses MSVCDIR
        AR              ?= lib ;
        AS              ?= masm386 ;
        CC              ?= $(MSVCDIR)\\bin\\cl /nologo ;             
        CCFLAGS         ?= "" ;
        C++             ?= $(CC) ;
        C++FLAGS        ?= $(CCFLAGS) ;
        LIBDIR          ?= $(MSVCDIR)\\lib ;
        LIBFLAGS        ?= "" ;
        LINK            ?= $(MSVCDIR)\\bin\\link /nologo ;            
        LINKFLAGS       ?= "" ;
        LINKLIBS        ?= $(LIBDIR)\\kernel32.lib $(LIBDIR)\\oldnames.lib ;
        OPTIM           ?= "" ;
        RC              ?= rc ;
        STDHDRS         ?= $(MSVCDIR)\\include ;
        UNDEFFLAG       ?= "/u _" ;
    } else if $(DMCDIR) {
        CC              ?= $(DMCDIR)\\bin\\dmc.exe ;
        CCFLAGS         ?= "" ;
        C++             ?= $(CC) ;
        C++FLAGS        ?= $(CCFLAGS) ;
        LIBDIR          ?= $(DMCDIR)\\lib ;
        LIBFLAGS        ?= "" ;
        LINK            ?= $(DMCDIR)\\bin\\link /nologo ;
        LINKFLAGS       ?= "" ;
        LINKLIBS        ?= $(DMCDIR)\\lib\\kernel32.lib $(DMCDIR)\\lib\\oldnames.lib ;
        OPTIM           ?= "" ;
        RC              ?= "" ;
        STDHDRS         ?= $(DMCDIR)\\Include ;
        UNDEFFLAG       ?= "-u " ;
    } else {
        Echo set MSVCDIR=d:\\progra~1\\micros~1\\vc98 ;
        EXIT On NT, set MSVCDIR to the root of the Microsoft directories. ;
    }
} else if $(UNIX) {
    switch $(OS) {
    case AIX :
        CC              ?= xlc_r ;
        C++             ?= xlC_r ;
        LIBFLAGS        ?= "-qmkshrobj -qtwolink -G -bnoerok -bf" ;
    case HPUX :
        RANLIB          ?= "" ;
    case SOLARIS :
        CC              ?= /opt/SUNWspro/bin/cc ;
        C++             ?= /opt/SUNWspro/bin/CC ;
        RANLIB          ?= "" ;
        AR              ?= "/usr/ccs/bin/ar ru" ;
    }
    # UNIX defaults
    CCFLAGS         ?= ;
    C++FLAGS        ?= $(CCFLAGS) ;
    CHMOD           ?= chmod ;
    CHGRP           ?= chgrp ;
    CHOWN           ?= chown ;
    LEX             ?= lex ;
    LINKFLAGS       ?= $(CCFLAGS) ;
    LINKLIBS        ?= ;
    OPTIM           ?= -O ;
    RANLIB          ?= ranlib ;
    YACC            ?= yacc ;
    YACCGEN         ?= .c ;
    YACCFILES       ?= y.tab ;
    YACCFLAGS       ?= -d ;
    }
#
# General defaults; a lot like UNIX
#
    AR              ?= ar ru ;
    AS              ?= as ;
    ASFLAGS         ?= ;
    AWK             ?= awk ;
    BINDIR          ?= /usr/local/bin ;
    C++             ?= cc ;
    C++FLAGS        ?= ;
    CC              ?= cc ;
    CCFLAGS         ?= ;
    CP              ?= cp -f ;
    DOT             ?= . ;
    DOTDOT          ?= .. ;
    EXEFLAGS        ?= ;
    EXEMODE         ?= 755 ;
    FILEMODE        ?= 644 ;
    HDRS            ?= ;
    INSTALLGRIST    ?= installed ;
    JAMFILE         ?= Jamfile ;
    JAMRULES        ?= Jamrules ;
    LEX             ?= ;
    LIBDIR          ?= /usr/local/lib ;
    LINK            ?= $(C++) ;                         # ?? $(CC) Linking is compiler dependent.
    LINKFLAGS       ?= ;
    LINKLIBS        ?= ;
    LN              ?= ln ;
    MANDIR          ?= /usr/local/man ;
    MKDIR           ?= mkdir ;
    MV              ?= mv -f ;
    OPTIM           ?= ;
    OSFULL           = $(OS)$(OSVER)$(OSPLAT) ;
    RCP             ?= rcp ;
    RM              ?= rm -f ;
    RMDIR           ?= $(RM) ;
    RSH             ?= rsh ;
    SED             ?= sed ;
    SHELLHEADER     ?= "#!/bin/sh" ;
    SHELLMODE       ?= 755 ;
    SLASH           ?= / ;
    STDHDRS         ?= /usr/include ;
    SUBDIRRULES     ?= ;
    SUBDIRRESET     ?= ASFLAGS HDRS C++FLAGS CCFLAGS DEFINES ;    # There is no SUBDIRDEFINES ??
    SUFEXE          ?= "" ;
    SUFDLL          ?= .so ;                            # MS centric. Unix uses .so suffix
    SUFLIB          ?= .so ;                            # MS has .lib and .dll
    SUFOBJ          ?= .o ;
    UNDEFFLAG       ?= "-u _" ;
    YACC            ?= ;
    YACCGEN         ?= ;
    YACCFILES       ?= ;
    YACCFLAGS       ?= ;
# Caution: HDRPATTERN contains 3 <blank><tab>  char sequences.  Do not remove/expand tabs.
    HDRPATTERN = "^[ 	]*#[ 	]*include[ 	]*[<\"]([^\">]*)[\">].*$" ;
#   HDRPATTERN = "^[ T]*#[ T]*include[ T]*[<\"]([^\">]*)[\">].*$" ;  (tabs (\t) shown as "T"

# Base dependencies - first for "bootstrap" kinds of rules ;
NotFile all clean dirs exe files first lib obj shell uninstall ;
Depends all : exe lib files obj shell ;
Depends all   exe lib files obj shell : first ;
Always clean uninstall ;

#
# Rules
#

rule    Archive {
        ArchiveFromObjects $(<) : $(>:S=$(SUFOBJ)) ; # :Suffix
        Objects $(>) ;
        }
rule    ArchiveFromObjects {
        local _file _lib _src ;
        _src = [ FGristFiles $(>) ] ;              # Add grist to file names
        _lib = $(<:S=$(SUFLIB)) ;                  # Archive :Suffix
        if $(KEEPOBJS) { Depends obj : $(_src) ; # library depends on its member objects
        } else         { Depends lib : $(_lib) ; }
        if ! $(_lib:D) { MakeLocate $(_lib) $(_lib)($(_src:BS)) : $(LOCATE_TARGET) ; } # :Base/:Suffix/:Directory
        if $(NOARSCAN) {
            Depends $(_lib) : $(_src) ;
        } else {
            Depends $(_lib) : $(_lib)($(_src:BS)) ;   # :Base/:Suffix
            for _file in $(_src) {
                Depends $(_lib)($(_file:BS)) : $(_file) ;   # :Base/:Suffix
                }
            }
        Clean clean : $(_lib) ;
        FArchive $(_lib) : $(_src) ;
        if $(RANLIB) { Ranlib $(_lib) ; }
        if ! ( $(NOARSCAN) || $(NOARUPDATE) ) { RmTemps $(_lib) : $(_src) ; }
        }
actions updated together piecemeal FArchive { $(AR) $(<) $(>) }
actions together Ranlib { $(RANLIB) $(<) }
rule    As {
        Depends $(<) : $(>) ;
        ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
        ASHDRS on $(<) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
        }
actions As       { $(AS) $(ASFLAGS) $(ASHDRS) -o $(<) $(>) }
rule    Bulk {
        local _file ;
        for _file in $(>) {
            File $(_file:D=$(<)) : $(_file) ;            # :Directory
            }
        }
rule    Cc {
        Depends $(<) : $(>) ;
        # Just to clarify here: this sets the per-target CCFLAGS to
        # be the current value of (global) CCFLAGS and SUBDIRCCFLAGS.
        # CCHDRS and CCDEFS must be reformatted each time for some
        # compiles (NT) that malign multiple -D or -I flags.
        CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) $(OPTIM) ;
        CCHDRS  on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
        CCDEFS  on $(<) = [ on $(<) FDefines  $(DEFINES) ] ;
        }
actions Cc       { $(CC)  $(CCFLAGS)  $(CCDEFS) $(CCHDRS) $(>) -c -o $(<) }
rule    C++ {
        Depends $(<) : $(>) ;
        C++FLAGS on $(<) += $(C++FLAGS) $(SUBDIRC++FLAGS) $(OPTIM) ;
        CCHDRS   on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
        CCDEFS   on $(<) = [ on $(<) FDefines  $(DEFINES) ] ;
        }
actions C++      { $(C++) $(C++FLAGS) $(CCDEFS) $(CCHDRS) $(>) -c -o $(<) }
rule    C++Flags { C++FLAGS += $(<) ; }
actions Chgrp    { $(CHGRP) $(GROUP) $(<) }
rule    Chmod    { if $(CHMOD) { Chmod1 $(<) ; } }
actions Chmod1   { $(CHMOD) $(MODE) $(<) }
actions Chown    { $(CHOWN) $(OWNER) $(<) }
actions piecemeal together existing Clean { $(RM) $(>) }  # ??
rule    Defines { DEFINES += $(<) ; }
rule    File {
        Depends files : $(<) ;
        Depends $(<) : $(>) ;
        SEARCH on $(>) = $(SEARCH_SOURCE) ;
        MODE   on $(<) = $(FILEMODE) ;
        Chmod $(<) ;
        }
actions File     { $(CP) "$(>)" $(<) }                       
rule    GenFile {
        local _tgt = [ FGristSourceFiles $(<) ] ;
        local _src = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;
        Depends  $(_tgt) : $(_src) $(>[2-]) ;
        GenFile1 $(_tgt) : $(_src) $(>[2-]) ;
        Clean clean : $(_tgt) ;
        }
rule    GenFile1 {
        MakeLocate $(<) : $(LOCATE_SOURCE) ;
        SEARCH on  $(>) = $(SEARCH_SOURCE) ;
        }
actions GenFile1 { PATH="$PATH:." $(>[1]) $(<) $(>[2-]) }
rule    HardLink {
        Depends files : $(<) ;
        Depends $(<) : $(>) ;
        SEARCH on $(>) = $(SEARCH_SOURCE) ;
        }
actions HardLink { $(RM) $(<) && $(LN) $(>) $(<) }
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 _hdr = $(>:G=$(HDRGRIST:E)) ;               # :Grist/:Value
        Includes $(<) : $(_hdr) ;
        SEARCH on $(_hdr) = $(HDRSEARCH) ;
        NoCare $(_hdr) ;
        # Propagate on $(<) to $(>)
        HDRSEARCH on $(_hdr) = $(HDRSEARCH) ;
        HDRSCAN   on $(_hdr) = $(HDRSCAN) ;
        HDRRULE   on $(_hdr) = $(HDRRULE) ;
        HDRGRIST  on $(_hdr) = $(HDRGRIST) ;
        }
actions Install  { $(CP) $(>) $(<) }
rule    InstallInto {            # InstallInto dir : sources ;
        local _src _sfile _tfile ;
        _src = $(>:G=$(INSTALLGRIST)) ;                   # :Grist
        # Arrange for jam install
        # Arrange for jam uninstall
        # sources are in SEARCH_SOURCE
        # targets are in dir
        Depends install : $(_src) ;
        Clean uninstall : $(_src) ;
        SEARCH on $(>) = $(SEARCH_SOURCE) ;
        MakeLocate $(_src) : $(<) ;
        # For each source, make gristed target name
        # and Install, Chmod, Chown, and Chgrp
        for _sfile in $(>) {
            _tfile = $(_sfile:G=$(INSTALLGRIST)) ;        # :Grist
            Depends $(_tfile) : $(_sfile) ;
            Install $(_tfile) : $(_sfile) ;
            Chmod $(_tfile) ;
            if $(OWNER) && $(CHOWN) {
                Chown    $(_tfile) ;
                OWNER on $(_tfile) = $(OWNER) ;
                }
            if $(GROUP) && $(CHGRP) {
                Chgrp    $(_tfile) ;
                GROUP on $(_tfile) = $(GROUP) ;
                }
            }
        }
rule    InstallBin {
        local _tgt = [ FAppendSuffix $(>) : $(SUFEXE) ] ;
        InstallInto $(<) : $(_tgt) ;
        MODE on $(_tgt:G=$(INSTALLGRIST)) = $(EXEMODE) ; # :Grist
        }
rule    InstallFile {
        InstallInto $(<) : $(>) ;
        MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ; # :Grist
        }
rule    InstallLib {
        InstallInto $(<) : $(>) ;
        MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ; # :Grist
        }
rule    InstallMan {       # This just strips the . from the suffix
        local _file _suf _dir ;
        for _file in $(>) {
            switch $(_file:S) {                   # :Suffix
              case .1 : _suf = 1 ; case .2 : _suf = 2 ; case .3 : _suf = 3 ;
              case .4 : _suf = 4 ; case .5 : _suf = 5 ; case .6 : _suf = 6 ;
              case .7 : _suf = 7 ; case .8 : _suf = 8 ; case .l : _suf = l ;
              case .n : _suf = n ; case .man : _suf = 1 ;
              }
            _dir = man$(_suf) ;
            InstallInto $(_dir:R=$(<)) : $(_file) ;                   # :Root
            }
        MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ; # :Grist
        }
rule    InstallShell {
        InstallInto $(<) : $(>) ;
        MODE on $(>:G=$(INSTALLGRIST)) = $(SHELLMODE) ; # :Grist
        }
rule    Lex {
        LexMv   $(<) : $(>) ;
        Depends $(<) : $(>) ;
        MakeLocate $(<) : $(LOCATE_SOURCE) ;
        Clean clean : $(<) ;
        }
actions Lex      { $(LEX) $(>) }
actions LexMv    { $(MV) lex.yy.c $(<) }
rule    Library {
        LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ; # :Suffix
        Objects $(>) ;
        LINKFLAGS += $(LIBFLAGS) ;
        }
# AIX example
#     xlC_r -G -qmkshrobj -g  shared.o -o libshared1.so -ldl
# Note: -G is combo flag for: erok, rtl, nortllib, nosymbolic, noautoexp, and M:SRE

rule    LibraryFromObjects {
        local _loc _src _lib _dll _file ;      # _src: sources
        _src   = [ FGristFiles $(>) ] ;        # Add grist to file names
        _lib = $(<:S=$(SUFLIB)) ;              # Library :Suffix  (.dll on windows, .so on unix)
        _dll = $(<:S=$(SUFDLL)) ;              # Library :Suffix  (.lib on windows, .so / .a on unix)
        if $(KEEPOBJS) { Depends obj : $(_src) ; # library depends on its member objects
        } else         { Depends lib : $(_lib) ; }
        # 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 ! $(_lib:D) {
             _loc = [ FDirName $(LOCATE_TARGET) ] ;
             MakeLocate $(_lib) $(_lib)($(_src:BS)) : $(_loc) ;
             } # :Base/:Suffix/:Directory
        Depends $(_lib) : $(_src) ;
        Depends $(_lib) : $(_lib)($(_src:BS)) ;
        for _file in $(_src) {
            Depends $(_lib)($(_file:BS)) : $(_file) ;
            }
        Clean clean : $(_lib) ;
        Link    $(_lib) : $(_src) ;
#       RmTemps $(_lib) : $(_src) ;      # Breaks incremental builds on win32 (probably AIX too)
        }
rule    LibFlags { LIBFLAGS += $(<) ; }
rule    Libs {
        # make library dependencies of target
        # set NEEDLIBS variable used by 'actions Main' / 'actions Library'
        local _exe = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
        Depends     $(_exe) :  $(>:S=$(SUFLIB)) ;   # :Suffix
        NEEDLIBS on $(_exe) += $(>:S=$(SUFLIB)) ;   # :Suffix
        }
rule    Link {
        MODE on $(<) = $(EXEMODE) ;
        Chmod   $(<) ;
        }
actions Link bind NEEDLIBS { $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) }
rule    LinkFlags { LINKFLAGS += $(<) ; }
rule    Main {
        LINKFLAGS += $(LIBFLAGS) ;                              # Siebel
        MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ; # :Suffix
        Objects $(>) ;
        }
rule    MainFromObjects {
        local _src _tgt _loc _i ;
        # Add grist to file names
        # Add suffix to exe
        _src = [ FGristFiles $(>) ] ;
        _tgt = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
        # so 'jam foo' works when it's really foo.exe
        if $(_tgt) != $(<) {
            Depends $(<) : $(_tgt) ;
            NotFile $(<) ;
            }
        # make compiled sources a dependency of target
        if ! $(_tgt:D) {                                      
           _loc = [ FDirName $(LOCATE_TARGET) ] ;
           MakeLocate $(_tgt) $(_tgt)($(_src:BS)) : $(_loc) ;
           }   # :Base/:Suffix/:Directory
        Depends exe : $(_tgt) ;
        Depends $(_tgt) : $(_src) ;
        Depends $(_tgt) : $(_tgt)($(_src:BS)) ;               
        for _i in $(_src) {                                   # Why? Difference from line above??
            Depends $(_tgt)($(_i:BS)) : $(i) ;
            }
        MakeLocate $(_tgt) : $(LOCATE_TARGET) ;               # Link2 Windows(no effect) AIX(needed) ??
        Clean clean   : $(_tgt) ;
        Link2 $(_tgt) : $(_src) ;
        }
rule    MakeLocate {           # MakeLocate targets : directory ;
        # Sets special variable LOCATE on targets, and arranges
        # with MkDir to create target directory.
        # Note we grist the directory name with 'dir',
        # so that directory path components and other
        # targets don't conflict.
        if $(>) {
            LOCATE on $(<) = $(>) ;
            Depends $(<) : $(>[1]:G=dir) ;             # :Grist
            MkDir $(>[1]:G=dir) ;                      # :Grist
            }
        }
rule    MkDir {                     # MkDir directory ;
        # Make a directory and all its parent directories.
        # Ignore timestamps on directories: we only care if they
        # exist.
        NoUpdate $(<) ;
        # Don't create . or any directory already created.
        if $(<:G=) != $(DOT) && ! $($(<)-mkdir) {      # :Grist
            # Cheesy gate to prevent multiple invocations on same dir
            # Arrange for jam dirs
            # MkDir1 has the actions
            $(<)-mkdir = true ;
            Depends dirs : $(<) ;
            MkDir1 $(<) ;
            # Recursively make parent directories.               #Siebel: Why not use mkdir -p 
            # $(<:P) = $(<)'s parent, & we recurse until root
            local _parent = $(<:P) ;              # :Parent
            # Don't try to create A: or A:\ on windows
            if $(NT) {
                switch $(_parent) {
                  case *:   : _parent = ;
                  case *:\\ : _parent = ;
                  }
                }
            if $(_parent) = $(<) {
                # The parent is the same as the dir.
                # We're at the root, which some OS's can't stat, so we mark
                # it as NotFile.
                NotFile $(_parent) ;
            } else if $(_parent:G=) {                        # :Grist
                # There's a parent; recurse.
                Depends $(<) : $(_parent) ;
                MkDir $(_parent) ;
                }
            }
        }
actions MkDir1   { $(MKDIR) $(<) }
rule    Object {
        # locate object and search for source, if wanted
        local _loc ;                              
        Clean clean : $(<) ;
        _loc = [ FDirName $(LOCATE_TARGET) ] ;    
        MakeLocate $(<) : $(_loc) ;               # Siebel Solve Src/foo.cpp windows directory structure
        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) $(SUBDIRHDRS) $(HDRS) ;
        # 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.
        # $(SEARCH_SOURCE:E) 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).
        HDRRULE   on $(>) = HdrRule ;
        HDRSCAN   on $(>) = $(HDRPATTERN) ;
        HDRSEARCH on $(>) = $(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ;  # :E value
        HDRGRIST  on $(>) = $(HDRGRIST) ;
        # propagate target specific-defines
        DEFINES on $(<) += $(DEFINES) ;
        # if source is not .c, generate .c with specific rule
        switch $(>:S) {                         # :Suffix
            case .asm : As  $(<) : $(>) ;
            case .c :   Cc  $(<) : $(>) ;
            case .C :   C++ $(<) : $(>) ;
            case .cc :  C++ $(<) : $(>) ;
            case .cpp : C++ $(<) : $(>) ;
            case .l :   Cc  $(<) : $(<:S=.c) ;  # :Suffix
                        Lex $(<:S=.c) : $(>) ;  # :Suffix
            case .s :   As  $(<) : $(>) ;
            case .y :   Cc  $(<) : $(<:S=$(YACCGEN)) ;  # :Suffix
                        Yacc $(<:S=$(YACCGEN)) : $(>) ; # :Suffix
            case * :    UserObject $(<) : $(>) ;
            }
        }
rule    ObjectCcFlags  { CCFLAGS  on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ; }     # :Suffix
rule    ObjectC++Flags { C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ; }     # :Suffix
rule    ObjectDefines  {   # reformat CCDEFS according to current defines
        local _src = [ FGristFiles $(<:S=$(SUFOBJ)) ] ;  # :Suffix
        DEFINES on $(_src) += $(>) ;
        CCDEFS  on $(_src)  = [ on $(_src) FDefines $(DEFINES) ] ;
        }
rule    ObjectHdrs {
        # Add to HDRS for HdrScan's benefit.
        # must reformat CCHDRS according to headers
        local _obj = [ FGristFiles $(<:S=$(SUFOBJ)) ] ;  # :Suffix
        HDRS on $(_obj) += $(>) ;
        CCHDRS on $(_obj) = [ on $(_obj) FIncludes $(HDRS) ] ;
        }
rule    Objects {
        local _obj ;
        for _obj in [ FGristFiles $(<) ] {
                Object $(_obj:S=$(SUFOBJ)) : $(_obj) ;  # :Suffix
                Depends obj : $(_obj:S=$(SUFOBJ)) ;     # :Suffix
                }
        }
rule    Resource  {
        local _src = [ FGristFiles $(>) ] ;
        local _res = $(_src:S=.res) ;
        local _exe = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
        Depends $(_exe) : $(_res) ;
        Depends $(_res) : $(_src) ;
        LOCATE    on $(_res)  = $(LOCATE_TARGET) ;
        SEARCH    on $(_src)  = $(SEARCH_SOURCE) ;
        NEEDLIBS  on $(_exe) += $(_res) ;
        HDRS      on $(_res)  = $(HDRS) $(SEARCH_SOURCE) $(SUBDIRHDRS) ;
        HDRRULE   on $(_src)  = HdrRule ;
        HDRSCAN   on $(_src)  = $(HDRPATTERN) ;
        HDRSEARCH on $(_src)  = $(SEARCH_SOURCE) $(SUBDIRHDRS) ;
        HDRGRIST  on $(_src)  = $(HDRGRIST) ;
        Rc $(_res) : $(_src) ;
        Clean clean : $(<) ;
        }
actions Rc       { $(RC) $(RCFLAGS) /I$(HDRS) /I$(RCHDRS) /Fo $(<) $(>) }
rule    RmTemps { Temporary $(>) ; }       
actions quietly updated piecemeal together RmTemps { $(RM) $(>) }
rule    Setuid  { MODE on [ FAppendSuffix $(<) : $(SUFEXE) ] = 4711 ; }
rule    Shell   {
        Depends shell : $(<) ;
        Depends $(<) : $(>) ;
        SEARCH on $(>) = $(SEARCH_SOURCE) ;
        MODE   on $(<) = $(SHELLMODE) ;
        Clean clean : $(<) ;
        Chmod $(<) ;
        }
actions Shell    {
        $(AWK) '
                NR == 1 { print "$(SHELLHEADER)" }
                NR == 1 && /^[#:]/ { next }
                /^##/ { next }
                { print }
        ' < $(>) > $(<)
        }
rule    SoftLink {
        Depends files : $(<) ;
        Depends $(<)  : $(>) ;
        SEARCH on $(>) = $(SEARCH_SOURCE) ;
        Clean clean : $(<) ;
        }
actions SoftLink { $(RM) $(<) && $(LN) -s $(>) $(<) }
rule    SubDir {              # SubDir TOP d1 d2 ... ;
        # Support for a project tree spanning multiple directories.
        #
        # SubDir declares a Jamfile's location in a project tree, setting
        # Jambase variables (SEARCH_SOURCE, LOCATE_TARGET) so that source
        # files can be found.
        #
        # TOP is a user-select variable name for root of the tree, and
        # d1 d2 ...  are the directory elements that lead from the root
        # of the tree to the directory of the Jamfile.
        #
        # TOP can be set externally, but normally the first SubDir call
        # computes TOP as the path up from the current directory; the
        # path contains one ../ for each of d1 d2 ...
        #
        # SubDir reads once the project-specific rules file Jamrules
        # in the TOP directory, if present.  This can be overridden
        # with the variable TOPRULES.
        #
        # SubDir supports multiple, overlaid project trees:  SubDir
        # invocations with different TOPs can appear in the same Jamfile.
        # The location established by the first SubDir call is used set
        # the TOPs for the subsequent SubDir calls.
        #
        # SubDir's public variables:
        #
        #       $(TOP) = path from CWD to root.
        #       $(SUBDIR) = path from CWD to the directory SubDir names.
        #       $(SUBDIR_TOKENS) = path from $(TOP) to $(SUBDIR) as dir names
        #       $(SEARCH_SOURCE) = $(SUBDIR)
        #       $(LOCATE_SOURCE) = $(ALL_LOCATE_TARGET) $(SUBDIR)
        #       $(LOCATE_TARGET) = $(ALL_LOCATE_TARGET) $(SUBDIR)
        #       $(SOURCE_GRIST) = $(SUBDIR_TOKENS) with !'s
        #
        local _top    = $(<[1]) ;
        local _tokens = $(<[2-]) ;
        #
        # First time through sets up relative root and includes Jamrules.
        #
        if ! $(_top) { Exit SubDir syntax error ; }
        if ! $($(_top)-SET) {
            $(_top)-SET = true ;       # First time we've seen this TOP.
            # We'll initialize a number of internal variables:
            #
            #   $(TOP-UP) = directories from ROOT to a common point
            #   $(TOP-DOWN) = directories from common point to TOP
            #   $(TOP-ROOT) = root directory for UP/DOWN -- normally CWD
            #   $(SUBDIR_UP) = current value of $(TOP-UP)
            #   $(SUBDIR_DOWN) = current value of $(TOP-DOWN)
            #   $(SUBDIR_ROOT) = current value of $(TOP-ROOT)
            #
            if $($(_top)) {
                # TOP externally set.
                # We'll ignore the relative (UP/DOWN) path that
                # got us here, and instead remember the hard ROOT.
                $(_top)-UP = ;
                $(_top)-DOWN = ;
                $(_top)-ROOT = $($(_top)) ;
            } else {                   # TOP not preset.
                # Establishing a new TOP.  In the simplest case,
                # (SUBDIR_UP/SUBDIR_DOWN/SUBDIR_ROOT unset), it's
                # merely a certain number of directories down from
                # the current directory, and FSubDirPath will set
                # TOP to a path consisting of ../ for each of the
                # elements of _tokens, because that represents how
                # far below TOP the current directory sits.
                #
                # In the more complicated case, the starting directory
                # isn't the directory of jam's invocation but an
                # location established by previous SubDir call.  The
                # starting directory is SUBDIR_UP directories up from
                # SUBDIR_ROOT, and then SUBDIR_DOWN directories down
                # from that.   If SUBDIR_ROOT is not set, that means
                # SUBDIR_DOWN and SUBDIR_UP represent the path from
                # the directory of jam's invocation.
                #
                # In the most complicated case, the _tokens also
                # represents directories down, because TOP is being
                # estalished in a directory other than TOP's root.
                # Hopefully, _tokens and SUBDIR_DOWN represent the
                # same final directory, relative to the new TOP and
                # the previous SubDIr's TOP.  To find the new TOP,
                # we have to chop off any common directories from
                # then ends of _tokens and SUBDIR_DOWN.  To do so,
                # we reverse each of them, call FStripCommon to
                # remove the initial common elements, and then
                # reverse them again.  After this process, if
                # both _tokens and SUBDIR_DOWN have elements, it
                # means the directory names estalished by the two
                # SubDir calls don't match, and a warning is issued.
                # All hell will likely break loose at this point,
                # since the whole SubDir scheme relies on the SubDir
                # calls accurately naming the current directory.
                # Strip common trailing elements of _tokens and SUBDIR_DOWN.
                _tokens = [ FReverse $(_tokens) ] ;
                SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
                FStripCommon _tokens : SUBDIR_DOWN ;
                SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
                _tokens = [ FReverse $(_tokens) ] ;
                if $(SUBDIR_DOWN) && $(_tokens) { Echo Warning: SubDir $(<) misplaced! ; }
                # We'll remember the relative (UP/DOWN) path that
                # got us here, plus any hard ROOT starting point
                # for the UP/DOWN.  If TOP is never set externally,
                # ROOT will always be "" (directory of jam's invocation).
                $(_top)-UP = $(SUBDIR_UP) $(_tokens) ;
                $(_top)-DOWN = $(SUBDIR_DOWN) ;
                $(_top)-ROOT = $(SUBDIR_ROOT:E="") ;                               # :E value
                $(_top) = [ FSubDirPath $(_top) ] ;
                }
            # Set subdir vars for the inclusion of the Jamrules,
            # just in case they have SubDir rules of their own.
            # Note that SUBDIR_DOWN is empty: it's all the way
            # up where the Jamrules live.  These gets overrided
            # just after the inclusion.
            SUBDIR_UP   = $($(_top)-UP) ;
            SUBDIR_DOWN = ;
            SUBDIR_ROOT = $($(_top)-ROOT) ;
            # Include $(TOPRULES) or $(TOP)/Jamrules.
            # Include $(TOPRULES) if set.
            # Otherwise include $(TOP)/Jamrules if present.
            if $($(_top)RULES) {
                include $($(_top)RULES) ;
            } else {
                NoCare  $(JAMRULES:R=$($(_top)):G=$(_top)) ;   # :Root/:Grist
                include $(JAMRULES:R=$($(_top)):G=$(_top)) ;   # :Root/:Grist
                }
           }
        # Get path from $(TOP) to named directory.
        # Save dir tokens for other potential uses.
        SUBDIR_UP     = $($(_top)-UP) ;
        SUBDIR_DOWN   = $($(_top)-DOWN) $(_tokens) ;
        SUBDIR_ROOT   = $($(_top)-ROOT) ;
        SUBDIR_TOKENS = $(SUBDIR_DOWN) ;
        SUBDIR = [ FSubDirPath $(<) ] ;
        # 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) ;
        SOURCE_GRIST  = [ FGrist $(SUBDIR_TOKENS) ] ;
        # Reset per-directory ccflags, hdrs, etc,
        # listed in SUBDIRRESET.
        # Note use of variable expanded assignment var
        SUBDIR$(SUBDIRRESET) = ;
        # Invoke user-specific SubDir extensions,
        # rule names listed in SUBDIRRULES.
        # Note use of variable expanded rule invocation
        $(SUBDIRRULES) $(<) ;
        }
rule    SubDirCcFlags  { SUBDIRCCFLAGS  += $(<) ; }
rule    SubDirC++Flags { SUBDIRC++FLAGS += $(<) ; }
rule    SubDirDefines  { SUBDIRC++FLAGS += [ FDefines $(<) ] ; }
rule    SubDirHdrs     { SUBDIRHDRS += [ FDirName $(<) ] ; }
rule    SubInclude {                # SubInclude TOP d1 ... ;
        # Include a subdirectory's Jamfile.
        # We use SubDir to get there, in case the included Jamfile
        # either doesn't have its own SubDir (naughty) or is a subtree
        # with its own TOP.
        if ! $($(<[1])) { Exit SubInclude $(<[1]) without prior SubDir $(<[1]) ; }
        SubDir  $(<) ;
        include $(JAMFILE:D=$(SUBDIR)) ;                             # :Directory
        }
rule    SubRules {                  # SubRules TOP d1 ... : Other-TOP ;
        #
        # Read another tree's Jamrules, by giving it's path according
        # to this tree and it's own name.
        if ! $($(<[1])) { Exit SubRules $(<[1]) without prior SubDir $(<[1]) ; }
        SubDir $(<) ;
        SubDir $(>) ;
        }
rule    Undefines { UNDEFS on [ FAppendSuffix $(<) : $(SUFEXE) ] += $(UNDEFFLAG)$(>) ; }
rule    UserObject { Exit "Unknown suffix on" $(>) "- see UserObject rule in Jamfile(5)." ; }
rule    Yacc {
        local _hdr ;
        _hdr = $(<:BS=.h) ;    # :Base/:Suffix
        MakeLocate $(<) $(_hdr) : $(LOCATE_SOURCE) ; # Some places don't have yacc.
        if $(YACC) {
            Depends $(<) $(_hdr) : $(>) ;
            Yacc1 $(<) $(_hdr) : $(>) ;
            YaccMv $(<) $(_hdr) : $(>) ;
            Clean clean : $(<) $(_hdr) ;
            }
        # make sure someone includes $(_hdr) else it will be
        # a deadly independent target
        Includes $(<) : $(_hdr) ;
        }
actions Yacc1    { $(YACC) $(YACCFLAGS) $(>) }
actions YaccMv   {
        $(MV) $(YACCFILES).c $(<[1])
        $(MV) $(YACCFILES).h $(<[2])
        }
#
# Utility rules; no side effects on these
#
rule    FAppendSuffix {    # "FAppendSuffix yacc lex foo.bat : $(SUFEXE) ;"
       # returns (yacc,lex,foo.bat) on Unix and
       # (yacc.exe,lex.exe,foo.bat) on NT.
        local _file _out ;
        if $(>) {
            for _file in $(<) {
                if $(_file:S) { _out += $(_file) ;          # :Suffix
                } else        { _out += $(_file:S=$(>)) ;   # :Suffix
                }
            }
            return $(_out) ;
        } else { return $(<) ; }
        }
rule    FDefines  { return -D$(<) ; }
rule    FDirName  {
        # Turn individual elements in $(<) into a usable path.
        local _dir ;
        local _path = $(DOT) ;
        for _dir in $(<) { _path = $(_dir:R=$(_path)) ; }       # :Root
        return $(_path) ;
        }
rule    FGrist      { return $(<:J=!) ; }        # :Join
rule    FGristFiles { return $(<:G=$(SOURCE_GRIST:E)) ; }   # :Grist # :E value
rule    FGristSourceFiles {
        # Produce source file 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 _src _gsrc ;
            for _src in $(<) {
                switch $(_src) {
                  case *.h : _gsrc += $(_src) ;
                  case *   : _gsrc += $(_src:G=$(SOURCE_GRIST)) ; # :Grist
                  }
                }
            return $(_gsrc) ;
            }
        }
rule    FIncludes { return -I$(<) ; }
rule    FRelPath {
        local _tgt _src ;       # first strip off common parts
        _tgt = $(<) ;
        _src = $(>) ;
        FStripCommon _tgt : _src ;
        _tgt = [ FSubDir  $(_tgt) ] ;   # now make path to root and path down
        _src = [ FDirName $(_src) ] ;
        # Concatenate and save
        if $(_src) = $(DOT) { return $(_tgt) ;
        } else              { return $(_src:R=$(_tgt)) ; }           # :Root
        }
rule    FReverse {               # FReverse a1 a2 a3 ... ;
        # return ... a3 a2 a1 ;
        if $(1) { return [ FReverse $(1[2-]) ] $(1[1]) ; }
        }
rule    FSubDir {
        # If $(>) is the path to the current directory, compute the
        # path (using ../../ etc) back to that root directory.
        # Sets result in $(<)
        if ! $(<[1]) { return $(DOT) ;
        } else {
            local _dir _path ;
            _path = $(DOTDOT) ;
            for _dir in $(<[2-]) { _path = $(_path:R=$(DOTDOT)) ; }    # :Root
            return $(_path) ;
            }
        }
rule    FSubDirPath {             # FSubDirPath TOP d1 ... ;
        # Returns path to named directory.
        # If jam is invoked in a subdirectory of the TOP, then we
        # need to prepend a ../ for every level we must climb up
        # (TOP-UP), and then append the directory names we must
        # climb down (TOP-DOWN), plus the named directories d1 ...
        # If TOP was set externally, or computed from another TOP
        # that was, we'll have to reroot the whole thing at TOP-ROOT.
        local _path = [ FRelPath $($(<[1])-UP) : $($(<[1])-DOWN) $(<[2-]) ] ;
        return $(_path:R=$($(<[1])-ROOT)) ;                       # :Root
        }
rule    FStripCommon {          # FStripCommon v1 : v2 ;
        # Strip common initial elements of variables v1 and v2.
        # Modifies the variable values themselves.
        if $($(<)[1]) && $($(<)[1]) = $($(>)[1]) {
            $(<) = $($(<)[2-]) ;
            $(>) = $($(>)[2-]) ;
            FStripCommon $(<) : $(>) ;
            }
        }
rule    FQuote    { return \\\"$(<)\\\" ; }

if $(MSVCDIR) {                             # NT specific actions
   rule    FDefines  { return /D$(<) ; }
   actions GenFile1 { $(>[1]) $(<) $(>[2-]) }
   rule    FIncludes { return /I$(<) ; }
   actions updated together piecemeal FArchive {
      if exist $(<) set _$(<:B)_= $(<) ; else set _$<:B) = ;
      $(AR) /out:$(<) %_$(<:B)_% $(>)
      }
   actions As  { $(AS)  /Ml /p /v /w2 $(>) $(<) ,nul,nul }
   actions Cc  { $(CC)  $(CCFLAGS)  $(CCDEFS) $(CCHDRS) /I$(STDHDRS)    $(>) /c /Fo".\\$(<:D)\\" /Fd".\\$(<:D)\\" }
   actions C++ { $(C++) $(C++FLAGS) $(CCDEFS) $(CCHDRS) /I$(STDHDRS) /Tp$(>) /c /Fo".\\$(<:D)\\" /Fd".\\$(<:D)\\" }
   actions Link  bind NEEDLIBS { $(LINK) /subsystem:windows /dll $(LINKFLAGS) $(UNDEFS) $(>) /libpath:$(LIBDIR) $(NEEDLIBS) $(LINKLIBS) /out:$(<:S=.dll) /implib:$(<:S=.lib) /pdb:$(<:S=.pdb) }
   actions Link2 bind NEEDLIBS { $(LINK) /subsystem:console      $(LINKFLAGS) $(UNDEFS) $(>) /libpath:$(LIBDIR) $(NEEDLIBS) $(LINKLIBS) /out:$(<:S=.exe) /implib:$(<:S=.lib) /pdb:$(<:S=.pdb) }
   }
# Compatibility with jam 2.5
rule    LinkLibraries { Libs $(<) ; }

# Compatibility with jam 2.2.
rule    addDirName   { $(<)   += [ FDirName $(>) ] ; }
rule     makeCommon  { FStripCommon $(<) : $(>) ; }
rule    _makeCommon  { FStripCommon $(<) : $(>) ; }
rule    makeDirName  { $(<)    = [ FDirName $(>) ] ; }
rule    makeGrist    { $(<)    = [ FGrist $(>) ] ; }
rule    makeGristedName { $(<) = [ FGristSourceFiles $(>) ] ; }
rule    makeRelPath  { $(<[1]) = [ FRelPath $(<[2-]) : $(>) ] ; }
rule    makeString   { $(<)    = $(>:J) ; }         # :Join
rule    makeSubDir   { $(<)    = [ FSubDir $(>) ] ; }
rule    makeSuffixed { $(<[1]) = [ FAppendSuffix $(>) : $(<[2]) ] ; }
#
# Now include the user's Jamfile.
#
include $(JAMFILE) ;
# Change User Description Committed
#3 4361 Dick Dunbar Repair Jam build (rule name changes in Jamfile)
       Submit a starting Test directory
#2 4360 Dick Dunbar Initial set of changes.
 This is a WORK IN PROGRESS.
       There may be some things that do not work in your environment.
       If you tell us, we'll fix it ASAP.
#1 4356 Dick Dunbar Jam 2.5 base established
//guest/perforce_software/jam/src/Jambase
#33 3070 Perforce staff Two Jambase changes: one fix, one enhancement.

The fix: if a Jamrules invoked SubDir to establish other roots,
and that Jamrules isn't in the current directory, the roots it
established were wrong.

The enhancement:  Undocumented support for SUBDIRRULES,
user-provided rules to invoke at the end of the SubDir rule,
and SUBDIRRESET, SUBDIR variables to reset (like SUBDIRC++FLAGS,
SUBDIRHDRS, etc) for each new SubDir.

Bug fix and change documented only in RELNOTES.
#32 3005 rmg Patch from Ingo Weinhold <[email protected]>,
BeOS porting.
#31 2852 rmg SubDir's support for an externally set TOP variable was broken
in 2.5rc1.  It now works as it did in 2.4.  Further, using SubDir
to include a subpart of an SubDir tree now works.  Previously,
you could only include the root of another SubDir tree.  For example,

    SubDir ALL src builds ;
    SubInclude ALL src server support ;

Essentially includes the ../server/support/Jamfile, without getting
confused as to the current directory.

Bug fix documented in RELNOTES.

=== computer:1666: Change 42285 by seiwald@waffle-cyg-seiwald on 2003/03/05 08:52:10
#30 2850 rmg Mac classic MPW Codewarrior 7 upgrades: minor compiling issues, new paths
in Jambase for libraries and includes, and separate out GenFile1 that sets PATH
for UNIX only, as it does't work under MPW (or anything other than with sh).

Porting change, noted in RELNOTES.

=== computer:1666: Change 41285 by evalynne@evalynne-bld-mac on 2003/02/05 11:47:19
#29 2849 rmg WinXP IA64 porting: set MSVCNT to the root of the SDK and
MSVCVer to Win64.

Jam: change handle type to long long (too much to include
windows.h?); bury IA64 in the library path in Jambase.

timer.cc: use long long for timer.

Also pulled over main's Jamsh.bat and extended it to handle the
IA64 SDK environment when MSVCVer=Win64.

Finally wrote a TarBall rule for NT that works (still uses tar
and cp, but written in cmd syntax), so 'jam api' works.

Porting changes, noted in RELNOTES.

=== computer:1666: Change 40867 by perforce@tridium on 2003/01/24 09:01:01
#28 2615 rmg Remove NT FQuote rule, as (at least with the command shell
I use), \" is required to pass quotes on the command line.

Fix to bug introduced by 2.5rc1.

Noted in the RELNOTES (for the moment) as a change between
2.5rc1 and 2.5rc2.

=== computer:1666: Change 40127 by seiwald@tricks-seiwald on 2003/01/14 16:20:25
#27 2566 rmg Add NT FQuote rule.

Undocumented.

=== computer:1666: Change 39604 by seiwald@play-seiwald on 2002/12/27 18:23:06
#26 2565 rmg Put .
in PATH for GenFile so jam can build itself without
. in the global PATH.

Porting change documented in RELNOTES.

=== computer:1666: Change 39602 by seiwald@play-seiwald on 2002/12/27 18:10:16
#25 2564 rmg Use MSVCDIR instead of MSVCNT if MSVCNT isn't set.
 Microsoft
changed the name to MSVCDIR in VC 6.0.

Porting change documented in RELNOTES.

=== computer:1666: Change 39600 by seiwald@play-seiwald on 2002/12/27 18:06:42
#24 2561 rmg RMDIR definition for NT and a default to $(RM) everywhere else.

New feature documented in RELNOTES.

=== computer:1666: Change 39570 by seiwald@play-seiwald on 2002/12/27 15:32:38
#23 2557 rmg Shuffle mechanism for optional Jamrules includes: now no error
message is issued for a missing include file marked with NOCARE.

Previously, we used Glob to try to find the optional Jamrules
files, but on VMS that doesn't work so well: Glob returns all
uppercase file names with .'s at the end, which doesn't match
"Jamrules" at all.

The NOCARE part is a user-visible change documented in RELNOTES.

=== computer:1666: Change 39273 by seiwald@waffle-cyg-seiwald on 2002/12/19 22:44:03
#22 2513 rmg Set the version number and patchlevel for the 2.5rc1 release.

In RELNOTES, don't document the different behavior when a "return"
is not the last statement executed in rule definition as a
       non-backward-compatible change (in the "Compatibility"
       section).
#21 2503 rmg No longer link jam with advapi32.lib -- it isn't needed
and it keeps moving.

No functional change.

=== computer:1666: Change 38674 by seiwald@tricks-seiwald on 2002/12/10 12:02:55
#20 2497 rmg Jambase no longer announces the compiler on Windows.
 It doesn't
announce anything else.

User visible change documented in RELNOTES.

=== computer:1666: Change 38194 by seiwald@tricks-seiwald on 2002/11/25 15:02:57
#19 2496 rmg Fix SubInclude's error message so that it actually mentions
the variable that is unset.

Also bumped patchlevel to 2.4.2 capriciously.

Change to unreleased behavior.

=== computer:1666: Change 38182 by seiwald@tricks-seiwald on 2002/11/25 10:47:50
#18 2485 rmg Beos updates for jam from "Ingo Weinhold" <[email protected]>.

Porting change.

=== computer:1666: Change 35634 by seiwald@play-seiwald on 2002/08/16 11:42:39
#17 2483 rmg Jam macosx changes: use 'ar' instead of libtool, as ar can do incremental
updates.  New support for the BSD style long filenames in archives.

Porting change.

=== computer:1666: Change 34993 by seiwald@oswald-seiwald on 2002/07/16 12:01:32

Fix archive scan (solaris and FreeBSD style) broken by change
#34993.  I _think_ all three forms of archive entries now work
again (traditional, solaris string table, and macosx #1/xxxx ).

=== computer:1666: Change 35027 by seiwald@play-seiwald on 2002/07/17 11:31:20

Fix archive scan supposedly fixed in 35027 (which was to fix 34993).
Now it works on MacOSX again.

=== computer:1666: Change 35057 by perforce@cardtrick on 2002/07/17 16:11:01
#16 2480 rmg Rewrite jam's SubDir rule to allow multiple roots.

Infrastructure change.

=== computer:1666: Change 33320 by seiwald@thin on 2002/05/13 10:10:50
#15 1577 rmg Use G=$(INSTALLGRIST) wherever G=installed had been hardcoded.
(To complete the use of $(INSTALLGRIST) started in change 1572
began)

completes change 1572; document as a Jambase variable, TBD.
#14 1572 Perforce staff Fix InstallInto to handle multiple sources properly, thanks
to Stephen Goodson.

Bug fix documented in RELNOTES.
#13 1571 Perforce staff MINGW port by Max Blagai.

Porting change documented in RELNOTES.
#12 1570 Perforce staff New SoftLink rule, courtesy of David Lindes.

User visible change documented in RELNOTES.
#11 1539 Perforce staff Fix definitions of FIncludes/FDefines for OS2 and NT, mistakes
caught by Craigh McPheeters.

This corrects behavior altered since jam 2.3 and prior to 2.4.
#10 1488 rmg Fix makeString to use builtin :J now - not the
missing FConcat.

Thanks to Craig McPheeters.
#9 1355 rmg Record integration of Change 281 by john_belmonte.
 (This was
actually dropped in as part of the Jam 2.3 release; the
present change serves to record the fact in the integration
history, only.)
#8 1344 rmg Under NT, default $(MV) to "move /y" in Jambase.
Logically (and in the integ hhistory) integrates Change 390 by Eric Scouten.

Cc: [email protected]
#7 1319 rmg Jam 2.3 + Perforce's internal changes.

This change is a drop of the Perforce internal Jam changes
since the 2.3 public release. The individual changes
represented herein are preserved in the
//guest/richard_geiger/intjam/ branch.

The intent of this drop is to provide a base, from which other
contributors' Jam branches may be integrated into. It is not
intended to become a packaged release in this state. We will
be integrating changes from other users prior to creating the
next packaged release.

Please refer to the src/RELNOTES file for an overview of the
changes present in this integration.

  - Richard Geiger
  Open Source Engineer at Perforce
#6 486 Perforce staff Jam 2.3.
 See RELNOTES for a list of changes from 2.2.x.

Just about every source file was touched when jam got ANSI-fied.
#5 211 Perforce staff Jeff Sickel's Mac OS X port.
#4 67 Laura Wingerd Integrate Perforce's jam changes & project page update
(change 59, change 60, change 61, change 62, change 63, change 64,
change 66)
#3 5 Perforce maintenance Jam/MR 2.2.4 (HDRPATTERN, JAMUNAME, JAMSHELL, plus misc tweaks)
#2 4 Perforce maintenance Jam/MR 2.2.2 (AmigaOS support)
#1 2 laura Add Jam/MR 2.2 source