# # /+\ # +\ 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 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) ;