# # /+\ # +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. # \+/ # # This file is part of Jam - see jam.c for Copyright information. # # # JAMBASE - jam 2.5 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 # 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 # 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 # 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 # FReverse a1 a2 ... ; return ... a2 a1 # 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.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 # # for perforce use -- jambase version JAMBASEDATE = 2004.10.07 ; # Initialize variables # # # OS specific variable settings # if $(NT) { # the list of supported toolsets on Windows NT and Windows 95/98 # local SUPPORTED_TOOLSETS = BORLANDC VISUALC VISUALC16 INTELC WATCOM MINGW LCC DIGITALMARS PELLESC ; # if the JAM_TOOLSET environment variable is defined, check that it is # one of our supported values # if $(JAM_TOOLSET) { if ! $(JAM_TOOLSET) in $(SUPPORTED_TOOLSETS) { Echo "The JAM_TOOLSET environment variable is defined but its value" ; Echo "is invalid, please use one of the following:" ; Echo ; for t in $(SUPPORTED_TOOLSETS) { Echo " " $(t) ; } Exit ; } } # if JAM_TOOLSET is empty, we'll try to detect the toolset from other # environment variables to remain backwards compatible with Jam 2.5 # if ! $(JAM_TOOLSET) { if $(BCCROOT) { JAM_TOOLSET = BORLANDC ; BORLANDC = $(BCCROOT) ; } else if $(MSVC) { JAM_TOOLSET = VISUALC16 ; VISUALC16 = $(MSVC) ; } else if $(MSVCNT) { JAM_TOOLSET = VISUALC ; VISUALC = $(MSVCNT) ; } else if $(MINGW) { # MINGW is defined when trying to compile FT-Jam with # classic Jam # JAM_TOOLSET = MINGW ; } else { Echo "Jam cannot be run because you didn't indicate which compilation toolset" ; Echo "to use. To do so, define the JAM_TOOLSET environment variable with" ; Echo "one of the following values:" ; Echo ; Echo " Value Toolset Description" ; Echo ; Echo " BORLANDC Borland C++" ; Echo " VISUALC Microsoft Visual C++" ; Echo " VISUALC16 Microsoft Visual C++ 16 bit" ; Echo " INTELC Intel C/C++" ; Echo " WATCOM Watcom C/C++" ; Echo " MINGW MinGW (gcc)" ; Echo " LCC Win32-LCC" ; Echo " DIGITALMARS Digital Mars C/C++" ; Echo " PELLESC Pelles C" ; Echo ; Echo "The corresponding compiler must be in your path" ; Echo ; Echo " e.g.: set JAM_TOOLSET=VISUALC" ; Exit ; } } MV ?= move /y ; CP ?= copy ; RM ?= del /f/q ; RMDIR ?= rmdir /s/q ; SLASH ?= \\ ; SUFLIB ?= .lib ; SUFOBJ ?= .obj ; SUFEXE ?= .exe ; SUFLIBSHR ?= .dll ; if $(JAM_TOOLSET) = BORLANDC { Echo "Compiler is Borland C++" ; AR ?= tlib /C /P64 ; CC ?= bcc32 ; CCFLAGS ?= -w- -q -DWIN -tWR -tWM -tWC ; C++ ?= $(CC) ; C++FLAGS ?= $(CCFLAGS) -P ; LINK ?= $(CC) ; ILINK ?= ilink32 -q ; IMPLIB ?= implib ; LINKFLAGS ?= $(CCFLAGS) ; STDLIBPATH ?= $(BORLANDC)\\lib ; STDHDRS ?= $(BORLANDC)\\include ; NOARSCAN ?= true ; ILINKLIBS ?= C0D32.OBJ CW32.LIB IMPORT32.LIB ; PICFLAGS ?= -tWD ; } else if $(JAM_TOOLSET) = VISUALC16 { Echo "Compiler is Microsoft Visual C++ 16 bit" ; AR ?= lib /nologo ; CC ?= cl /nologo ; CCFLAGS ?= /D "\"WIN\"" ; C++ ?= $(CC) ; C++FLAGS ?= $(CCFLAGS) ; LINK ?= $(CC) ; LINKFLAGS ?= $(CCFLAGS) ; LINKLIBS ?= $(MSVC)\\lib\\mlibce.lib $(MSVC)\\lib\\oldnames.lib ; LINKLIBS ?= ; NOARSCAN ?= true ; OPTIM ?= "" ; STDHDRS ?= $(VISUALC16)\\include ; UNDEFFLAG ?= "/u _" ; } else if $(JAM_TOOLSET) = VISUALC { # Visual C++ 6.0 uses MSVCDIR MSVCNT ?= $(MSVCDIR) ; # bury IA64 in the path for the SDK local I ; if $(OSPLAT) = IA64 { I = ia64\\ ; } else { I = "" ; } AR ?= lib ; AS ?= masm386 ; CC ?= cl /nologo ; CCFLAGS ?= "" ; C++ ?= $(CC) ; C++FLAGS ?= $(CCFLAGS) ; LINK ?= link /nologo ; LINKFLAGS ?= "" ; LINKLIBS ?= $(MSVCNT)\\lib\\$(I)libc.lib $(MSVCNT)\\lib\\$(I)oldnames.lib $(MSVCNT)\\lib\\$(I)kernel32.lib ; OPTIM ?= "" ; STDHDRS ?= $(VISUALC)\\include ; UNDEFFLAG ?= "/u _" ; } else if $(JAM_TOOLSET) = INTELC { Echo "Compiler is Intel C/C++" ; if ! $(VISUALC) { Echo "As a special exception, when using the Intel C++ compiler, you need" ; Echo "to define the VISUALC environment variable to indicate the location" ; Echo "of your Visual C++ installation. Aborting.." ; Exit ; } AR ?= lib ; AS ?= masm386 ; CC ?= icl /nologo ; CCFLAGS ?= "" ; C++ ?= $(CC) ; C++FLAGS ?= $(CCFLAGS) ; LINK ?= link /nologo ; LINKFLAGS ?= "" ; LINKLIBS ?= $(VISUALC)\\lib\\advapi32.lib $(VISUALC)\\lib\\libc.lib $(VISUALC)\\lib\\oldnames.lib $(VISUALC)\\lib\\kernel32.lib ; OPTIM ?= "" ; STDHDRS ?= $(INTELC)\include $(VISUALC)\\include ; UNDEFFLAG ?= "/u _" ; } else if $(JAM_TOOLSET) = WATCOM { Echo "Compiler is Watcom C/C++" ; AR ?= wlib ; CC ?= wcc386 ; CCFLAGS ?= /zq /DWIN32 /I$(WATCOM)\\h ; # zq=quiet C++ ?= wpp386 ; C++FLAGS ?= $(CCFLAGS) ; CP ?= copy ; DOT ?= . ; DOTDOT ?= .. ; LINK ?= wcl386 ; LINKFLAGS ?= /zq ; # zq=quiet LINKLIBS ?= ; MV ?= move ; NOARSCAN ?= true ; OPTIM ?= ; RM ?= del /f ; SLASH ?= \\ ; STDHDRS ?= $(WATCOM)\\h $(WATCOM)\\h\\nt ; SUFEXE ?= .exe ; SUFLIB ?= .lib ; SUFOBJ ?= .obj ; UNDEFFLAG ?= "/u _" ; PICFLAGS = -s ; # disable stack checks } else if $(JAM_TOOLSET) = MINGW { Echo "Compiler is GCC with Mingw" ; AR ?= ar -ru ; CC ?= gcc ; CCFLAGS ?= "" ; C++ ?= $(CC) ; C++FLAGS ?= $(CCFLAGS) ; LINK ?= $(CC) ; LINKFLAGS ?= "" ; LINKLIBS ?= "" ; OPTIM ?= ; SUFOBJ = .o ; SUFLIB = .a ; SLASH = / ; # NOARSCAN ?= true ; } else if $(JAM_TOOLSET) = LCC { Echo "Compiler is Win32-LCC" ; AR ?= lcclib ; CC ?= lcc ; CCFLAGS ?= "" ; C++ ?= $(CC) ; C++FLAGS ?= $(CCFLAGS) ; LINK ?= lcclnk ; LINKFLAGS ?= "" ; LINKLIBS ?= "" ; OPTIM ?= ; NOARSCAN = true ; } else if $(JAM_TOOLSET) = DIGITALMARS { Echo "Compiler is Digital Mars C/C++" ; AR ?= lib -c ; CC ?= dmc ; CCFLAGS ?= "" ; C++ ?= $(CC) ; C++FLAGS ?= $(CCFLAGS) ; LINK ?= link /nologo ; LINKFLAGS ?= "/EXETYPE:NT /NOMAP" ; LINKLIBS ?= USER32.LIB KERNEL32.LIB GDI32.LIB ; OPTIM ?= ; NOARSCAN = true ; PICFLAGS = -mn -WD ; } else if $(JAM_TOOLSET) = PELLESC { Echo "Compiler is PellesC" ; AR ?= polib ; CC ?= pocc ; CCFLAGS ?= "" ; LINK ?= polink ; LINKFLAGS ?= ; LINKLIBS ?= ; OPTIM ?= ; NOARSCAN = true ; LINKLIBS ?= crt.lib oldnames.lib Win\\kernel32.lib ; } else { # # XXX: We need better comments here !! # Exit "On NT, set BCCROOT, MSVCNT, MINGW or MSVC to the root of the" "Borland or Microsoft directories." ; } STDHRS ?= "" ; } else if $(OS2) { # the list of supported toolsets on OS/2 # local SUPPORTED_TOOLSETS = "EMX" "WATCOM" ; # this variable holds the current toolset # TOOLSET = "" ; # if the JAM_TOOLSET environment variable is defined, check that it is # one of our supported values # if $(JAM_TOOLSET) { if ! $(JAM_TOOLSET) in $(SUPPORTED_TOOLSETS) { Echo "The JAM_TOOLSET environment variable is defined but its value" ; Echo "is invalid, please use one of the following:" ; Echo ; for t in $(SUPPORTED_TOOLSETS) { Echo " " $(t) ; } Exit ; } } # if TOOLSET is empty, we'll try to detect the toolset from other # environment variables to remain backwards compatible with Jam 2.3 # if ! $(JAM_TOOLSET) { if $(watcom) { WATCOM = $(watcom) ; TOOLSET = WATCOM ; } else { Echo "Jam cannot be run because you didn't indicate which compilation toolset" ; Echo "to use. To do so, follow these simple instructions:" ; Echo ; Echo " - define one of the following environment variable, with the" ; Echo " appropriate value according to this list:" ; Echo ; Echo " Variable Toolset Description" ; Echo ; Echo " WATCOM Watcom C/C++ Watcom install path" ; Echo " EMX EMX (gcc) EMX install path" ; ############Echo " VISUALAGE IBM Visual Age C/C++ VisualAge install path" ; Echo ; Echo " - define the JAM_TOOLSET environment variable with the *name*" ; Echo " of the toolset variable you want to use." ; Echo ; Echo " e.g.: set WATCOM=C:\WATCOM" ; Echo " set JAM_TOOLSET=WATCOM" ; Echo ; Exit ; } } RM = del /f ; CP = copy ; MV ?= move ; DOT ?= . ; DOTDOT ?= .. ; SUFLIB ?= .lib ; SUFOBJ ?= .obj ; SUFEXE ?= .exe ; SUFLIBSHR ?= .dll ; if $(JAM_TOOLSET) = WATCOM { AR ?= wlib ; BINDIR ?= \\os2\\apps ; CC ?= wcc386 ; CCFLAGS ?= /zq /DOS2 /I$(WATCOM)\\h ; # zq=quiet C++ ?= wpp386 ; C++FLAGS ?= $(CCFLAGS) ; CP ?= copy ; DOT ?= . ; DOTDOT ?= .. ; LINK ?= wcl386 ; LINKFLAGS ?= /zq ; # zq=quiet LINKLIBS ?= ; MV ?= move ; NOARSCAN ?= true ; OPTIM ?= ; RM ?= del /f ; SLASH ?= \\ ; STDHDRS ?= $(WATCOM)\\h ; SUFEXE ?= .exe ; SUFLIB ?= .lib ; SUFOBJ ?= .obj ; UNDEFFLAG ?= "/u _" ; } else if $(JAM_TOOLSET) = EMX { Echo "Compiler is GCC-EMX" ; AR ?= ar -ru ; CC ?= gcc ; CCFLAGS ?= "" ; C++ ?= $(CC) ; C++FLAGS ?= $(CCFLAGS) ; LINK ?= $(CC) ; LINKFLAGS ?= "" ; LINKLIBS ?= "" ; OPTIM ?= ; SUFOBJ = .o ; SUFLIB = .a ; UNDEFFLAG ?= "-U" ; SLASH = / ; } else { # should never happen Exit "Sorry, but the $(JAM_TOOLSET) toolset isn't supported for now" ; } } else if $(VMS) { C++ ?= cxx ; C++FLAGS ?= ; CC ?= cc ; CCFLAGS ?= ; CHMOD ?= set file/prot= ; CP ?= copy/replace ; CRELIB ?= true ; DOT ?= [] ; DOTDOT ?= [-] ; EXEMODE ?= (w:e) ; FILEMODE ?= (w:r) ; HDRS ?= ; LINK ?= link ; LINKFLAGS ?= "" ; LINKLIBS ?= ; 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 OPENVMS : CCFLAGS ?= /stand=vaxc ; 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:Libs:MSL_MPWCRuntime_PPC.lib" "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL_C_PPC_MPW.Lib" ; MPWNLLIBS ?= "$(CW):MacOS Support:Libraries:Runtime:Libs:MSL_MPWCRuntime_PPC.lib" "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL_C_PPC_MPW(NL).Lib" ; SIOUXHDRS ?= ; SIOUXLIBS ?= "$(CW):MacOS Support:Libraries:Runtime:Libs:MSL_Runtime_PPC.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" ; C++ ?= mwcppc ; C++FLAGS ?= -w off ; CC ?= mwcppc ; CCFLAGS ?= -w off ; CP ?= duplicate -y ; DOT ?= ":" ; DOTDOT ?= "::" ; HDRS ?= $(MACHDRS) $(MPWHDRS) ; LINK ?= mwlinkppc ; LINKFLAGS ?= -mpwtool -warn ; LINKLIBS ?= $(MACLIBS) $(MPWLIBS) ; MKDIR ?= newfolder ; MV ?= rename -y ; NOARSCAN ?= true ; OPTIM ?= ; RM ?= delete -y ; SLASH ?= ":" ; STDHDRS ?= ; SUFLIB ?= .lib ; SUFOBJ ?= .o ; } else if $(OS) = BEOS && $(OSPLAT) = PPC { AR ?= mwld -xml -o ; BINDIR ?= /boot/home/config/bin ; CC ?= mwcc ; CCFLAGS ?= -nosyspath ; C++ ?= $(CC) ; C++FLAGS ?= -nosyspath ; CHMOD ?= chmod ; CHGRP ?= chgrp ; CHOWN ?= chown ; FORTRAN ?= "" ; LEX ?= flex ; LIBDIR ?= /boot/home/config/lib ; LINK ?= mwld ; LINKFLAGS ?= "" ; MANDIR ?= /boot/home/config/man ; NOARSCAN ?= true ; RANLIB ?= ranlib ; STDHDRS ?= /boot/develop/headers/posix ; YACC ?= bison -y ; YACCGEN ?= .c ; YACCFILES ?= y.tab ; YACCFLAGS ?= -d ; } else if $(OS) = BEOS { BINDIR ?= /boot/home/config/bin ; CC ?= gcc ; C++ ?= $(CC) ; CHMOD ?= chmod ; CHGRP ?= chgrp ; CHOWN ?= chown ; FORTRAN ?= "" ; LEX ?= flex ; LIBDIR ?= /boot/home/config/lib ; LINK ?= gcc ; MANDIR ?= /boot/home/config/man ; NOARSCAN ?= true ; RANLIB ?= ranlib ; STDHDRS ?= /boot/develop/headers/posix ; YACC ?= bison -y ; YACCGEN ?= .c ; YACCFILES ?= y.tab ; YACCFLAGS ?= -d ; } else if $(UNIX) { switch $(OS) { case AIX : LINKLIBS ?= -lbsd ; case AMIGA : CC ?= gcc ; YACC ?= bison -y ; case CYGWIN : CC ?= gcc ; CCFLAGS += -D__cygwin__ ; LEX ?= flex ; JAMSHELL ?= sh -c ; RANLIB ?= "" ; SUFEXE ?= .exe ; YACC ?= bison -y ; case DGUX : RANLIB ?= "" ; RELOCATE ?= true ; case HPUX : RANLIB ?= "" ; case INTERIX : CC ?= gcc ; JAMSHELL ?= sh -c ; RANLIB ?= "" ; case IRIX : RANLIB ?= "" ; case MPEIX : CC ?= gcc ; C++ ?= gcc ; CCFLAGS += -D_POSIX_SOURCE ; HDRS += /usr/include ; RANLIB ?= "" ; NOARSCAN ?= true ; NOARUPDATE ?= true ; case MVS : RANLIB ?= "" ; case NEXT : AR ?= libtool -o ; RANLIB ?= "" ; case MACOSX : C++ ?= c++ ; MANDIR ?= /usr/local/share/man ; case NCR : RANLIB ?= "" ; case PTX : RANLIB ?= "" ; case QNX : AR ?= wlib ; CC ?= cc ; CCFLAGS ?= -Q ; # quiet C++ ?= $(CC) ; C++FLAGS ?= -Q ; # quiet LINK ?= $(CC) ; LINKFLAGS ?= -Q ; # quiet 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 ; } # 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 ; SUFOBJSHR ?= .lo ; SUFLIBSHR ?= .la ; PICFLAGS ?= -fpic ; STDHDRS ?= /usr/include ; } # shared library object file suffix. We assume that it is identical # than the normal one SUFOBJSHR ?= $(SUFOBJ) ; SUFLIBSHR ?= $(SUFLIB) ; # the D compiler DC ?= dmd ; # # 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 ; CRELIB ?= ; DOT ?= . ; DOTDOT ?= .. ; EXEMODE ?= 711 ; FILEMODE ?= 644 ; FORTRAN ?= f77 ; FORTRANFLAGS ?= ; HDRS ?= ; INSTALLGRIST ?= installed ; JAMFILE ?= Jamfile ; JAMRULES ?= Jamrules ; LEX ?= ; LIBDIR ?= /usr/local/lib ; LINK ?= $(CC) ; LINKFLAGS ?= ; LINKLIBS ?= ; LN ?= ln ; MANDIR ?= /usr/local/man ; MKDIR ?= mkdir ; MV ?= mv -f ; OPTIM ?= ; RCP ?= rcp ; RM ?= rm -f ; RMDIR ?= $(RM) ; RSH ?= rsh ; SED ?= sed ; SHELLHEADER ?= "#!/bin/sh" ; SHELLMODE ?= 755 ; SLASH ?= / ; SUBDIRRULES ?= ; SUBDIRRESET ?= ASFLAGS HDRS C++FLAGS CCFLAGS ; SUFEXE ?= "" ; SUFLIB ?= .a ; SUFOBJ ?= .o ; UNDEFFLAG ?= "-u _" ; YACC ?= ; YACCGEN ?= ; YACCFILES ?= ; YACCFLAGS ?= ; HDRPATTERN = "^[ ]*#[ ]*include[ ]*[<\"]([^\">]*)[\">].*$" ; OSFULL = $(OS)$(OSVER)$(OSPLAT) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ; # # Base dependencies - first for "bootstrap" kinds of rules # Depends all : shell files lib exe obj ; Depends all shell files lib exe obj : first ; NotFile all first shell files lib exe obj dirs clean uninstall ; Always clean uninstall ; # # Rules # # /As object : source ; # # Assemble the file _source_, called by the @Object rule. # # Do not call this rule directly, since _object_ and _source_ may have # have platform-specific file extensions # rule As { Depends $(<) : $(>) ; ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ; ASHDRS on $(<) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ; } # /Bulk directory : sources ; # # Copies _sources_ into _directory_ # rule Bulk { local i ; for i in $(>) { File $(i:D=$(<)) : $(i) ; } } # /Dc object : source ; # # Compile the file source into object, usin the D compiler $(DC), its # flags $(DCFLAGS) and $(DOPTIM) # Called by the @Object rule # # Do not call this rule directly, since _object_ and _source_ may have # have platform-specific file extensions # rule Dc { Depends $(<) : $(>) ; # Just to clarify here: this sets the per-target DCFLAGS to # be the current value of (global) DCFLAGS and SUBDIRDCFLAGS. DCFLAGS on $(<) += $(DCFLAGS) $(SUBDIRDCFLAGS) ; } # /Cc object : source ; # # Compile the file source into object, using the C compiler $(CC), its # flags $(CCFLAGS) and $(OPTIM), and the header file directories $(HDRS). # Called by the @Object rule # # Do not call this rule directly, since _object_ and _source_ may have # have platform-specific file extensions # rule Cc { Depends $(<) : $(>) ; # If the compiler's -o flag doesn't work, relocate the .o if $(RELOCATE) { CcMv $(<) : $(>) ; } # 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 (VMS, NT) that malign multiple -D or -I flags. CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) ; CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ; CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; } # /C++ object : source ; # # Compile the C++ source file _source_. Similar to @CC, called by @Object # # Do not call this rule directly, since _object_ and _source_ may have # have platform-specific file extensions # rule C++ { Depends $(<) : $(>) ; if $(RELOCATE) { CcMv $(<) : $(>) ; } C++FLAGS on $(<) += $(C++FLAGS) $(SUBDIRC++FLAGS) ; CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ; CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; } # /Chmod target ; # # (Unix and VMS only). Change file permissions on _target_ to target-specific # $(MODE) value set by @Link, @File, @Install* and @Shell rules # rule Chmod { if $(CHMOD) { Chmod1 $(<) ; } } # /Clean clean : targets ; # # Removes existing _targets_ when _clean_ is built. clean is not a dependency # of all, and must be built explicitely for targets to be removed # # /File target : source ; # # Copies _source_ into _target_ # rule File { Depends files : $(<) ; Depends $(<) : $(>) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; MODE on $(<) = $(FILEMODE) ; Chmod $(<) ; } # /Fortran object : source ; # # Compile the Fortran source file _source_. Called by the @Object rule # # Do not call this rule directly, since _obj_ and _source_ may have # have platform-specific file extensions # rule Fortran { Depends $(<) : $(>) ; } # /GenFile target : image sources ; # # Runs the command "_image_ _target_ _sources_" to create _target_ from # _sources_ and _image_ (where _image_ is an executable built by the # @Main rule) # 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) ; } # /HardLink target : source ; # # Makes _target_ a hard link to _source_, if it isn't one already # (Unix only) # rule HardLink { Depends files : $(<) ; Depends $(<) : $(>) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; } # /HdrMacroFile # # this rule is specific to FT-Jam. It is used to indicate that a given file # contains definitions for filename macros (e.g. "#define MYFILE_H .h") # that can later be used in #include statements in the rest of the source # # these files must be parsed before any make is tried. # rule HdrMacroFile { HDRMACRO $(<) ; } # /HdrRule source : headers ; # # Arranges the proper dependencies when the file _source_ includes the files # _headers_ through the #include C preprocessor directive # # this rule is not intendend to be called explicitely. It is called # automatically during header scanning on sources handled by the @Object # rule (e.g. sources in @Main or @Library rules) # rule HdrRule { # HdrRule source : headers ; # N.B. This rule is called during binding, potentially after # the fate of many targets has been determined, and must be # used with caution: don't add dependencies to unrelated # targets, and don't set variables on $(<). # Tell Jam that anything depending on $(<) also depends on $(>), # set SEARCH so Jam can find the headers, but then say we don't # care if we can't actually find the headers (they may have been # within ifdefs), local s = $(>:G=$(HDRGRIST:E)) ; Includes $(<) : $(s) ; SEARCH on $(s) = $(HDRSEARCH) ; NoCare $(s) ; # Propagate on $(<) to $(>) HDRSEARCH on $(s) = $(HDRSEARCH) ; HDRSCAN on $(s) = $(HDRSCAN) ; HDRRULE on $(s) = $(HDRRULE) ; HDRGRIST on $(s) = $(HDRGRIST) ; } rule InstallInto { # InstallInto dir : sources ; local i t ; t = $(>:G=$(INSTALLGRIST)) ; # Arrange for jam install # Arrange for jam uninstall # sources are in SEARCH_SOURCE # targets are in dir Depends install : $(t) ; Clean uninstall : $(t) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; MakeLocate $(t) : $(<) ; # For each source, make gristed target name # and Install, Chmod, Chown, and Chgrp for i in $(>) { local tt = $(i:G=$(INSTALLGRIST)) ; Depends $(tt) : $(i) ; Install $(tt) : $(i) ; Chmod $(tt) ; if $(OWNER) && $(CHOWN) { Chown $(tt) ; OWNER on $(tt) = $(OWNER) ; } if $(GROUP) && $(CHGRP) { Chgrp $(tt) ; GROUP on $(tt) = $(GROUP) ; } } } # /InstallBin dir : sources ; # # Copy _sources_ into _dir_ with mode $(EXEMODE) # rule InstallBin { local _t = [ FAppendSuffix $(>) : $(SUFEXE) ] ; InstallInto $(<) : $(_t) ; MODE on $(_t:G=$(INSTALLGRIST)) = $(EXEMODE) ; } # /InstallFile dir : sources ; # # Copy _sources_ into _dir_ with mode $(FILEMODE) # rule InstallFile { InstallInto $(<) : $(>) ; MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ; } # /InstallLib dir : sources ; # # Copy _sources_ into _dir_ with mode $(FILEMODE) # rule InstallLib { InstallInto $(<) : $(>) ; MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ; } # /InstallLib dir : sources ; # # Copy _sources_ into the appropriate subdirectory of _dir_ with mode # $(FILEMODE). The subdirectory is manS, where S is the suffix of each of # sources. # 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=$(INSTALLGRIST)) = $(FILEMODE) ; } # /InstallShell dir : sources ; # # Copy _sources_ into _dir_ with mode $(SHELLMODE) # rule InstallShell { InstallInto $(<) : $(>) ; MODE on $(>:G=$(INSTALLGRIST)) = $(SHELLMODE) ; } # /Lex source.c : source.l ; # # Process the lex source file _source.l_ and rename the lex.yy.c # to _source.c_ . Called by the @Object rule # rule Lex { LexMv $(<) : $(>) ; Depends $(<) : $(>) ; MakeLocate $(<) : $(LOCATE_SOURCE) ; Clean clean : $(<) ; } # /Library library : sources ; # # Compiles _sources_ and archives them into _library_. The intermediate # objects are deleted. Calles @Object and @LibraryFromObjects # # If @Library is invoked with no suffix on _library_, the $(SUFLIB) # suffix is used # rule Library { LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ; Objects $(>) ; } # /SharedLibrary library : sources : def : import ; # # Compiles _sources_ and generates a shared _library_ (i.e. DLL on Windows, # or shared object on Unix). Calls @SharedObjects and @SharedLibraryFromObjects # # If @SharedLibrary is invoked with no suffix on _library_, then # $(SUFLIBSHR) suffix is used # # _def_ is the name of the corresponding definition file used to generate # the library on Windows and OS/2 (ignored otherwise). If undefined, it # will default to _library_ with the .def suffix # # _import_ is the name of the corresponding import library for Windows # and OS/2 platforms (ignored otherwise). If undefined, it will default # to _library_ with the .dll.lib suffix. # rule SharedLibrary { SharedLibraryFromObjects $(<) : $(>:S=$(SUFOBJSHR)) : $(3) : $(4) ; SharedObjects $(>) ; } if $(UNIX) { # this rule is used to find the 'libtool' script in the current # path, this is required when compiling shared objects on Unix # rule LibToolFind { if $(LIBTOOL) { return $(LIBTOOL) ; } local matches = [ Glob $(PATH) : libtool ] ; if ! $(matches) { Exit "could not find 'libtool' program in current path. Aborting !" ; } LIBTOOL = $(matches[1]) ; return $(LIBTOOL) ; } } # /LibraryFromObjects library : objects ; # # Archives _objects_ into _library_. The _objects_ are then deleted # # If _library_ has no suffix, the $(SUFLIB) suffix is used # # Called by @Library rule. Most people should never call this rule # directly. # rule LibraryFromObjects { local _i _l _s ; # Add grist to file names _s = [ FGristFiles $(>) ] ; _l = $(<:S=$(SUFLIB)) ; # library depends on its member objects if $(KEEPOBJS) { Depends obj : $(_s) ; } else { Depends lib : $(_l) ; } # Set LOCATE for the library and its contents. The bound # value shows up as $(NEEDLIBS) on the Link actions. # For compatibility, we only do this if the library doesn't # already have a path. if ! $(_l:D) { MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ; } if $(NOARSCAN) { # If we can't scan the library to timestamp its contents, # we have to just make the library depend directly on the # on-disk object files. Depends $(_l) : $(_s) ; } else { # If we can scan the library, we make the library depend # on its members and each member depend on the on-disk # object file. Depends $(_l) : $(_l)($(_s:BS)) ; for _i in $(_s) { Depends $(_l)($(_i:BS)) : $(_i) ; } } Clean clean : $(_l) ; if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; } Archive $(_l) : $(_s) ; if $(RANLIB) { Ranlib $(_l) ; } # If we can't scan the library, we have to leave the .o's around. if ! ( $(NOARSCAN) || $(NOARUPDATE) ) { RmTemps $(_l) : $(_s) ; } } # /SharedLibraryFromObjects library : objects : def : import ; # # Equivalent of @LibraryFromObjects for shared libraries. # # Called by @SharedLibrary. Most people shouldn't call this rule # directly # rule SharedLibraryFromObjects { local _i _l _s ; # Add grist to file names _s = [ FGristFiles $(>) ] ; _l = $(<:S=$(SUFLIBSHR)) ; #Echo "Library is $(_l)" ; # library depends on its member objects if $(KEEPOBJS) { Depends obj : $(_s) ; } else { Depends lib : $(_l) ; } # Set LOCATE for the library and its contents. The bound # value shows up as $(NEEDLIBS) on the Link actions. # For compatibility, we only do this if the library doesn't # already have a path. if ! $(_l:D) { MakeLocate $(_l) : $(LOCATE_TARGET) ; } # we never scan shared libraries for member objects Depends $(_l) : $(_s) ; Clean clean : $(_l) ; # I don't know if VMS supports shared libraries, so I prefer # to disable the following right now # #if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; } # creating the library is so much fun on Unix :-) if $(UNIX) { local libtool = [ LibToolFind ] ; # find the right libtool AR on $(_l) = "$(libtool) --mode=link $(AR)" ; } else if $(NT) { local _implib = $(4) ; local _def = $(3) ; _implib ?= $(_l:S=$(SUFLIBSHR)$(SUFLIB)) ; _def ?= $(_l:S=.def) ; Clean clean : $(_implib) ; Depends lib : $(_implib) $(_def) ; Depends $(_implib) : $(_def) $(_l) ; Depends $(_l) : $(_def) ; DEFFILENAME on $(_l) = $(_def) ; IMPLIBNAME on $(_l) = $(_implib) ; MakeLocate $(_implib) : $(LOCATE_TARGET) ; MakeLocate $(_implib:S=.exp) : $(LOCATE_TARGET) ; if $(JAM_TOOLSET) in VISUALC BORLANDC LCC WATCOM DIGITALMARS { SharedLink-$(JAM_TOOLSET) $(_l) : $(_s) : $(_implib) : $(_def) ; } DllLink $(_l) : $(_s) ; } else { Echo "Sorry, I don't know how to make a shared library on your system" ; Exit "Please contact the FTJam maintainer for help" ; } } # Since building shared libraries is so different depending on the # compiler being used, I've broken this task into compiler-specific # ones # # # This contains the Visual C++ specific rule used to build a DLL # and its import library # rule SharedLink-VISUALC { # get rid of the '.exp' file when cleaning # Clean clean : $(3:S=.exp) ; } rule SharedLink-BORLANDC { local _deffile = $(4) ; local _implib = $(3) ; LINKFLAGS on $(<) += /x /Gn /Tpd ; LINKLIBS on $(<) = $(LINKLIBS) $(ILINKLIBS) ; # Generate import library with the IMPLIB tool !! # DllImplib $(_implib) : $(<) ; Depends $(_implib) : $(_deffile) $(<) ; Depends lib : $(_implib) ; DEFFILENAME on $(_implib) = $(_deffile) ; # clean the TDS file, since the compiler refuses to not generate it ! MakeLocate $(<:S=.tds) : $(LOCATE_TARGET) ; Clean clean : $(<:S=.tds) ; } rule SharedLink-LCC { if "" { #Echo "Sorry, but generating DLLs with LCC is not supported. That's" ; #Echo "because the 'lcclnk' tool that comes with this compiler is" ; #Echo "unreliable and doesn't work as expected. For more information" ; #Echo "contact the FT-Jam maintainer" ; #Exit ; } # the 'lcclnk' tool is absolutely broken: # - its -o flag doesn't work when there is a LIBRARY statement # in the .def file. # # - it uses the LIBRARY name in the .def file to determine # the name of the dll and its import library, and always # places them in the current directory !! # # - if there is no LIBRARY statement, the -o flag is only # used to determine where the DLL is placed, the import # library will always be placed in the current directory !! # # clean the .exp file too, don't know how to get rid of it Clean clean : $(4:S=.exp) ; } rule SharedLink-WATCOM { #Echo "Sorry, but building DLLs with Watcom isn't supported by this tool" ; #Echo "this comes from the fact that the Watcom linker isn't capable of" ; #Echo "using normal .def files" ; #Exit ; local _deffile = $(4) ; local _implib = $(3) ; IMPLIB on $(<) = $(_implib) ; DEFFILE on $(<) = $(_deffile) ; # clean the TDS file, since the compiler refuses to not generate it ! MakeLocate $(<:S=.tds) : $(LOCATE_TARGET) ; Clean clean : $(<:S=.tds) ; } rule SharedLink-DIGITALMARS { #Echo "Sorry, but building DLLs with Digital Mars isn't supported at the" ; #Echo "moment, please contact the FT-Jam maintainers" ; #Exit ; } # /Link image : objects ; # # Links _image_ from _objects_ and sets permissions on _image_ to # $(EXEMODE). _image_ must be an actual filename; suffix is not # supplied. # # Called by @Main, shouldn't be called by most people # rule Link { MODE on $(<) = $(EXEMODE) ; Chmod $(<) ; } # /LinkLibraries image : libraries ; # # Makes _image_ depend on _libraries_ and includes them during linking # # _image_ may be referenced without a suffix in this rule invocation. # @LinkLibraries supplies the suffix # # You should only use this rule with libraries created through the # @Library rule. For external libraries, use something else (XXX) # 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)) ; } # /LinkSharedLibraries image : libraries : # # Same as @LinkLibraries, but to link _image_ with shared libraries # generated through the @SharedLibrary rule # rule LinkSharedLibraries { # make library dependencies of target # set NEEDLIBS variable used by 'actions Main' local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ; local _ext = $(SUFLIBSHR) ; if $(NT) || $(OS2) { # on NT or OS/2, we need to link agains the import library, # not the DLL itself !! # _ext = $(SUFLIBSHR)$(SUFLIB) ; } Depends $(_t) : $(>:S=$(_ext)) ; NEEDLIBS on $(_t) += $(>:S=$(_ext)) ; } # /Main image : sources ; # # Compiles _sources_ and links them into _image_. Calls @Objects and # @MainFromObjects. # # _image_ may be supplied without suffix. # rule Main { MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ; Objects $(>) ; } # /MainFromObjects image : objects ; # # Links _objects_ into _image_. Dependency of exe. # @MainFromObjects provides a default suffix for _image_ # rule MainFromObjects { local _s _t ; # Add grist to file names # Add suffix to exe _s = [ FGristFiles $(>) ] ; _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ; # so 'jam foo' works when it's really foo.exe if $(_t) != $(<) { Depends $(<) : $(_t) ; NotFile $(<) ; } # make compiled sources a dependency of target Depends exe : $(_t) ; Depends $(_t) : $(_s) ; MakeLocate $(_t) : $(LOCATE_TARGET) ; Clean clean : $(_t) ; # special case for stupid Borland C++, which always generates a # .tds file for executables, even when no debug information is needed # if $(JAM_TOOLSET) = BORLANDC { MakeLocate $(_t:S=.tds) : $(LOCATE_TARGET) ; Clean clean : $(_t:S=.tds) ; } Link $(_t) : $(_s) ; } # /MakeLocate targets : directory # # Creates _dir_ and causes _target_ to be built into _dir_ # # This is done by setting the target-specific variable LOCATE # on _targets_, and arranges with @MkDir to create the target # directory # rule MakeLocate { # 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) ; MkDir $(>[1]:G=dir) ; } } # /MkDir dir ; # # Creates _dir_ and its parent directories # rule MkDir { # Ignore timestamps on directories: we only care if they # exist. NoUpdate $(<) ; # Don't create . or any directory already created. if $(<:G=) != $(DOT) && ! $($(<)-mkdir) { # 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. # $(<:P) = $(<)'s parent, & we recurse until root local s = $(<:P) ; # Don't try to create A: or A:\ on windows if $(NT) { switch $(s) { case *: : s = ; case *:\\ : s = ; } } # handle "C:", "C:/", "/cygdrive" and "/cygdrive/" in Cygwin if $(UNIX) && $(OS) = CYGWIN { switch $(s) { case ?: : s = ; case ?:/ : s = ; case /cygdrive : s = ; case /cygdrive/ : s = ; } } if $(s) = $(<) { # 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 $(s) ; } else if $(s:G=) { # There's a parent; recurse. Depends $(<) : $(s) ; MkDir $(s) ; } } } # /Object object : source ; # # Compile s a single _source_ file into _object_. The @Main and @Library # rules use it to compile sources. # # Causes _source_ to be scanned for #include directives and calls @HdrRule # to make all included files dependencies of _object_. # # Calls one of the following rules depending on the suffix to do the # actual compilation: # rule Object { # locate object and search for source, if wanted Clean clean : $(<) ; MakeLocate $(<) : $(LOCATE_TARGET) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; # Save HDRS for -I$(HDRS) on compile. # We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers # in the .c file's directory, but generated .c files (from # yacc, lex, etc) are located in $(LOCATE_TARGET), possibly # different from $(SEARCH_SOURCE). HDRS on $(<) = $(SEARCH_SOURCE) $(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) ; HDRGRIST on $(>) = $(HDRGRIST) ; # propagate target specific-defines DEFINES on $(<) += $(DEFINES) ; # if source is not .c, generate .c with specific rule switch $(>:S) { case .asm : As $(<) : $(>) ; case .c : Cc $(<) : $(>) ; case .C : C++ $(<) : $(>) ; case .cc : C++ $(<) : $(>) ; case .cpp : C++ $(<) : $(>) ; case .cxx : C++ $(<) : $(>) ; case .c++ : C++ $(<) : $(>) ; case .C++ : C++ $(<) : $(>) ; case .d : Dc $(<) : $(>) ; case .f : Fortran $(<) : $(>) ; case .l : Cc $(<) : $(<:S=.c) ; Lex $(<:S=.c) : $(>) ; case .s : As $(<) : $(>) ; case .y : Cc $(<) : $(<:S=$(YACCGEN)) ; Yacc $(<:S=$(YACCGEN)) : $(>) ; case * : UserObject $(<) : $(>) ; } } # /ObjectCcFlags sources : flags ; # # this rule is used to add compiler flags to the compilation of # specific C sources files. # rule ObjectCcFlags { CCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ; } # /ObjectC++Flags sources : flags ; # # this rule is used to add compiler flags to the compilation of # specific C++ source files # rule ObjectC++Flags { C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ; } # /ObjectDefines objects : macros ; # # this rule is used to add macro defines to the compilation of # specific C and C++ source files # rule ObjectDefines { # must reformat CCDEFS according to current defines local s = [ FGristFiles $(<:S=$(SUFOBJ)) ] ; DEFINES on $(s) += $(>) ; CCDEFS on $(s) = [ on $(s) FDefines $(DEFINES) ] ; } # /ObjectHdrs sources : paths ; # # this rule is used to add include paths to the compilation of # specific C and C++ source files # rule ObjectHdrs { # Add to HDRS for HdrScan's benefit. # must reformat CCHDRS according to headers local s = [ FGristFiles $(<:S=$(SUFOBJ)) ] ; HDRS on $(s) += $(>) ; CCHDRS on $(s) = [ on $(s) FIncludes $(HDRS) ] ; } # /Objects sources ; # # this rule is used to compile one or more sources into object files. # do not call it directly, it is used by the Main and Library rules # automatically # rule Objects { local _i ; for _i in [ FGristFiles $(<) ] { Object $(_i:S=$(SUFOBJ)) : $(_i) ; Depends obj : $(_i:S=$(SUFOBJ)) ; } } # /SharedObjects # # this rule is used to compile one or more sources into 'shared object # files'. This means object files used to build either DLLs or Unix shared # libraries. # # do not call this rule directly, it is called by SharedLibrary automatically # rule SharedObjects { # temporarily override SUFOBJ with $(SUFOBJSHR) to # local SUFOBJ = $(SUFOBJSHR) ; # call the normal Objects rule # Objects $(<) ; # add the compiler-specific position-independent-code flag # where needed # ObjectCcFlags $(<) : $(PICFLAGS) ; # change the compiler invokation for all these objects # to use Libtool on Unix systems. We explicitely disable the # generation of static objects here # if $(UNIX) { libtool on $(<:S=$(SUFOBJ)) = [ LibToolFind ] ; CC on $(<:S=$(SUFOBJ)) = "$(libtool) --mode=compile $(CC) -dynamic" ; } } rule RmTemps { Temporary $(>) ; } rule Setuid { MODE on [ FAppendSuffix $(<) : $(SUFEXE) ] = 4711 ; } rule Shell { Depends shell : $(<) ; Depends $(<) : $(>) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; MODE on $(<) = $(SHELLMODE) ; Clean clean : $(<) ; Chmod $(<) ; } rule SoftLink { Depends files : $(<) ; Depends $(<) : $(>) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; Clean clean : $(<) ; } 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="") ; $(_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)) ; include $(JAMRULES:R=$($(_top)):G=$(_top)) ; } } # 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 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 _r = [ FRelPath $($(<[1])-UP) : $($(<[1])-DOWN) $(<[2-]) ] ; return $(_r:R=$($(<[1])-ROOT)) ; } rule SubDirDcFlags { SUBDIRDCFLAGS += $(<) ; } rule SubDirCcFlags { SUBDIRCCFLAGS += $(<) ; } rule SubDirC++Flags { SUBDIRC++FLAGS += $(<) ; } 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)) ; } 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 _h ; _h = $(<:BS=.h) ; # Some places don't have a yacc. MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ; if $(YACC) { Depends $(<) $(_h) : $(>) ; Yacc1 $(<) $(_h) : $(>) ; YaccMv $(<) $(_h) : $(>) ; Clean clean : $(<) $(_h) ; } # make sure someone includes $(_h) else it will be # a deadly independent target Includes $(<) : $(_h) ; } # # Utility rules; no side effects on these # # /FGrist path to file ; # # Returns a single string that is used as grist # rule FGrist { return $(<:J=!) ; } rule FGristFiles { return $(<:G=$(SOURCE_GRIST:E)) ; } 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 * : _o += $(_i:G=$(SOURCE_GRIST)) ; } } return $(_o) ; } } rule FReverse { 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 _i _d ; _d = $(DOTDOT) ; for _i in $(<[2-]) { _d = $(_d:R=$(DOTDOT)) ; } return $(_d) ; } } 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 FRelPath { local _l _r ; # first strip off common parts _l = $(<) ; _r = $(>) ; FStripCommon _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)) ; } } 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) ; } else { _o += $(_i:S=$(>)) ; } } return $(_o) ; } else { return $(<) ; } } # # Operating system specific utility rules # First, the (generic) UNIX versions # rule FQuote { return "\\\"$(<)\\\"" ; } rule FDefines { return -D$(<) ; } rule FIncludes { return -I$(<) ; } rule FDirName { # Turn individual elements in $(<) into a usable path. local _i ; local _s = $(DOT) ; for _i in $(<) { _s = $(_i:R=$(_s)) ; } return $(_s) ; } if $(OS2) { rule FQuote { return "\"$(<)\"" ; } rule FIncludes { return /I$(<) ; } } else if $(NT) && $(JAM_TOOLSET) != MINGW && $(JAM_TOOLSET) != LCC { rule FDefines { return /D$(<) ; } rule FIncludes { return /I$(<) ; } } else if $(MAC) { rule FQuote { return "\"$(<)\"" ; } rule FDefines { return "-define '$(<)'" ; } rule FIncludes { return "\"$(<:J=,)\"" ; } } else if $(VMS) { rule FQuote { return "\"\"\"$(<)\"\"\"" ; } rule FDefines { return "/define=( $(<:J=,) )" ; } rule FIncludes { return "/inc=( $(<:J=,) )" ; } rule FDirName { local _s _i ; # Turn individual elements in $(<) into a usable path. if ! $(<) { _s = $(DOT) ; } else { # 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)) ; } } return $(_s) ; } } # # Actions # # # First the defaults # actions updated together piecemeal Archive { $(AR) $(<) $(>) } actions As { $(AS) $(ASFLAGS) $(ASHDRS) -o $(<) $(>) } actions C++ { $(C++) -c -o $(<) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } actions Cc { $(CC) -c -o $(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } actions Dc { $(DC) -c -of$(<) $(DCFLAGS) $(DOPTIM) $(>) } actions Chgrp { $(CHGRP) $(GROUP) $(<) } actions Chmod1 { $(CHMOD) $(MODE) $(<) } actions Chown { $(CHOWN) $(OWNER) $(<) } actions piecemeal together existing Clean { $(RM) $(>) } actions File { $(CP) $(>) $(<) } actions GenFile1 { $(>[1]) $(<) $(>[2-]) } actions Fortran { $(FORTRAN) $(FORTRANFLAGS) -o $(<) $(>) } actions HardLink { $(RM) $(<) && $(LN) $(>) $(<) } actions Install { $(CP) $(>) $(<) } actions Lex { $(LEX) $(>) } actions LexMv { $(MV) lex.yy.c $(<) } actions Link bind NEEDLIBS { $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) } actions MkDir1 { $(MKDIR) $(<) } actions together Ranlib { $(RANLIB) $(<) } actions quietly updated piecemeal together RmTemps { $(RM) $(>) } actions Shell { $(AWK) ' NR == 1 { print "$(SHELLHEADER)" } NR == 1 && /^[#:]/ { next } /^##/ { next } { print } ' < $(>) > $(<) } actions SoftLink { $(RM) $(<) && $(LN) -s $(>) $(<) } actions Yacc1 { $(YACC) $(YACCFLAGS) $(>) } actions YaccMv { $(MV) $(YACCFILES).c $(<[1]) $(MV) $(YACCFILES).h $(<[2]) } # # RELOCATE - for compilers with broken -o flags # if $(RELOCATE) { actions C++ { $(C++) -c $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } actions Cc { $(CC) -c $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } actions ignore CcMv { [ $(<) != $(>:BS=$(SUFOBJ)) ] && $(MV) $(>:BS=$(SUFOBJ)) $(<) } } # # NOARUPDATE - can't update an archive # if $(NOARUPDATE) { actions Archive { $(AR) $(<) $(>) } } # # UNIX specific actions # if $(UNIX) { actions GenFile1 { PATH="$PATH:." $(>[1]) $(<) $(>[2-]) } } # # NT specific actions # if $(NT) { if $(JAM_TOOLSET) = VISUALC || $(JAM_TOOLSET) = INTELC { actions updated together piecemeal Archive { if exist $(<) set _$(<:B)_=$(<) $(AR) /out:$(<) %_$(<:B)_% $(>) } actions As { $(AS) /Ml /p /v /w2 $(>) $(<) ,nul,nul; } actions Cc { $(CC) /c /Fo$(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) /I$(STDHDRS) $(>) } actions C++ { $(C++) /c /Fo$(<) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) /I$(STDHDRS) /Tp$(>) } actions Link bind NEEDLIBS { $(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) } actions DllLink bind NEEDLIBS DEFFILENAME IMPLIBNAME { $(LINK) $(LINKFLAGS) /DLL /DEF:$(DEFFILENAME) /IMPLIB:$(IMPLIBNAME) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) } } else if $(JAM_TOOLSET) = VISUALC16 { actions updated together piecemeal Archive { $(AR) $(<) -+$(>) } actions Cc { $(CC) /c /Fo$(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } actions C++ { $(C++) /c /Fo$(<) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) /Tp$(>) } actions Link bind NEEDLIBS { $(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) } actions DllLink bind NEEDLIBS DEFFILENAME IMPLIBNAME { $(LINK) $(LINKFLAGS) /DLL /DEF:$(DEFFILENAME) /IMPLIB:$(IMPLIBNAME) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) } } else if $(JAM_TOOLSET) = BORLANDC { actions updated together piecemeal Archive { $(AR) $(<) -+$(>) } actions Link bind NEEDLIBS { $(LINK) -e$(<) $(LINKFLAGS) $(UNDEFS) -L$(LINKLIBS) $(NEEDLIBS) $(>) } actions DllLink bind NEEDLIBS DEFFILENAME { $(ILINK) $(LINKFLAGS) $(>) , $(<) ,, $(LINKLIBS:E) $(NEEDLIBS:E) , $(DEFFILENAME) } actions DllImplib bind DEFFILENAME { $(IMPLIB) -a $(<) $(>) $(DEFFILENAME) } actions C++ { $(C++) -c -o$(<) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } actions Cc { $(CC) -c -o$(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } } else if $(JAM_TOOLSET) = MINGW { actions together piecemeal Archive { $(AR) $(<) $(>:T) } actions Cc { $(CC) -c -o $(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) -I$(STDHDRS) $(>) } actions C++ { $(C++) -c -o $(<) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) -I$(STDHDRS) $(>) } actions DllLink bind DEFFILENAME IMPLIBNAME { $(LINK) $(LINKFLAGS) -shared -o $(<) $(>) $(DEFFILENAME) -Wl,--out-implib,$(IMPLIBNAME) } } else if $(JAM_TOOLSET) = WATCOM { actions together piecemeal Archive { $(AR) -q $(<) +-$(>) } actions Cc { $(CC) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) /Fo=$(<) -I$(STDHDRS) $(>) } actions C++ { $(C++) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) /Fo=$(<) -I$(STDHDRS) $(>) } actions Link bind NEEDLIBS { $(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) } actions DllLink bind NEEDLIBS DEFFILENAME IMPLIBNAME { $(LINK) $(LINKFLAGS) -l=NT_DLL -"export=$(DEFFILENAME) option implib=$(IMPLIBNAME)" /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) } actions Shell { $(CP) $(>) $(<) } } else if $(JAM_TOOLSET) = LCC { actions together piecemeal Archive { $(AR) /out:$(<) $(>) } actions Cc { $(CC) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) -Fo$(<) -I$(STDHDRS) $(>) } actions Link bind NEEDLIBS { $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) } actions DllLink bind NEEDLIBS DEFFILENAME { $(LINK) $(LINKFLAGS) -DLL -o $(<) $(UNDEFS) $(>) $(DEFFILENAME) $(NEEDLIBS) $(LINKLIBS) } actions ignore DllLinkMv { $(MV) $(2) $(1) } actions Shell { $(CP) $(>) $(<) } } else if $(JAM_TOOLSET) = DIGITALMARS { actions together piecemeal Archive { $(AR) $(<) $(>) } actions Cc { $(CC) -c $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) -o$(<) -I$(STDHDRS) $(>) } actions C++ { $(C++) -c $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) -o$(<) -I$(STDHDRS) $(>) } # note: we don't generate MAP files here ! actions Link bind NEEDLIBS { $(LINK) $(LINKFLAGS) $(>),$(<),NUL, $(NEEDLIBS) $(LINKLIBS) } # note: we don't generate MAP files here ! actions DllLink bind NEEDLIBS DEFFILENAME IMPLIBNAME { $(LINK) $(LINKFLAGS) /IMPLIB:$(IMPLIBNAME) $(>) , $(<) ,NUL, $(LINKLIBS:E) $(NEEDLIBS:E) , $(DEFFILENAME) } actions Shell { $(CP) $(>) $(<) } } else if $(JAM_TOOLSET) = PELLESC { actions together piecemeal Archive { $(AR) /OUT:$(<) $(>) } actions Cc { $(CC) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) /Fo $(<) -I$(STDHDRS) $(>) } actions Link bind NEEDLIBS { $(LINK) $(LINKFLAGS) /OUT:$(<) $(>) $(NEEDLIBS) $(LINKLIBS) } actions DllLink bind NEEDLIBS DEFFILENAME IMPLIBNAME { $(LINK) $(LINKFLAGS) /DLL /DEF:$(DEFFILENAME) /IMPLIB:$(IMPLIBNAME) /OUT:$(<) $(>) $(NEEDLIBS) $(LINKLIBS) } actions Shell { $(CP) $(>) $(<) } } } # # OS2 specific actions # else if $(OS2) { if $(JAM_TOOLSET) = WATCOM { actions together piecemeal Archive { $(AR) -q $(<) +-$(>) } actions Cc { $(CC) /Fo=$(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } actions C++ { $(C++) /Fo=$(<) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } actions Link bind NEEDLIBS { $(LINK) -q $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) } actions Shell { $(CP) $(>) $(<) } } else if $(JAM_TOOLSET) = EMX { actions together piecemeal Archive { $(AR) $(<) $(>:T) } actions Cc { $(CC) -c -o $(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } actions C++ { $(C++) -c -o $(<) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } } } # # VMS specific actions # else if $(VMS) { actions updated together piecemeal Archive { lib/replace $(<) $(>[1]) ,$(>[2-]) } actions Cc { $(CC)/obj=$(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } actions C++ { $(C++)/obj=$(<) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>) } actions piecemeal together existing Clean { $(RM) $(>[1]);* ,$(>[2-]);* } actions together quietly CreLib { if f$search("$(<)") .eqs. "" then lib/create $(<) } actions GenFile1 { mcr $(>[1]) $(<) $(>[2-]) } actions Link bind NEEDLIBS { $(LINK)/exe=$(<) $(LINKFLAGS) $(>:J=,) ,$(NEEDLIBS)/lib ,$(LINKLIBS) } actions quietly updated piecemeal together RmTemps { $(RM) $(>[1]);* ,$(>[2-]);* } actions Shell { $(CP) $(>) $(<) } } # # Mac specifc actions # else if $(MAC) { actions together Archive { $(LINK) -library -o $(<) $(>) } actions Cc { set -e MWCincludes $(CCHDRS) $(CC) -o $(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(>) } actions C++ { set -e MWCincludes $(CCHDRS) $(CC) -o $(<) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(>) } actions Link bind NEEDLIBS { $(LINK) -o $(<) $(LINKFLAGS) $(>) $(NEEDLIBS) "$(LINKLIBS)" } } if $(WIN98) { actions existing Clean { del $(>) } } # # Backwards compatibility with jam 1, where rules were uppercased. # rule BULK { Bulk $(<) : $(>) ; } rule FILE { File $(<) : $(>) ; } rule HDRRULE { HdrRule $(<) : $(>) ; } rule INSTALL { Install $(<) : $(>) ; } rule LIBRARY { Library $(<) : $(>) ; } rule LIBS { LinkLibraries $(<) : $(>) ; } rule LINK { Link $(<) : $(>) ; } rule MAIN { Main $(<) : $(>) ; } rule SETUID { Setuid $(<) ; } rule SHELL { Shell $(<) : $(>) ; } rule UNDEFINES { Undefines $(<) : $(>) ; } # Old INSTALL* didn't take dest directory. rule INSTALLBIN { InstallBin $(BINDIR) : $(<) ; } rule INSTALLLIB { InstallLib $(LIBDIR) : $(<) ; } rule INSTALLMAN { InstallMan $(MANDIR) : $(<) ; } # 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) ; } rule makeSubDir { $(<) = [ FSubDir $(>) ] ; } rule makeSuffixed { $(<[1]) = [ FAppendSuffix $(>) : $(<[2]) ] ; } # # special package-management rules # # check that the package root directory is set # otherwise, set it to $HOME/packages by default # # $(1) : list variable identifier # $(2) : new list # rule _PkgAppend { local result = $($(1)) ; local i ; for i in $(2) { if ! $(i) in $(result) { result += $(i) ; } } $(1) = $(result) ; } # $(1) : list variable identifier # $(2) : new list # rule _PkgPrepend { local result = $($(1)) ; local i ; for i in $(2) { if ! $(i) in $(result) { result = $(i) $(result) ; } } $(1) = $(result) ; } # $(1) : Package Name # $(2) : optional top-level installation directory # rule PkgBegin { if $(_PKG_NAME) { Echo "nested package declarations are not allowed. please use" Exit "PkgEnd to finish" $(_PKG_NAME)"'s declaration" ; } if ! $(PACKAGE_ROOT) { PACKAGE_ROOT = [ FDirName $(HOME) packages ] ; Echo "PACKAGE_ROOT variable not set, using" $(PACKAGE_ROOT) "directory" ; } _PKG_NAME = $(1[1]) ; _PKG_DESC = [ FDirName $(PACKAGE_ROOT) $(_PKG_NAME).pc ] ; _PKG_TOP = $(2) ; if ! $(_PKG_TOP) { _PKG_TOP = [ FDirName $(PACKAGE_ROOT) $(_PKG_NAME) ] ; } _PKG_ORG_HDRS = $(HDRS) ; _PKG_ORG_DEFINES = $(DEFINES) ; _PKG_ORG_LINKLIBS = $(LINKLIBS) ; _PKG_ORG_SUBDIRHDRS = $(SUBDIRHDRS) ; pkg-$(_PKG_NAME)-top = $(_PKG_TOP) ; _PKG_USES = ; _PKG_DEFINES = ; _PKG_INCLUDES = ; _PKG_LIBS = ; _PKG_DO_INSTALL = ; _PKG_ALL_USES = ; _PkgUpdate ; } rule PkgEnd { if $(_PKG_DO_INSTALL) { _PkgGeneratePc $(_PKG_DESC) ; PKG on $(_PKG_DESC) = $(_PKG_NAME) ; } HDRS = $(_PKG_ORG_HDRS) ; DEFINES = $(_PKG_ORG_DEFINES) ; LINKLIBS = $(_PKG_ORG_LINKLIBS) ; SUBDIRHDRS = $(_PKG_ORG_SUBDIRHDRS) ; _PKG_NAME = ; _PKG_DO_INSTALL = ; } # # rule _PkgReverse { local p ; result = $(1[1]) ; for p in $(1[2-]) { result = $(p) $(result) ; } return $(result) ; } # $(1) : package descriptor file path # rule _PkgGeneratePc { MkDir $(PACKAGE_ROOT) ; Depends $(1) : $(PACKAGE_ROOT) ; Depends install : $(1) ; Clean uninstall : $(1) ; Always $(1) ; # always re-install, overwrite old version } if $(UNIX) { actions _PkgGeneratePc { echo "# this file was generated automatically - do not edit" > $(1) echo "pkg-$(PKG)-uses = $(pkg-$(PKG)-uses) ;" >> $(1) echo "pkg-$(PKG)-libs = $(pkg-$(PKG)-libs:Q) ;" >> $(1) echo "pkg-$(PKG)-defines = $(pkg-$(PKG)-defines) ;" >> $(1) echo "pkg-$(PKG)-includes = $(pkg-$(PKG)-includes:Q) ;" >> $(1) echo "pkg-$(PKG)-ok = 1 ;" >> $(1) } } else { actions _PkgGeneratePc { echo # this file was generated automatically - do not edit > $(1) echo pkg-$(PKG)-uses = $(pkg-$(PKG)-uses) ; >> $(1) echo pkg-$(PKG)-libs = $(pkg-$(PKG)-libs:Q) ; >> $(1) echo pkg-$(PKG)-defines = $(pkg-$(PKG)-defines) ; >> $(1) echo pkg-$(PKG)-includes = $(pkg-$(PKG)-includes:Q) ; >> $(1) echo pkg-$(PKG)-ok = 1 ; >> $(1) } } rule PkgInstallPc { # nothing, this is now handled automatically by PkgEnd } # recomputes current package's settings whenever needed # # no arguments # rule _PkgUpdate { local p z ; _PKG_ALL_DEFINES = ; _PKG_ALL_INCLUDES = ; _PKG_ALL_LIBS = ; _PKG_USE_LIBS = ; for p in $(_PKG_ALL_USES) { _PkgAppend _PKG_ALL_DEFINES : $(pkg-$(p)-defines) ; _PkgAppend _PKG_ALL_INCLUDES : $(pkg-$(p)-includes) ; } for p in [ _PkgReverse $(_PKG_ALL_USES) ] { local thelibs = $(pkg-$(p)-libs) ; _PKG_ALL_LIBS += $(thelibs) ; _PKG_USE_LIBS += $(thelibs[1]) ; } _PkgAppend _PKG_ALL_DEFINES : $(_PKG_DEFINES) ; _PkgAppend _PKG_ALL_INCLUDES : $(_PKG_INCLUDES) ; HDRS = $(_PKG_ORG_HDRS) $(_PKG_ALL_INCLUDES) ; DEFINES = $(_PKG_ORG_DEFINES) $(_PKG_ALL_DEFINES) ; LINKLIBS = $(_PKG_ORG_LINKLIBS) $(_PKG_ALL_LIBS) ; pkg-$(_PKG_NAME)-includes = $(_PKG_INCLUDES) ; pkg-$(_PKG_NAME)-defines = $(_PKG_DEFINES) ; pkg-$(_PKG_NAME)-uses = $(_PKG_USES) ; pkg-$(_PKG_NAME)-libs = $(_PKG_LIBS) ; } # $(1) : list of packages to use # $(2) : name of missing packages variable # rule _PkgUses { local p ; for p in $(1) { if ! $(p) in $(_PKG_ALL_USES) { local pcfile = [ FDirName $(PACKAGE_ROOT) $(p).pc ] ; NoCare $(pcfile) ; include $(pcfile) ; if ! $(pkg-$(p)-ok) { $(2) += $(p) ; } else if $(pkg-$(p)-uses) { _PkgUses $(pkg-$(p)-uses) ; } _PKG_ALL_USES += $(p) ; } } } # $(1) : Package name list # rule PkgUses { local pkg-missing = ; _PkgUses $(1) : pkg-missing ; if $(pkg-missing) { Exit "Please install the following required packages:" $(pkg-missing) ; } _PkgPrepend _PKG_USES : $(1) ; _PkgUpdate ; } # $(1) : target directory # $(2) : list of sources relative to $(3) # $(3) : top source directory # rule _PkgMakeLocate { local top = $(3:E=$(DOT)) ; local dir file ss ; local dirs ; for ss in $(2) { file = [ FDirName $(top) $(ss:G="") ] ; dir = $(1) ; if $(ss:D) { dir = [ FDirName $(dir) $(ss:D) ] ; } LOCATE on $(ss) = $(1) ; Depends $(ss) : $(dir) ; if ! $(dir) in $(dirs) { dirs += $(dir) ; } } MkDir $(dirs) ; } # $(1) : target directory # $(2) : list of source files relative to $(3) # $(3) : top source directory # rule _PkgInstallInto { # InstallInto dir : sources ; local sources = $(2) ; local targets = $(sources:G=$(INSTALLGRIST)) ; # Arrange for jam install # Arrange for jam uninstall # sources are in SEARCH_SOURCE # targets are in dir Depends install : $(targets) ; Clean uninstall : $(targets) ; _PkgMakeLocate $(1) : $(targets) : $(3) ; # For each source, make gristed target name # and Install, Chmod, Chown, and Chgrp for s in $(sources) { local t = $(s:G=$(INSTALLGRIST)) ; Depends $(t) : $(s) ; SEARCH on $(s) = $(3) ; Install $(t) : $(s) ; Chmod $(t) ; if $(OWNER) && $(CHOWN) { Chown $(t) ; OWNER on $(t) = $(OWNER) ; } if $(GROUP) && $(CHGRP) { Chgrp $(t) ; GROUP on $(t) = $(GROUP) ; } } } # $(1) : target directory # $(2) : list of source binaries # $(3) : top source directory # rule _PkgInstallBin { local _t = [ FAppendSuffix $(>) : $(SUFEXE) ] ; _PkgInstallInto $(<) : $(_t) : $(3) ; MODE on $(_t:G=$(INSTALLGRIST)) = $(EXEMODE) ; } # $(1) : target directory # $(2) : list of source shells # $(3) : top source directory # rule _PkgInstallShell { _PkgInstallInto $(1) : $(2) : $(3) ; MODE on $(2:G=$(INSTALLGRIST)) = $(SHELLMODE) ; } # $(1) : target directory # $(2) : list of source files # $(3) : top source directory # rule _PkgInstallFile { _PkgInstallInto $(1) : $(2) : $(3) ; MODE on $(2:G=$(INSTALLGRIST)) = $(FILEMODE) ; } # $(1) : list of include paths # rule PkgIncludes { _PKG_INCLUDES += $(1) ; _PkgUpdate ; } rule PkgDefines { _PKG_DEFINES += $(1) ; _PkgUpdate ; } # $(1) : list of header files # $(2) : top-level source directory # $(3) : optional directory suffix # rule PkgInstallHeader { local dir = [ FDirName $(_PKG_TOP) include ] ; _PKG_DO_INSTALL = 1 ; _PkgInstallFile [ FDirName $(dir) $(3) ] : $(1) : $(2) ; _PkgAppend _PKG_INCLUDES : $(dir) ; _PkgUpdate ; } # $(1) : library name # rule PkgInstallLib { local lib = $(1:S=$(SUFLIB)) ; local dir = [ FDirName $(_PKG_TOP) lib ] ; _PKG_DO_INSTALL = 1 ; _PkgInstallFile $(dir) : $(lib) : $(DOT) ; _PkgPrepend _PKG_LIBS : [ FDirName $(dir) $(lib) ] ; _PkgUpdate ; } # $(1) : required library names or link flags # rule PkgNeedLib { _PkgAppend _PKG_LIBS : $(1) ; _PkgUpdate ; } rule PkgMain { MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ; Objects $(>) ; LINKLIBS on $(<:S=$(SUFEXE)) += $(LINKLIBS) ; Depends $(<:S=$(SUFEXE)) : $(_PKG_USE_LIBS) ; } # $(1) : list of directories relative to $(2) # $(2) : top search directory # $(3) : pattern # rule PkgGlob { local files dir ; files = [ GLOB [ FDirName $(2) $(1) ] : $(3) ] ; dir = [ FDirName $(1) ] ; return $(files:D=$(dir)) ; } # # Now include the user's Jamfile. # include $(JAMFILE) ;