Jambase #63

  • //
  • guest/
  • perforce_software/
  • jam/
  • src/
  • Jambase
  • View
  • Commits
  • Open Download .zip Download (45 KB)
#
# /+\
# +\	Copyright 1993-2019 Christopher Seiwald and Perforce Software, Inc.
# \+/
#
# This file is part of Jam - see jam.c for Copyright information.
#

#
# JAMBASE - jam 2.6.1 ruleset providing make(1)-like functionality
#
# Supports UNIX, NT, and VMS.
#
# 12/27/93 (seiwald) - purturb library sources with SOURCE_GRIST
# 04/18/94 (seiwald) - use '?=' 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.
# 12/08/03 (seiwald) - New YaccHdr to attribute #includes to generated .c.
# 11/22/13 (brett)   - Support for Darwin.

# 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.6.1)
#
# Special variables used by jam:
#	SEARCH - where to find something (used during binding and actions)
#	LOCATE - where to plop something not found with SEARCH
#	HDRRULE - rule to call to handle include files
#	HDRSCAN - egrep regex to extract include files
#
# Special targets:
#	all - default if none given on command line
#

# for perforce use -- jambase version

JAMBASEDATE = 2015.04.16  ;

# Initialize variables
#

#
# OS specific variable settings
#

if $(NT)
{
	MV			?= move /y ;
	CP			?= copy ;
	RM			?= del /f/q ;
	RMDIR		?= rmdir /s/q ;
	SLASH		?= \\ ;
	SUFLIB		?= .lib ;
	SUFOBJ		?= .obj ;
	SUFEXE		?= .exe ;

	if $(BCCROOT)	# Borland
	{
		AR			?= tlib /C /P64 ;
		CC			?= bcc32 ;
		CCFLAGS		?= -v -w- -q -DWIN -tWR -tWM -tWC ;
		C++			?= $(CC) ;
		C++FLAGS	?= $(CCFLAGS) -P ;
		LINK		?= $(CC) ;
		LINKFLAGS	?= $(CCFLAGS) ;
		STDLIBPATH	?= $(BCCROOT)\\lib ;
		STDHDRS		?= $(BCCROOT)\\include ;
		NOARSCAN	?= true ;
	}
	else			# Visual Studio 8 or later
	{
		local mflags ;
		switch $(OSPLAT)
		{
		case X86  :	AS ?= ml     ;
		case X64  :	AS ?= ml64   ;	mflags = -D_M_AMD64 /favor:blend ;
		case IA64 :	AS ?= ias    ;	mflags = -D_M_IA64 ;
		case ARM  :	AS ?= armasm ;  mflags = -D_M_ARM -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE ;
		}

		AR			?= lib /MACHINE:$(OSPLAT) ;
		CC			?= cl /nologo ;
		CCFLAGS		?= $(mflags) -DNT -D_CRT_SECURE_NO_DEPRECATE /wd4996 ;
		C++			?= $(CC) ;
		C++FLAGS	?= $(CCFLAGS) ;
		OPTIM		?= "" ;
		LINK		?= link /nologo ;
		LINKFLAGS	?= /MACHINE:$(OSPLAT) ;
		LINKLIBS	?= libcmt.lib oldnames.lib kernel32.lib ;
		STDHDRS     ?= ;
		UNDEFFLAG	?= "/u _" ;
	}
}
else if $(MINGW)
{
	CC			?= gcc ;
	C++			?= g++ ;
	LINK		?= gcc ;
	CCFLAGS 	+= -DMINGW ;
	RANLIB		?= ranlib ;

	MV			?= move /y ;
	CP			?= copy ;
	RM			?= del /f/q ;
	RMDIR		?= rmdir /s/q ;
	SLASH		?= \\ ;
	SUFEXE		?= .exe ;
}
else if $(MINGW64)
{
	CC			?= gcc ;
	C++			?= g++ ;
	LINK		?= gcc ;
	CCFLAGS 	+= -DMINGW64 ;
	RANLIB		?= ranlib ;

	MV			?= move /y ;
	CP			?= copy ;
	RM			?= del /f/q ;
	RMDIR		?= rmdir /s/q ;
	SLASH		?= \\ ;
	SUFEXE		?= .exe ;
}
else if $(OS2)
{
	WATCOM		?= $(watcom) ;

	if ! $(WATCOM)
	{
	    Exit On OS2, set WATCOM to the root of the Watcom directory. ;
	}

	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 $(AS400)
{
	C++			?= icc ;
	C++FLAGS	?= -DAS400 ;
	CC			?= icc ;
	CCFLAGS		?= -DAS400 ;
	LINK		?= icc ;
	LINKFLAGS	?= -qDUPPROC ;
	NOARSCAN	?= true ;
	AR			?= qar -cru ;
	RM			?= del ;
	CRELIB		?= true ;

	# QSYS Library to use for build output
	QSYSLIB 	?= jam ;
}
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 ;

}
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 :
	C++			?= g++ ;
	CC			?= gcc ;
	CCFLAGS 	+= -D_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		?= "" ;
	YACC		?= "" ;

	case NEXT :
	AR		?= libtool -o ;
	RANLIB		?= "" ;

	case MACOSX :
	C++			?= c++ ;
	MANDIR		?= /usr/local/share/man ;

	case DARWIN :
	C++			?= g++ ;
	CC			?= gcc ;
	CCFLAGS		+= -D__DARWIN__ ;
	C++FLAGS		+= -D__DARWIN__ ;
	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 ;
}

#
# 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		?= / ;
	STDHDRS		?= ;
	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
#

rule As
{
	Depends $(<) : $(>) ;
	ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
	ASHDRS on $(<) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
}

rule Bulk
{
	local i ;

	for i in $(>)
	{
	    File $(i:D=$(<)) : $(i) ;
	}
}


rule GetTargetVar
{
	on $(<) { return $($(>)) ; }
}

rule Cc
{
	local _s ;
	local _o ;

	_s = [ GetTargetVar $(<) : SUBDIRCCFLAGS ] ;
	_o = [ GetTargetVar $(<) : OPTIM ] ;

	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) $(_s) $(_o) ;

	CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
	CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}

rule C++
{
	local _s ;
	local _o ;

	_s = [ GetTargetVar $(<) : SUBDIRC++FLAGS ] ;
	_o = [ GetTargetVar $(<) : OPTIM ] ;

	Depends $(<) : $(>) ;

	if $(RELOCATE)
	{
	    CcMv $(<) : $(>) ;
	}

	C++FLAGS on $(<) += $(C++FLAGS) $(_s) $(_o) ;

	CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
	CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}

rule Chmod
{
	if $(CHMOD) { Chmod1 $(<) ; }
}

rule File
{
	Depends files : $(<) ;
	Depends $(<) : $(>) ;
	SEARCH on $(>) = $(SEARCH_SOURCE) ;
	MODE on $(<) = $(FILEMODE) ;
	Chmod $(<) ;
}

rule Fortran
{
	Depends $(<) : $(>) ;
}

rule GenFile
{
	local _t = [ FGristSourceFiles $(<) ] ;
	local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;
	Depends $(_t) : $(_s) $(>[2-]) ;
	GenFile1 $(_t) : $(_s) $(>[2-]) ;
	Clean clean : $(_t) ;
}

rule GenFile1
{
	MakeLocate $(<) : $(LOCATE_SOURCE) ;
	SEARCH on $(>) = $(SEARCH_SOURCE) ;
}

rule HardLink
{
	Depends files : $(<) ;
	Depends $(<) : $(>) ;
	SEARCH on $(>) = $(SEARCH_SOURCE) ;
}

rule HdrRule
{
	# HdrRule source : headers ;

	# N.B.	This rule is called during binding, potentially after
	# the fate of many targets has been determined, and must be
	# used with caution: don't add dependencies to unrelated
	# targets, and don't set variables on $(<).

	# Tell Jam that anything depending on $(<) also depends on $(>),
	# set SEARCH so Jam can find the headers, but then say we don't
	# care if we can't actually find the headers (they may have been
	# within ifdefs),

	local s = $(>:G=$(HDRGRIST:E)) ;

	Includes $(<) : $(s) ;
	NoCare $(s) ;

	# Propagate on $(<) to $(>)

	HDRSCAN on $(s) = $(HDRSCAN) ;
	HDRRULE on $(s) = $(HDRRULE) ;
	HDRGRIST on $(s) = $(HDRGRIST) ;
	HDRSEARCH on $(s) = $(HDRSEARCH) ;
	SEARCH on $(s) = $(HDRSEARCH) ;

	# If the including file has a hard-coded directory path $(<:D),
	# we need to add that, as a subdirectory of the existing header
	# search path, to SEARCH/HDRSEARCH.  We try to be careful not to
	# add duplicates.

	local d = $(<:D) ;
	local h ;

	if $(d)
	{
	    # Build unique list h = $(HDRSEARCH)/$(<:D)

	    for i in $(d:R=$(HDRSEARCH))
	    {
	    	if ! $(i) in $(HDRSEARCH) $(h) { h += $(i) ; }
	    }

	    # For each included file whose directory doesn't match the
	    # including file, add new subdirectories h to the search.

	    for i in $(s)
	    {
		if $(d) != $(i:D)
		{
		    HDRSEARCH on $(i) += $(h) ;
		    SEARCH on $(i) += $(h) ;
		}
	    }
	}
}

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) ;
	    }
	}
}

rule InstallBin
{
	local _t = [ FAppendSuffix $(>) : $(SUFEXE) ] ;

	InstallInto $(<) : $(_t) ;
	MODE on $(_t:G=$(INSTALLGRIST)) = $(EXEMODE) ;
}

rule InstallFile
{
	InstallInto $(<) : $(>) ;
	MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
}

rule InstallLib
{
	InstallInto $(<) : $(>) ;
	MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
}

rule InstallMan
{
	# Really this just strips the . from the suffix

	local i s d ;

	for i in $(>)
	{
	    switch $(i:S)
	    {
	    case .1 : s = 1 ; case .2 : s = 2 ; case .3 : s = 3 ;
	    case .4 : s = 4 ; case .5 : s = 5 ; case .6 : s = 6 ;
	    case .7 : s = 7 ; case .8 : s = 8 ; case .l : s = l ;
	    case .n : s = n ; case .man : s = 1 ;
	    }

	    d = man$(s) ;

	    InstallInto $(d:R=$(<)) : $(i) ;
	}

	MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
}

rule InstallShell
{
	InstallInto $(<) : $(>) ;
	MODE on $(>:G=$(INSTALLGRIST)) = $(SHELLMODE) ;
}

rule Lex
{
	LexMv $(<) : $(>) ;
	Depends $(<) : $(>) ;
	MakeLocate $(<) : $(LOCATE_SOURCE) ;
	Clean clean : $(<) ;
}

rule Library
{
	LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
	Objects $(>) ;
}

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) ; }
}

rule Link
{
	MODE on $(<) = $(EXEMODE) ;
	Chmod $(<) ;
}

rule LinkLibraries
{
	# make library dependencies of target
	# set NEEDLIBS variable used by 'actions Main'

	local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;

	Depends $(_t) : $(>:S=$(SUFLIB)) ;
	NEEDLIBS on $(_t) += $(>:S=$(SUFLIB)) ;
}

rule Main
{
	MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
	Objects $(>) ;
}

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) ;

	Link $(_t) : $(_s) ;
}

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) ;
	    MkDir $(>[1]:G=dir) ;
	}
}

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)
	{
	    # 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 = ;
		}
	    }

	    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) ;
	    }
	}
}

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 .f :	Fortran $(<) : $(>) ;
	    case .l :	Cc $(<) : $(<:S=.c) ;
		            Lex $(<:S=.c) : $(>) ;
	    case .m :	Cc $(<) : $(>) ;
	    case .mm :	Cc $(<) : $(>) ;
	    case .s :	As $(<) : $(>) ;
	    case .y :	Cc $(<) : $(<:S=$(YACCGEN)) ;
		            Yacc $(<:S=$(YACCGEN)) : $(>) ;
	    case * :	UserObject $(<) : $(>) ;
	}
}

rule ObjectCcFlags
{
	CCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
}

rule ObjectC++Flags
{
	C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
}

rule ObjectDefines
{
	# must reformat CCDEFS according to current defines

	local s = [ FGristFiles $(<:S=$(SUFOBJ)) ] ;

	DEFINES on $(s) += $(>) ;
	CCDEFS on $(s) = [ on $(s) FDefines $(DEFINES) ] ;
}

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) ] ;
}

rule Objects
{
	local _i ;

	for _i in [ FGristFiles $(<) ]
	{
		Object $(_i:S=$(SUFOBJ)) : $(_i) ;
		Depends obj : $(_i:S=$(SUFOBJ)) ;
	}
}

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 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) ;

	# Handle #includes in .y file

	HDRRULE on $(>) = YaccHdr ;
}

rule YaccHdr
{
	# YaccHdr .y : hdrs ;
	# For yacc, includes are actually on the generated
	# .c file, not on the source .y.

	HdrRule $(<:S=$(YACCGEN)) : $(>) ;
}

#
# Utility rules; no side effects on these
#

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
{
	# 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 _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)
{
	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) $(CCDEFS) $(CCHDRS) $(>)
}

actions Cc
{
	$(CC) -c -o $(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) $(>)
}

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) $(CCDEFS) $(CCHDRS) $(>)
	}

	actions Cc
	{
	$(CC) -c $(CCFLAGS) $(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-])
	}
}

if $(AS400)
{
	#
	# AS/400's unix-style compiler, linker and archiver use the OUTPUTDIR
	# environment variable to decide which QSYS library the output file
	# should be placed in. These actions make sure that variable is
	# set when the command is run.
	#

	actions updated piecemeal Archive
	{
	    OUTPUTDIR=$(QSYSLIB) $(AR) $(<) $(>)
	}

	actions Cc
	{
	    OUTPUTDIR=$(QSYSLIB) $(CC) -c -o $(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) $(>)
	}

	actions C++
	{
	    OUTPUTDIR=$(QSYSLIB) $(C++) -c -o $(<) $(C++FLAGS) $(CCDEFS) $(CCHDRS) $(>)
	}

	actions Link bind NEEDLIBS
	{
	    OUTPUTDIR=$(QSYSLIB) $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
	}

	#
	# On AS/400 we pre-create libraries by creating a symlink to a
	# Bound Directory in the QSYS library where the output goes. This
	# helps qar get the library name right.
	#

	actions CreLib
	{
	    dest=`echo $(<) | sed -e 's#.*/\([^/]*\)\.a$#/qsys.lib/$(QSYSLIB).lib/\1.bnddir#'`
	    [ -h $(<) ] || ln -s $dest $(<)
	}

}

#
# NT specific actions
#

if $(NT) && $(BCCROOT)
{
	actions updated together piecemeal Archive
	{
	$(AR) $(<) -+$(>)
	}

	actions Link bind NEEDLIBS
	{
	$(LINK) -e$(<) $(LINKFLAGS) $(UNDEFS) -L$(LINKLIBS) $(NEEDLIBS) $(>)
	}

	actions C++
	{
	$(C++) -c -o$(<) $(C++FLAGS) $(CCDEFS) $(CCHDRS) $(>)
	}

	actions Cc
	{
	$(CC) -c -o$(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) $(>)
	}
}
else if $(NT)
{
	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) $(CCDEFS) $(CCHDRS) /I"$(STDHDRS)" $(>)
	}

	actions C++
	{
	$(C++) /c /Fo$(<) $(C++FLAGS) $(CCDEFS) $(CCHDRS) /I"$(STDHDRS)" /Tp$(>)
	}

	actions Link bind NEEDLIBS
	{
	$(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) "$(LINKLIBS)"
	}
}

#
# OS2 specific actions
#

else if $(OS2) && $(WATCOM)
{
	actions together piecemeal Archive
	{
	$(AR) $(<) +-$(>)
	}

	actions Cc
	{
	$(CC) /Fo=$(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) $(>)
	}

	actions C++
	{
	$(C++) /Fo=$(<) $(C++FLAGS) $(CCDEFS) $(CCHDRS) $(>)
	}

	actions Link bind NEEDLIBS
	{
	$(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
	}

	actions Shell
	{
	$(CP) $(>) $(<)
	}
}

#
# VMS specific actions
#

else if $(VMS)
{
	actions updated together piecemeal Archive
	{
	lib/replace $(<) $(>[1]) ,$(>[2-])
	}

	actions Cc
	{
	$(CC)/obj=$(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) $(>)
	}

	actions C++
	{
	$(C++)/obj=$(<) $(C++FLAGS) $(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) $(CCDEFS) $(>)
	}

	actions C++
	{
	set -e MWCincludes $(CCHDRS)
	$(CC) -o $(<) $(C++FLAGS) $(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]) ] ; }

#
# Now include the user's Jamfile.
#

include $(JAMFILE) ;
# Change User Description Committed
#63 25730 Jason Gibson Source update for the 2.6.1 release.
#62 23298 Nick Poole Updating Jam source

The changes here include a simplified Windows build process:
the makefile now has 2 MSVC sections, one 32-bit the other
64-bit.
#61 9883 brett Build rules for jam on Darwin 9.0.


p4transfer.py: Transferred from production
#60 9882 brett Update build rules for AIX53.


p4transfer.py: Transferred from production
#59 9881 noahf Eliminate hateful MSVCNT variable and the need to set it.
Consolidate all the Visual Studio configuration sections.


p4transfer.py: Transferred from production
#58 9880 noahf Add defaults for NT ARM.


p4transfer.py: Transferred from production
#57 9879 brett On a Windows debug build the /MT flag was used in addition to
the /MTd flag.  Basically harmless except the compiler issued
a warning for every file compiled.

Removed the use of the /MT flag in the jambase arena.  This
allows the Jamrules to properly set this flag as required.

Also when doing a Smart Heap debug build, duplicate symbols
in the Smart Heap library conflicted with the standard
Windows CRT library.  Adding a /FORCE to the link line solves
this problem.  This is a very narrow case and should not effect
builds without Smart Heap.

Jam must be rebuilt to remove the /MT and /MTd warning.


p4transfer.py: Transferred from production
#56 9878 brett Remove hard coded paths to the Visual Studio SDK libraries.

As of Visual Studio 2008 and including 2010 the SDK libraries,
like kernel32.lib, have been moved out of the VC directory
structure.  These hard coded paths prevented jam from building.

Test built jam with VS2005 x64 and x86, VS2010 x64 and x86
with these new settings.

Test built main/p4 in these combinations as well.


p4transfer.py: Transferred from production
#55 9877 marc *Significant* MD5 speedups

This change requires a new Jambase, so, a new Jam, to take full
advantage.

Jambase: Now we handle local variables OPTIM, SUBDIRC++FLAGS, and
SUBDIRCCFLAGS on targets correctly.  This was a change contemplated
ages ago on the jamming@ mailing list but never committed.

md5.cc: We no longer do byte-swabbing on temporary buffers,
we use a union to treat buffers as char * or uint32 *. We have
re-ordered the MD5STEP macros to be faster slightly based on
Wei Dai's "Public Domain" crypto++ 5.6.1 routines.

md5.h: We now align our buffers (per Wittenberg's recommendation) for
those machines both where it's faster to do so. Windows will be next?

Mostly reviewed by development.

Infrastructure change.


p4transfer.py: Transferred from production
#54 9876 noahf Add shell command definitions for MINGW.


p4transfer.py: Transferred from production
#53 9875 mbishop Added Objective-C and Objective-C++ support to the Jambase.


p4transfer.py: Transferred from production
#52 9874 tony Port 2008.1 P4 to MVS Unix System Services.
This is an onsite
port carried out at Bank of America in Croydon.

It's not pretty. There are some uglies in here which could
probably be taken care of in better ways, but I was pressed
for time. Here's the background to each of the issues I found:

1. The compiler really didn't like our Zeroconf
code, and since building Avahi on the mainframe wasn't top of
my agenda, I disabled it with some heinous ifdef's in client.cc.
Sorry. The compiler was bitching about types of arguments being
passed to zeroconf methods, and it wasn't obvious to me what the
problem was either. I think we could use a -DUSE_ZEROCONF in
our Jamrules for occasions like this; that would be cleaner than
a platform ifdef in client.cc. With more time, it might be
possible to make the zeroconf code compile on MVS, but getting
dynamic loading working on that platform is ambitious I think.

2. The mapping code needed ifdefs too (again, sorry!). On MVS,
C and C++ don't share the same linkage and qsort() is a C function
so it (apparently) can't take a pointer to a C++ function. So,
all the qsort() compare functions have to be declared as
'extern "C"'. See:

http://publib.boulder.ibm.com/infocenter/zos/v1r9/index.jsp?topic=/com.ibm.zos.r9.bpxbd00/qsort.htm

I didn't ifdef these as I don't think they'll do any harm on other
platforms.

3. support/random.cc needed an ifdef (no big deal)

4. sys/netaddr.cc had to have a (correct) const removed since
the MVS implementation of inet_addr takes a 'char *' argument
instead of 'const char *'. I ifdef'd that to keep it clean
on other platforms.

5. zlib/zconf.h had some old pragmas that no longer apply.

6. Jamrules: I reinstated the old rules from MVS builds, and
made EBCDIC optional rather than compulsory. I also
documented in it the environment variables we set to persuade
the compilers on BofA's machine to behave. These may, or may not
be required on other MVS boxes. No idea.

Building Jam also had a few idiosyncracies:

1. Best to assume the yacc on MVS is broken. It was there, but
not in great shape. I disabled it in Jambase and I think that's
a sensible thing to do going forward.

2. yylineno() can't return a 'const int' on MVS. Not sure why
it's defined that way on other platforms so I changed it to
just returning an int. Hopefully that won't break elsewhere...


There are three binaries being submitted here:

    jam            - built from main
    bin.mvs/p4        - EBCDIC client
    bin.mvs/ascii/p4    - Non-EBCDIC client

The ascii client identifies itself as such:

    P4/MVS/2008.1.ascii/164042

While unconventional, I thought that was the best plan so that
if we take support calls on it, we'll get a clue.


p4transfer.py: Transferred from production
#51 9873 noahf Don't hardcode paths to SDK libraries on ia64.
The LIB search path should come from the environment.


p4transfer.py: Transferred from production
#50 9872 noahf Remove -D_CRT_SECURE_NO_DEPRECATE for ntia64.
Not supported.


p4transfer.py: Transferred from production
#49 9871 noahf Add settings for IA64 VS2005.

Add /MT flags to other VS2005 sections and change libc.lib to libcmt.lib.
VS2005 doesn't have libc.lib anymore.

Remove \\$(I) ia64 hack from VS6 section and from the other sections in
which it appears uninitialized.


p4transfer.py: Transferred from production
#48 9870 brett Followon change to 142516.

The x86 build was using VS2003 with the VS2005 flags.

Placed the VS2003 x86 build rules before the VS2005 x86 build
rules and accounted for both MSVCDIR and MSVCDir.


p4transfer.py: Transferred from production
#47 9869 brett Move the /MT flag for NET 2005 into jam's Jamfile and out
of the Jambase file.  This removes the conflict with the
various TYPE=dyn, TYPE=dyng and so on, yet compiles jam as
multi threaded.


p4transfer.py: Transferred from production
#46 9868 brett Build jam on Windows using NET 2005 in X86 mode.
This is the counter part to NET 2005 in X64 mode.


p4transfer.py: Transferred from production
#45 9867 noahf Follow-on to change 129197: Update JAMBASEDATE and submit updated
jambase.c generated from Jambase.


p4transfer.py: Transferred from production
#44 9866 noahf Use $(MSVCNT:J=" ") and $(MSVC:J=" ") when constructing paths, since
spaces in the inherited environment variable are part of a scalar
value (a file name), not separators within an array.

This is probably still going to blow chunks if MSVCNT contains a
path where there are two or more adjacent spaces somewhere (since
the join will result in a nonexistent filename), but that's an
unlikely case whereas single spaces in NT filenames are pervasive.
To really do this right, Jam needs a way to treat variables
inherited from the environment as a single value without any array
tokenization.  At least sometimes.

For the MSVC/MSVCNT special case actions Cc, C++, and Link: put quotes
around the expansion of $(STDHDRS) and $(LINKLIBS) so the batch
interpreter won't split space-embedded pathnames into multiple
arguments.  Note that it's the operating system's command interpreter,
not Jam, which needs the quoting against whitespace this time.
Multiple values within these variables are still expanded correctly
at the Jam level.


p4transfer.py: Transferred from production
#43 9865 noahf * Build.com: Compile jamgram.c with /NOOPTIMIZE.
  The V7.2-021 cxx compiler on VMS8.2/IA64 has trouble with the parser
  produced by either (b)yacc or bison: when jamgram.c is compiled with
  optimization levels at or above /OPTIMIZE=(LEVEL=2), jam.exe crashes
  as soon as it begins to parse its internal copy of Jambase.  (The
  default optmization level is /OPTIMIZE=(LEVEL=4), by the way.)

* Build.com: Display commands in build.com as they are executed, since
  there is no other progress notification.

* Jambase ($(VMS)): Remove special cases for OS=OPENVMS and OS=VMS;
  Newer compilers do not accept "vaxc" as a C dialect, and vaxcrtl.olb
  does not exist on IA64.

  There is no real difference between VMS and OPENVMS; the latter is
  just marketingspeak.  Having both OS=VMS and OS=OPENVMS switches is
  probably more confusing than helpful; if in the future these flags
  need to be restored, consider using some combination of OSPLAT and/or
  OSVER also.


p4transfer.py: Transferred from production
#42 9864 brett Followup change to 83464, /MT flag should not be in the base rule
for thw Windows amd64 build.


p4transfer.py: Transferred from production
#41 9863 Perforce staff Fix jam HdrRule change 79346 -- it has horrible combinatoric
behavior when you have system include files that go like this:

    arpa/something includes
    sys/something includes
    machine/something includes
    sys/something-else

Now HdrRule tries to be as conservative as possible to avoid
building monster SEARCH lists.

This is needed for AIX 5.3, where they apparently have such wild
include mazes.

Change to unreleased behavior.


p4transfer.py: Transferred from production
#40 9862 brett An attempt at sorting out the various 64bit Windows builds.

IA64 indicates the Intel Itanium 64bit Windows build.
X64 indicates the AMD64 and the Intel EM64T 64bit Windows build.

It should not be necessary to set MSVCVer or OSPLAT for these builds.

Hopefully these changes didn't break the AMD64 Linux build.


p4transfer.py: Transferred from production
#39 9861 brett Add the _M_AMD64 flag to the amd64 build.
 The rest does indeed
produce x64 binaries as verified by dumpbin /headers p4d.exe.

With change 81112, the x64 p4d.exe no longer faults.


p4transfer.py: Transferred from production
#38 9860 brett A few more amd64 build changes.
 Remove conflicting /MT /MTd flags.
Remove common7 from jamsh.bat PATH setting.

As a note, built a 64bit p4d.exe without smartheap.  This port
is going to be some work.  For starters, _get_osfhandle() now
has checks which fault the server.  It's not clear on what it
will take to resolve this.  I suspect MS has a bunch more issues
like this which must be addressed for the port.


p4transfer.py: Transferred from production
#37 9859 brett Jam changes for building on the AMD64 platform.
 The .NET 2005
beta2 compiler requires several flags.  First it is necessary
to turn off the depreciation stuff, CRT functions like strcpy
sprintf and so on are now viewed as insecure by MS.  For now it
is still possible to use them with the correct application of
compile flags.  MS is making noises in line with taking these
functions away for good.

The "Win64" token was used for 64 bit builds.  This is now a
bit ambiguous since it covers x64, ia64 and em64t.  With this
change Win64 has been retired and we use x64 for amd64, ia64
for the Itanium and em64t for the extended memory processors.
Set MSVCVer accordingly.  MSVCNT is set as always, to the
location of the VC directory, VC98, VC7 and now just VC.

For the most part the x64 build works on amd64, the exception
being a template problem in nettcp.cc.  That problem will not
be corrected in this change.


p4transfer.py: Transferred from production
#36 9858 tony jam and 2004.2 p4 client for AS/400.
Built on AS/400 V5R2 with native
ILE C/C++ compiler. Note, this build reports itself as
P4/AS400/2004.2/76944 but this change contains porting changes that
were required to make the build work so the changelist number is incorrect.
This can be resolved with a clean build for 2005.1 at a later date.

p4.sav and jam.sav are AS/400 "Save Files" that can be used to install
the software on an AS/400 machine. The p4.sav file includes the p4.cmd
and p4sync.cmd files we distributed with our older AS/400 builds. These
files define a forms-type interface for supplying the parameters to the
commands when you run them.

Porting change only. No functional change.


p4transfer.py: Transferred from production
#35 9857 Perforce staff Fix to HdrRule to handle '#include "path/file"': if the included
file has a directory component, then SEARCH and HDRSEARCH are set
to include the previous HDRSEARCH with 'path' appended. Without
this, then any files included by "path/file" might not be found
by jam, as it didn't know to look in the 'path' subdirectory.

This is needed for p4v's central 'windows' include file.


p4transfer.py: Transferred from production
#34 9856 Perforce staff Jam's Yacc rule now puts include dependencies on the generated
.c rather than on the .y.

Bug fix documented in RELNOTES.


p4transfer.py: Transferred from production
#33 3070 Perforce staff Two Jambase changes: one fix, one enhancement.

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

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

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

    SubDir ALL src builds ;
    SubInclude ALL src server support ;

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

Bug fix documented in RELNOTES.

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

Porting change, noted in RELNOTES.

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

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

timer.cc: use long long for timer.

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

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

Porting changes, noted in RELNOTES.

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

Fix to bug introduced by 2.5rc1.

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

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

Undocumented.

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

Porting change documented in RELNOTES.

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

Porting change documented in RELNOTES.

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

New feature documented in RELNOTES.

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

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

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

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

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

No functional change.

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

User visible change documented in RELNOTES.

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

Also bumped patchlevel to 2.4.2 capriciously.

Change to unreleased behavior.

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

Porting change.

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

Porting change.

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

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

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

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

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

Infrastructure change.

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

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

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

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

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

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

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

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

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

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

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

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

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