1#
2# /+\
3# +\	Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4# \+/
5#
6# This file is part of Jam - see jam.c for Copyright information.
7#
8
9#
10# JAMBASE - jam 2.5 ruleset providing make(1)-like functionality
11#
12# Supports UNIX, NT, and VMS.
13#
14# 12/27/93 (seiwald) - purturb library sources with SOURCE_GRIST
15# 04/18/94 (seiwald) - use '?=' when setting OS specific vars
16# 04/21/94 (seiwald) - do RmTemps together
17# 05/05/94 (seiwald) - all supported C compilers support -o: relegate
18#		       RELOCATE as an option; set Ranlib to "" to disable it
19# 06/01/94 (seiwald) - new 'actions existing' to do existing sources
20# 08/25/94 (seiwald) - new ObjectCcFlags rule to append to per-target CCFLAGS
21# 08/29/94 (seiwald) - new ObjectHdrs rule to append to per-target HDRS
22# 09/19/94 (seiwald) - LinkLibraries and Undefs now append
23#		     - Rule names downshifted.
24# 10/06/94 (seiwald) - Dumb yyacc stuff moved into Jamfile.
25# 10/14/94 (seiwald) - (Crude) support for .s, .C, .cc, .cpp, and .f files.
26# 01/08/95 (seiwald) - Shell now handled with awk, not sed
27# 01/09/95 (seiwald) - Install* now take dest directory as target
28# 01/10/95 (seiwald) - All entries sorted.
29# 01/10/95 (seiwald) - NT support moved in, with LauraW's help.
30# 01/10/95 (seiwald) - VMS support moved in.
31# 02/06/95 (seiwald) - ObjectC++Flags and SubDirC++Flags added.
32# 02/07/95 (seiwald) - Iron out when HDRSEARCH uses "" or SEARCH_SOURCE.
33# 02/08/95 (seiwald) - SubDir works on VMS.
34# 02/14/95 (seiwald) - MkDir and entourage.
35# 04/30/95 (seiwald) - Use install -c flag so that it copies, not moves.
36# 07/10/95 (taylor) - Support for Microsoft C++.
37# 11/21/96 (peterk) - Support for BeOS
38# 07/19/99 (sickel) - Support for Mac OS X Server (and maybe client)
39# 02/18/00 (belmonte)- Support for Cygwin.
40# 12/08/03 (seiwald) - New YaccHdr to attribute #includes to generated .c.
41# 11/22/13 (brett)   - Support for Darwin.
42
43# Special targets defined in this file:
44#
45# all		- parent of first, shell, files, lib, exe
46# first		- first dependent of 'all', for potential initialization
47# shell		- parent of all Shell targets
48# files		- parent of all File targets
49# lib		- parent of all Library targets
50# exe		- parent of all Main targets
51# dirs		- parent of all MkDir targets
52# clean		- removes all Shell, File, Library, and Main targets
53# uninstall	- removes all Install targets
54#
55
56# Rules defined by this file:
57#
58# as obj.o : source.s ;			.s -> .o
59# Bulk dir : files ;			populate directory with many files
60# Cc obj.o : source.c ;			.c -> .o
61# C++ obj.o : source.cc ;		.cc -> .o
62# Clean clean : sources ;		remove sources with 'jam clean'
63# File dest : source ;			copy file
64# Fortran obj.o : source.f ;		.f -> .o
65# GenFile source.c : program args ;	make custom file
66# HardLink target : source ;		make link from source to target
67# HdrRule source : headers ;		handle #includes
68# InstallInto dir : sources ;		install any files
69# InstallBin dir : sources ;		install binaries
70# InstallLib dir : sources ;		install files
71# InstallFile dir : sources ;		install files
72# InstallMan dir : sources ;		install man pages
73# InstallShell dir : sources ;		install shell scripts
74# Lex source.c : source.l ;		.l -> .c
75# Library lib : source ;		archive library from compiled sources
76# LibraryFromObjects lib : objects ;	archive library from objects
77# LinkLibraries images : libraries ;	bag libraries onto Mains
78# Main image : source ;			link executable from compiled sources
79# MainFromObjects image : objects ;	link executable from objects
80# MkDir dir ;				make a directory, if not there
81# Object object : source ;		compile object from source
82# ObjectCcFlags source : flags ;	add compiler flags for object
83# ObjectC++Flags source : flags ;	add compiler flags for object
84# ObjectHdrs source : dirs ;		add include directories for object
85# Objects sources ;			compile sources
86# RmTemps target : sources ;		remove temp sources after target made
87# Setuid images ;			mark executables Setuid
88# SoftLink target : source ;		make symlink from source to target
89# SubDir TOP d1 d2 ... ;		start a subdirectory Jamfile
90# SubDirCcFlags flags ;			add compiler flags until next SubDir
91# SubDirC++Flags flags ;		add compiler flags until next SubDir
92# SubDirHdrs d1 d2 ... ;		add include dir until next SubDir
93# SubInclude TOP d1 d2 ... ;		include a subdirectory Jamfile
94# Shell exe : source ;			make a shell executable
95# Undefines images : symbols ;		save undef's for linking
96# UserObject object : source ;		handle unknown suffixes for Object
97# Yacc source.c : source.y ;		.y -> .c
98#
99# Utility rules that have no side effects (not supported):
100#
101# FAppendSuffix f1 f2 ... : $(SUF) ; 	return $(<) with suffixes
102# FDirName d1 d2 ... ;			return path from root to dir
103# FGrist d1 d2 ... ;			return d1!d2!...
104# FGristFiles value ;			return $(value:G=$(SOURCE_GRIST))
105# FGristSourceFiles value ;		return $(value:G=$(SOURCE_GRIST))
106# FStripCommon v1 : v2 ; 		strip common initial parts of v1 v2
107# FReverse a1 a2 ... ;			return ... a2 a1
108# FRelPath d1 : d2 ;			return rel path from d1 to d2
109# FSubDir d1 d2 ... ;			return path to root
110#
111
112
113# Brief review of the jam language:
114#
115# Statements:
116#	rule RULE - statements to process a rule
117#	actions RULE - system commands to carry out target update
118#
119# Modifiers on actions:
120#	together - multiple instances of same rule on target get executed
121#		   once with their sources ($(>)) concatenated
122#	updated - refers to updated sources ($(>)) only
123#	ignore - ignore return status of command
124#	quietly - don't trace its execution unless verbose
125#	piecemeal - iterate command each time with a small subset of $(>)
126#	existing - refers to currently existing sources ($(>)) only
127#	bind vars - subject to binding before expanding in actions
128#
129# Special rules:
130#	Always - always build a target
131#	Depends - builds the dependency graph
132#	Echo - blurt out targets on stdout
133#	Exit - blurt out targets and exit
134#	Includes - marks sources as headers for target (a codependency)
135#	NoCare - don't panic if the target can't be built
136#	NoUpdate - create the target if needed but never update it
137#	NotFile - ignore the timestamp of the target (it's not a file)
138#	Temporary - target need not be present if sources haven't changed
139#
140# Special variables set by jam:
141#	$(<) - targets of a rule (to the left of the :)
142#	$(>) - sources of a rule (to the right of the :)
143#	$(xxx) - true on xxx (UNIX, VMS, NT, OS2, MAC)
144#	$(OS) - name of OS - varies wildly
145#	$(JAMVERSION) - version number (2.5)
146#
147# Special variables used by jam:
148#	SEARCH - where to find something (used during binding and actions)
149#	LOCATE - where to plop something not found with SEARCH
150#	HDRRULE - rule to call to handle include files
151#	HDRSCAN - egrep regex to extract include files
152#
153# Special targets:
154#	all - default if none given on command line
155#
156
157# for perforce use -- jambase version
158
159JAMBASEDATE = 2012.10.04  ;
160
161# Initialize variables
162#
163
164#
165# OS specific variable settings
166#
167
168if $(NT)
169{
170	MV			?= move /y ;
171	CP			?= copy ;
172	RM			?= del /f/q ;
173	RMDIR		?= rmdir /s/q ;
174	SLASH		?= \\ ;
175	SUFLIB		?= .lib ;
176	SUFOBJ		?= .obj ;
177	SUFEXE		?= .exe ;
178
179	if $(BCCROOT)	# Borland
180	{
181		AR			?= tlib /C /P64 ;
182		CC			?= bcc32 ;
183		CCFLAGS		?= -v -w- -q -DWIN -tWR -tWM -tWC ;
184		C++			?= $(CC) ;
185		C++FLAGS	?= $(CCFLAGS) -P ;
186		LINK		?= $(CC) ;
187		LINKFLAGS	?= $(CCFLAGS) ;
188		STDLIBPATH	?= $(BCCROOT)\\lib ;
189		STDHDRS		?= $(BCCROOT)\\include ;
190		NOARSCAN	?= true ;
191	}
192	else			# Visual Studio 8 or later
193	{
194		local mflags ;
195		switch $(OSPLAT)
196		{
197		case X86  :	AS ?= ml     ;
198		case X64  :	AS ?= ml64   ;	mflags = -D_M_AMD64 /favor:blend ;
199		case IA64 :	AS ?= ias    ;	mflags = -D_M_IA64 ;
200		case ARM  :	AS ?= armasm ;  mflags = -D_M_ARM -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE ;
201		}
202
203		AR			?= lib /MACHINE:$(OSPLAT) ;
204		CC			?= cl /nologo ;
205		CCFLAGS		?= $(mflags) -DNT -D_CRT_SECURE_NO_DEPRECATE /wd4996 ;
206		C++			?= $(CC) ;
207		C++FLAGS	?= $(CCFLAGS) ;
208		OPTIM		?= "" ;
209		LINK		?= link /nologo ;
210		LINKFLAGS	?= /MACHINE:$(OSPLAT) ;
211		LINKLIBS	?= libcmt.lib oldnames.lib kernel32.lib ;
212		STDHDRS     ?= ;
213		UNDEFFLAG	?= "/u _" ;
214	}
215}
216else if $(MINGW)
217{
218	CC			?= gcc ;
219	C++			?= g++ ;
220	LINK		?= gcc ;
221	CCFLAGS 	+= -DMINGW ;
222	RANLIB		?= ranlib ;
223
224	MV			?= move /y ;
225	CP			?= copy ;
226	RM			?= del /f/q ;
227	RMDIR		?= rmdir /s/q ;
228	SLASH		?= \\ ;
229	SUFEXE		?= .exe ;
230}
231else if $(OS2)
232{
233	WATCOM		?= $(watcom) ;
234
235	if ! $(WATCOM)
236	{
237	    Exit On OS2, set WATCOM to the root of the Watcom directory. ;
238	}
239
240	AR			?= wlib ;
241	BINDIR		?= \\os2\\apps ;
242	CC			?= wcc386 ;
243	CCFLAGS		?= /zq /DOS2 /I$(WATCOM)\\h ; # zq=quiet
244	C++			?= wpp386 ;
245	C++FLAGS	?= $(CCFLAGS) ;
246	CP			?= copy ;
247	DOT			?= . ;
248	DOTDOT		?= .. ;
249	LINK		?= wcl386 ;
250	LINKFLAGS	?= /zq ; # zq=quiet
251	LINKLIBS	?= ;
252	MV			?= move ;
253	NOARSCAN	?= true ;
254	OPTIM		?= ;
255	RM			?= del /f ;
256	SLASH		?= \\ ;
257	STDHDRS		?= $(WATCOM)\\h ;
258	SUFEXE		?= .exe ;
259	SUFLIB		?= .lib ;
260	SUFOBJ		?= .obj ;
261	UNDEFFLAG	?= "/u _" ;
262
263}
264else if $(AS400)
265{
266	C++			?= icc ;
267	C++FLAGS	?= -DAS400 ;
268	CC			?= icc ;
269	CCFLAGS		?= -DAS400 ;
270	LINK		?= icc ;
271	LINKFLAGS	?= -qDUPPROC ;
272	NOARSCAN	?= true ;
273	AR			?= qar -cru ;
274	RM			?= del ;
275	CRELIB		?= true ;
276
277	# QSYS Library to use for build output
278	QSYSLIB 	?= jam ;
279}
280else if $(VMS)
281{
282	C++			?= cxx ;
283	C++FLAGS	?= ;
284	CC			?= cc ;
285	CCFLAGS		?= ;
286	CHMOD		?= set file/prot= ;
287	CP			?= copy/replace ;
288	CRELIB		?= true ;
289	DOT			?= [] ;
290	DOTDOT		?= [-] ;
291	EXEMODE		?= (w:e) ;
292	FILEMODE	?= (w:r) ;
293	HDRS		?= ;
294	LINK		?= link ;
295	LINKFLAGS	?= "" ;
296	LINKLIBS	?= ;
297	MKDIR		?= create/dir ;
298	MV			?= rename ;
299	OPTIM		?= "" ;
300	RM			?= delete ;
301	RUNVMS		?= mcr ;
302	SHELLMODE	?= (w:er) ;
303	SLASH		?= . ;
304	STDHDRS		?= decc$library_include ;
305	SUFEXE		?= .exe ;
306	SUFLIB		?= .olb ;
307	SUFOBJ		?= .obj ;
308
309}
310else if $(MAC)
311{
312	local OPT ;
313
314	CW	?= "{CW}" ;
315
316	MACHDRS ?=
317		"$(UMACHDRS):Universal:Interfaces:CIncludes"
318		"$(CW):MSL:MSL_C:MSL_Common:Include"
319		"$(CW):MSL:MSL_C:MSL_MacOS:Include" ;
320
321	MACLIBS ?=
322		"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Interfacelib"
323		"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Mathlib" ;
324
325	MPWLIBS ?=
326		"$(CW):MacOS Support:Libraries:Runtime:Libs:MSL_MPWCRuntime_PPC.lib"
327		"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL_C_PPC_MPW.Lib" ;
328
329	MPWNLLIBS ?=
330		"$(CW):MacOS Support:Libraries:Runtime:Libs:MSL_MPWCRuntime_PPC.lib"
331		"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL_C_PPC_MPW(NL).Lib" ;
332
333	SIOUXHDRS ?= ;
334
335	SIOUXLIBS ?=
336		"$(CW):MacOS Support:Libraries:Runtime:Libs:MSL_Runtime_PPC.lib"
337		"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL_SIOUX_PPC.Lib"
338		"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL_C_PPC.Lib" ;
339
340	C++			?= mwcppc ;
341	C++FLAGS	?= -w off ;
342	CC			?= mwcppc ;
343	CCFLAGS		?= -w off ;
344	CP			?= duplicate -y ;
345	DOT			?= ":" ;
346	DOTDOT		?= "::" ;
347	HDRS 		?= $(MACHDRS) $(MPWHDRS) ;
348	LINK		?= mwlinkppc ;
349	LINKFLAGS	?= -mpwtool -warn ;
350	LINKLIBS 	?= $(MACLIBS) $(MPWLIBS) ;
351	MKDIR		?= newfolder ;
352	MV			?= rename -y ;
353	NOARSCAN	?= true ;
354	OPTIM		?= ;
355	RM			?= delete -y ;
356	SLASH		?= ":" ;
357	STDHDRS		?= ;
358	SUFLIB		?= .lib ;
359	SUFOBJ		?= .o ;
360}
361else if $(OS) = BEOS && $(OSPLAT) = PPC
362{
363	AR			?= mwld -xml -o ;
364	BINDIR		?= /boot/home/config/bin ;
365	CC			?= mwcc ;
366	CCFLAGS		?= -nosyspath ;
367	C++			?= $(CC) ;
368	C++FLAGS	?= -nosyspath ;
369	CHMOD		?= chmod ;
370	CHGRP		?= chgrp ;
371	CHOWN		?= chown ;
372	FORTRAN		?= "" ;
373	LEX			?= flex ;
374	LIBDIR		?= /boot/home/config/lib ;
375	LINK		?= mwld ;
376	LINKFLAGS	?= "" ;
377	MANDIR		?= /boot/home/config/man ;
378	NOARSCAN	?= true ;
379	RANLIB		?= ranlib ;
380	STDHDRS		?= /boot/develop/headers/posix ;
381	YACC		?= bison -y ;
382	YACCGEN		?= .c ;
383	YACCFILES	?= y.tab ;
384	YACCFLAGS	?= -d ;
385}
386else if $(OS) = BEOS
387{
388	BINDIR		?= /boot/home/config/bin ;
389	CC			?= gcc ;
390	C++			?= $(CC) ;
391	CHMOD		?= chmod ;
392	CHGRP		?= chgrp ;
393	CHOWN		?= chown ;
394	FORTRAN		?= "" ;
395	LEX			?= flex ;
396	LIBDIR		?= /boot/home/config/lib ;
397	LINK		?= gcc ;
398	MANDIR		?= /boot/home/config/man ;
399	NOARSCAN	?= true ;
400	RANLIB		?= ranlib ;
401	STDHDRS		?= /boot/develop/headers/posix ;
402	YACC		?= bison -y ;
403	YACCGEN		?= .c ;
404	YACCFILES	?= y.tab ;
405	YACCFLAGS	?= -d ;
406}
407else if $(UNIX)
408{
409	switch $(OS)
410	{
411	case AIX :
412	C++			?= g++ ;
413	CC			?= gcc ;
414	CCFLAGS 	+= -D_AIX ;
415	LINKLIBS	?= -lbsd ;
416
417	case AMIGA :
418	CC			?= gcc ;
419	YACC		?= bison -y ;
420
421	case CYGWIN :
422	CC			?= gcc ;
423	CCFLAGS 	+= -D__cygwin__ ;
424	LEX			?= flex ;
425	JAMSHELL	?= sh -c ;
426	RANLIB		?= "" ;
427	SUFEXE		?= .exe ;
428	YACC		?= bison -y ;
429
430	case DGUX :
431	RANLIB		?= "" ;
432	RELOCATE 	?= true ;
433
434	case HPUX :
435	RANLIB		?= "" ;
436
437	case INTERIX :
438	CC			?= gcc ;
439	JAMSHELL	?= sh -c ;
440	RANLIB		?= "" ;
441
442	case IRIX :
443	RANLIB		?= "" ;
444
445	case MPEIX :
446	CC			?= gcc ;
447	C++			?= gcc ;
448	CCFLAGS		+= -D_POSIX_SOURCE ;
449	HDRS		+= /usr/include ;
450	RANLIB		?= "" ;
451	NOARSCAN	?= true ;
452	NOARUPDATE	?= true ;
453
454	case MVS :
455	RANLIB		?= "" ;
456	YACC		?= "" ;
457
458	case NEXT :
459	AR		?= libtool -o ;
460	RANLIB		?= "" ;
461
462	case MACOSX :
463	C++			?= c++ ;
464	MANDIR		?= /usr/local/share/man ;
465
466	case DARWIN :
467	C++			?= g++ ;
468	CC			?= gcc ;
469	CCFLAGS		+= -D__DARWIN__ ;
470	C++FLAGS		+= -D__DARWIN__ ;
471	MANDIR		?= /usr/local/share/man ;
472
473	case NCR :
474	RANLIB		?= "" ;
475
476	case PTX :
477	RANLIB		?= "" ;
478
479	case QNX :
480	AR			?= wlib ;
481	CC			?= cc ;
482	CCFLAGS		?= -Q ;	# quiet
483	C++			?= $(CC) ;
484	C++FLAGS	?= -Q ;	# quiet
485	LINK		?= $(CC) ;
486	LINKFLAGS	?= -Q ;	# quiet
487	NOARSCAN	?= true ;
488	RANLIB		?= "" ;
489
490	case SCO :
491	RANLIB		?= "" ;
492	RELOCATE 	?= true ;
493
494	case SINIX :
495	RANLIB		?= "" ;
496
497	case SOLARIS :
498	RANLIB		?= "" ;
499	AR			?= /usr/ccs/bin/ar ru ;
500
501	case UNICOS :
502	NOARSCAN 	?= true ;
503	OPTIM 		?= -O0 ;
504
505	case UNIXWARE :
506	RANLIB		?= "" ;
507	RELOCATE 	?= true ;
508	}
509
510	# UNIX defaults
511
512	CCFLAGS		?= ;
513	C++FLAGS	?= $(CCFLAGS) ;
514	CHMOD		?= chmod ;
515	CHGRP		?= chgrp ;
516	CHOWN		?= chown ;
517	LEX			?= lex ;
518	LINKFLAGS	?= $(CCFLAGS) ;
519	LINKLIBS	?= ;
520	OPTIM		?= -O ;
521	RANLIB		?= ranlib ;
522	YACC		?= yacc ;
523	YACCGEN		?= .c ;
524	YACCFILES	?= y.tab ;
525	YACCFLAGS	?= -d ;
526}
527
528#
529# General defaults; a lot like UNIX
530#
531
532	AR			?= ar ru ;
533	AS			?= as ;
534	ASFLAGS		?= ;
535	AWK			?= awk ;
536	BINDIR		?= /usr/local/bin ;
537	C++			?= cc ;
538	C++FLAGS	?= ;
539	CC			?= cc ;
540	CCFLAGS		?= ;
541	CP			?= cp -f ;
542	CRELIB		?= ;
543	DOT			?= . ;
544	DOTDOT		?= .. ;
545	EXEMODE		?= 711 ;
546	FILEMODE	?= 644 ;
547	FORTRAN		?= f77 ;
548	FORTRANFLAGS	?= ;
549	HDRS		?= ;
550	INSTALLGRIST	?= installed ;
551	JAMFILE		?= Jamfile ;
552	JAMRULES	?= Jamrules ;
553	LEX			?= ;
554	LIBDIR		?= /usr/local/lib ;
555	LINK		?= $(CC) ;
556	LINKFLAGS	?= ;
557	LINKLIBS	?= ;
558	LN			?= ln ;
559	MANDIR		?= /usr/local/man ;
560	MKDIR		?= mkdir ;
561	MV			?= mv -f ;
562	OPTIM		?= ;
563	RCP			?= rcp ;
564	RM			?= rm -f ;
565	RMDIR		?= $(RM) ;
566	RSH			?= rsh ;
567	SED			?= sed ;
568	SHELLHEADER	?= "#!/bin/sh" ;
569	SHELLMODE	?= 755 ;
570	SLASH		?= / ;
571	STDHDRS		?= ;
572	SUBDIRRULES ?= ;
573	SUBDIRRESET ?= ASFLAGS HDRS C++FLAGS CCFLAGS ;
574	SUFEXE		?= "" ;
575	SUFLIB		?= .a ;
576	SUFOBJ		?= .o ;
577	UNDEFFLAG	?= "-u _" ;
578	YACC		?= ;
579	YACCGEN		?= ;
580	YACCFILES	?= ;
581	YACCFLAGS	?= ;
582
583	HDRPATTERN =
584	    	"^[ 	]*#[ 	]*include[ 	]*[<\"]([^\">]*)[\">].*$" ;
585
586	OSFULL = $(OS)$(OSVER)$(OSPLAT) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ;
587
588
589#
590# Base dependencies - first for "bootstrap" kinds of rules
591#
592
593Depends all : shell files lib exe obj ;
594Depends all shell files lib exe obj : first ;
595NotFile all first shell files lib exe obj dirs clean uninstall ;
596Always clean uninstall ;
597
598#
599# Rules
600#
601
602rule As
603{
604	Depends $(<) : $(>) ;
605	ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
606	ASHDRS on $(<) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
607}
608
609rule Bulk
610{
611	local i ;
612
613	for i in $(>)
614	{
615	    File $(i:D=$(<)) : $(i) ;
616	}
617}
618
619
620rule GetTargetVar
621{
622	on $(<) { return $($(>)) ; }
623}
624
625rule Cc
626{
627	local _s ;
628	local _o ;
629
630	_s = [ GetTargetVar $(<) : SUBDIRCCFLAGS ] ;
631	_o = [ GetTargetVar $(<) : OPTIM ] ;
632
633	Depends $(<) : $(>) ;
634
635	# If the compiler's -o flag doesn't work, relocate the .o
636
637	if $(RELOCATE)
638	{
639	    CcMv $(<) : $(>) ;
640	}
641
642	# Just to clarify here: this sets the per-target CCFLAGS to
643	# be the current value of (global) CCFLAGS and SUBDIRCCFLAGS.
644	# CCHDRS and CCDEFS must be reformatted each time for some
645	# compiles (VMS, NT) that malign multiple -D or -I flags.
646
647	CCFLAGS on $(<) += $(CCFLAGS) $(_s) $(_o) ;
648
649	CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
650	CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
651}
652
653rule C++
654{
655	local _s ;
656	local _o ;
657
658	_s = [ GetTargetVar $(<) : SUBDIRC++FLAGS ] ;
659	_o = [ GetTargetVar $(<) : OPTIM ] ;
660
661	Depends $(<) : $(>) ;
662
663	if $(RELOCATE)
664	{
665	    CcMv $(<) : $(>) ;
666	}
667
668	C++FLAGS on $(<) += $(C++FLAGS) $(_s) $(_o) ;
669
670	CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
671	CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
672}
673
674rule Chmod
675{
676	if $(CHMOD) { Chmod1 $(<) ; }
677}
678
679rule File
680{
681	Depends files : $(<) ;
682	Depends $(<) : $(>) ;
683	SEARCH on $(>) = $(SEARCH_SOURCE) ;
684	MODE on $(<) = $(FILEMODE) ;
685	Chmod $(<) ;
686}
687
688rule Fortran
689{
690	Depends $(<) : $(>) ;
691}
692
693rule GenFile
694{
695	local _t = [ FGristSourceFiles $(<) ] ;
696	local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;
697	Depends $(_t) : $(_s) $(>[2-]) ;
698	GenFile1 $(_t) : $(_s) $(>[2-]) ;
699	Clean clean : $(_t) ;
700}
701
702rule GenFile1
703{
704	MakeLocate $(<) : $(LOCATE_SOURCE) ;
705	SEARCH on $(>) = $(SEARCH_SOURCE) ;
706}
707
708rule HardLink
709{
710	Depends files : $(<) ;
711	Depends $(<) : $(>) ;
712	SEARCH on $(>) = $(SEARCH_SOURCE) ;
713}
714
715rule HdrRule
716{
717	# HdrRule source : headers ;
718
719	# N.B.	This rule is called during binding, potentially after
720	# the fate of many targets has been determined, and must be
721	# used with caution: don't add dependencies to unrelated
722	# targets, and don't set variables on $(<).
723
724	# Tell Jam that anything depending on $(<) also depends on $(>),
725	# set SEARCH so Jam can find the headers, but then say we don't
726	# care if we can't actually find the headers (they may have been
727	# within ifdefs),
728
729	local s = $(>:G=$(HDRGRIST:E)) ;
730
731	Includes $(<) : $(s) ;
732	NoCare $(s) ;
733
734	# Propagate on $(<) to $(>)
735
736	HDRSCAN on $(s) = $(HDRSCAN) ;
737	HDRRULE on $(s) = $(HDRRULE) ;
738	HDRGRIST on $(s) = $(HDRGRIST) ;
739	HDRSEARCH on $(s) = $(HDRSEARCH) ;
740	SEARCH on $(s) = $(HDRSEARCH) ;
741
742	# If the including file has a hard-coded directory path $(<:D),
743	# we need to add that, as a subdirectory of the existing header
744	# search path, to SEARCH/HDRSEARCH.  We try to be careful not to
745	# add duplicates.
746
747	local d = $(<:D) ;
748	local h ;
749
750	if $(d)
751	{
752	    # Build unique list h = $(HDRSEARCH)/$(<:D)
753
754	    for i in $(d:R=$(HDRSEARCH))
755	    {
756	    	if ! $(i) in $(HDRSEARCH) $(h) { h += $(i) ; }
757	    }
758
759	    # For each included file whose directory doesn't match the
760	    # including file, add new subdirectories h to the search.
761
762	    for i in $(s)
763	    {
764		if $(d) != $(i:D)
765		{
766		    HDRSEARCH on $(i) += $(h) ;
767		    SEARCH on $(i) += $(h) ;
768		}
769	    }
770	}
771}
772
773rule InstallInto
774{
775	# InstallInto dir : sources ;
776
777	local i t ;
778
779	t = $(>:G=$(INSTALLGRIST)) ;
780
781	# Arrange for jam install
782	# Arrange for jam uninstall
783	# sources are in SEARCH_SOURCE
784	# targets are in dir
785
786	Depends install : $(t) ;
787	Clean uninstall : $(t) ;
788	SEARCH on $(>) = $(SEARCH_SOURCE) ;
789	MakeLocate $(t) : $(<) ;
790
791	# For each source, make gristed target name
792	# and Install, Chmod, Chown, and Chgrp
793
794	for i in $(>)
795	{
796	    local tt = $(i:G=$(INSTALLGRIST)) ;
797
798	    Depends $(tt) : $(i) ;
799	    Install $(tt) : $(i) ;
800	    Chmod $(tt) ;
801
802	    if $(OWNER) && $(CHOWN)
803	    {
804		Chown $(tt) ;
805		OWNER on $(tt) = $(OWNER) ;
806	    }
807
808	    if $(GROUP) && $(CHGRP)
809	    {
810		Chgrp $(tt) ;
811		GROUP on $(tt) = $(GROUP) ;
812	    }
813	}
814}
815
816rule InstallBin
817{
818	local _t = [ FAppendSuffix $(>) : $(SUFEXE) ] ;
819
820	InstallInto $(<) : $(_t) ;
821	MODE on $(_t:G=$(INSTALLGRIST)) = $(EXEMODE) ;
822}
823
824rule InstallFile
825{
826	InstallInto $(<) : $(>) ;
827	MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
828}
829
830rule InstallLib
831{
832	InstallInto $(<) : $(>) ;
833	MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
834}
835
836rule InstallMan
837{
838	# Really this just strips the . from the suffix
839
840	local i s d ;
841
842	for i in $(>)
843	{
844	    switch $(i:S)
845	    {
846	    case .1 : s = 1 ; case .2 : s = 2 ; case .3 : s = 3 ;
847	    case .4 : s = 4 ; case .5 : s = 5 ; case .6 : s = 6 ;
848	    case .7 : s = 7 ; case .8 : s = 8 ; case .l : s = l ;
849	    case .n : s = n ; case .man : s = 1 ;
850	    }
851
852	    d = man$(s) ;
853
854	    InstallInto $(d:R=$(<)) : $(i) ;
855	}
856
857	MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
858}
859
860rule InstallShell
861{
862	InstallInto $(<) : $(>) ;
863	MODE on $(>:G=$(INSTALLGRIST)) = $(SHELLMODE) ;
864}
865
866rule Lex
867{
868	LexMv $(<) : $(>) ;
869	Depends $(<) : $(>) ;
870	MakeLocate $(<) : $(LOCATE_SOURCE) ;
871	Clean clean : $(<) ;
872}
873
874rule Library
875{
876	LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
877	Objects $(>) ;
878}
879
880rule LibraryFromObjects
881{
882	local _i _l _s ;
883
884	# Add grist to file names
885
886	_s = [ FGristFiles $(>) ] ;
887	_l = $(<:S=$(SUFLIB)) ;
888
889	# library depends on its member objects
890
891	if $(KEEPOBJS)
892	{
893	    Depends obj : $(_s) ;
894	}
895	else
896	{
897	    Depends lib : $(_l) ;
898	}
899
900	# Set LOCATE for the library and its contents.  The bound
901	# value shows up as $(NEEDLIBS) on the Link actions.
902	# For compatibility, we only do this if the library doesn't
903	# already have a path.
904
905	if ! $(_l:D)
906	{
907	    MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ;
908	}
909
910	if $(NOARSCAN)
911	{
912	    # If we can't scan the library to timestamp its contents,
913	    # we have to just make the library depend directly on the
914	    # on-disk object files.
915
916	    Depends $(_l) : $(_s) ;
917	}
918	else
919	{
920	    # If we can scan the library, we make the library depend
921	    # on its members and each member depend on the on-disk
922	    # object file.
923
924	    Depends $(_l) : $(_l)($(_s:BS)) ;
925
926	    for _i in $(_s)
927	    {
928		Depends $(_l)($(_i:BS)) : $(_i) ;
929	    }
930	}
931
932	Clean clean : $(_l) ;
933
934	if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; }
935
936	Archive $(_l) : $(_s) ;
937
938	if $(RANLIB) { Ranlib $(_l) ; }
939
940	# If we can't scan the library, we have to leave the .o's around.
941
942	if ! ( $(NOARSCAN) || $(NOARUPDATE) ) { RmTemps $(_l) : $(_s) ; }
943}
944
945rule Link
946{
947	MODE on $(<) = $(EXEMODE) ;
948	Chmod $(<) ;
949}
950
951rule LinkLibraries
952{
953	# make library dependencies of target
954	# set NEEDLIBS variable used by 'actions Main'
955
956	local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
957
958	Depends $(_t) : $(>:S=$(SUFLIB)) ;
959	NEEDLIBS on $(_t) += $(>:S=$(SUFLIB)) ;
960}
961
962rule Main
963{
964	MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
965	Objects $(>) ;
966}
967
968rule MainFromObjects
969{
970	local _s _t ;
971
972	# Add grist to file names
973	# Add suffix to exe
974
975	_s = [ FGristFiles $(>) ] ;
976	_t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
977
978	# so 'jam foo' works when it's really foo.exe
979
980	if $(_t) != $(<)
981	{
982	    Depends $(<) : $(_t) ;
983	    NotFile $(<) ;
984	}
985
986	# make compiled sources a dependency of target
987
988	Depends exe : $(_t) ;
989	Depends $(_t) : $(_s) ;
990	MakeLocate $(_t) : $(LOCATE_TARGET) ;
991
992	Clean clean : $(_t) ;
993
994	Link $(_t) : $(_s) ;
995}
996
997rule MakeLocate
998{
999	# MakeLocate targets : directory ;
1000
1001	# Sets special variable LOCATE on targets, and arranges
1002	# with MkDir to create target directory.
1003
1004	# Note we grist the directory name with 'dir',
1005	# so that directory path components and other
1006	# targets don't conflict.
1007
1008	if $(>)
1009	{
1010	    LOCATE on $(<) = $(>) ;
1011	    Depends $(<) : $(>[1]:G=dir) ;
1012	    MkDir $(>[1]:G=dir) ;
1013	}
1014}
1015
1016rule MkDir
1017{
1018	# MkDir directory ;
1019
1020	# Make a directory and all its parent directories.
1021
1022	# Ignore timestamps on directories: we only care if they
1023	# exist.
1024
1025	NoUpdate $(<) ;
1026
1027	# Don't create . or any directory already created.
1028
1029	if $(<:G=) != $(DOT) && ! $($(<)-mkdir)
1030	{
1031	    # Cheesy gate to prevent multiple invocations on same dir
1032	    # Arrange for jam dirs
1033	    # MkDir1 has the actions
1034
1035	    $(<)-mkdir = true ;
1036	    Depends dirs : $(<) ;
1037	    MkDir1 $(<) ;
1038
1039	    # Recursively make parent directories.
1040	    # $(<:P) = $(<)'s parent, & we recurse until root
1041
1042	    local s = $(<:P) ;
1043
1044	    # Don't try to create A: or A:\ on windows
1045
1046	    if $(NT)
1047	    {
1048	        switch $(s)
1049		{
1050		case *:   : s = ;
1051		case *:\\ : s = ;
1052		}
1053	    }
1054
1055	    if $(s) = $(<)
1056	    {
1057		# The parent is the same as the dir.
1058		# We're at the root, which some OS's can't stat, so we mark
1059		# it as NotFile.
1060
1061	        NotFile $(s) ;
1062	    }
1063	    else if $(s:G=)
1064	    {
1065		# There's a parent; recurse.
1066
1067		Depends $(<) : $(s) ;
1068		MkDir $(s) ;
1069	    }
1070	}
1071}
1072
1073rule Object
1074{
1075	# locate object and search for source, if wanted
1076
1077	Clean clean : $(<) ;
1078
1079	MakeLocate $(<) : $(LOCATE_TARGET) ;
1080	SEARCH on $(>) = $(SEARCH_SOURCE) ;
1081
1082	# Save HDRS for -I$(HDRS) on compile.
1083	# We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers
1084	# in the .c file's directory, but generated .c files (from
1085	# yacc, lex, etc) are located in $(LOCATE_TARGET), possibly
1086	# different from $(SEARCH_SOURCE).
1087
1088	HDRS on $(<) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ;
1089
1090	# handle #includes for source: Jam scans for headers with
1091	# the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE)
1092	# with the scanned file as the target and the found headers
1093	# as the sources.  HDRSEARCH is the value of SEARCH used for
1094	# the found header files.  Finally, if jam must deal with
1095	# header files of the same name in different directories,
1096	# they can be distinguished with HDRGRIST.
1097
1098	# $(SEARCH_SOURCE:E) is where cc first looks for #include
1099	# "foo.h" files.  If the source file is in a distant directory,
1100	# look there.  Else, look in "" (the current directory).
1101
1102	HDRRULE on $(>) = HdrRule ;
1103	HDRSCAN on $(>) = $(HDRPATTERN) ;
1104	HDRSEARCH on $(>) =
1105		$(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ;
1106
1107	HDRGRIST on $(>) = $(HDRGRIST) ;
1108
1109	# propagate target specific-defines
1110
1111	DEFINES on $(<) += $(DEFINES) ;
1112
1113	# if source is not .c, generate .c with specific rule
1114
1115	switch $(>:S)
1116	{
1117	    case .asm : As $(<) : $(>) ;
1118	    case .c :	Cc $(<) : $(>) ;
1119	    case .C :	C++ $(<) : $(>) ;
1120	    case .cc :	C++ $(<) : $(>) ;
1121	    case .cpp : C++ $(<) : $(>) ;
1122	    case .f :	Fortran $(<) : $(>) ;
1123	    case .l :	Cc $(<) : $(<:S=.c) ;
1124		            Lex $(<:S=.c) : $(>) ;
1125	    case .m :	Cc $(<) : $(>) ;
1126	    case .mm :	Cc $(<) : $(>) ;
1127	    case .s :	As $(<) : $(>) ;
1128	    case .y :	Cc $(<) : $(<:S=$(YACCGEN)) ;
1129		            Yacc $(<:S=$(YACCGEN)) : $(>) ;
1130	    case * :	UserObject $(<) : $(>) ;
1131	}
1132}
1133
1134rule ObjectCcFlags
1135{
1136	CCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
1137}
1138
1139rule ObjectC++Flags
1140{
1141	C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
1142}
1143
1144rule ObjectDefines
1145{
1146	# must reformat CCDEFS according to current defines
1147
1148	local s = [ FGristFiles $(<:S=$(SUFOBJ)) ] ;
1149
1150	DEFINES on $(s) += $(>) ;
1151	CCDEFS on $(s) = [ on $(s) FDefines $(DEFINES) ] ;
1152}
1153
1154rule ObjectHdrs
1155{
1156	# Add to HDRS for HdrScan's benefit.
1157	# must reformat CCHDRS according to headers
1158
1159	local s = [ FGristFiles $(<:S=$(SUFOBJ)) ] ;
1160
1161	HDRS on $(s) += $(>) ;
1162	CCHDRS on $(s) = [ on $(s) FIncludes $(HDRS) ] ;
1163}
1164
1165rule Objects
1166{
1167	local _i ;
1168
1169	for _i in [ FGristFiles $(<) ]
1170	{
1171		Object $(_i:S=$(SUFOBJ)) : $(_i) ;
1172		Depends obj : $(_i:S=$(SUFOBJ)) ;
1173	}
1174}
1175
1176rule RmTemps
1177{
1178	Temporary $(>) ;
1179}
1180
1181rule Setuid
1182{
1183	MODE on [ FAppendSuffix $(<) : $(SUFEXE) ] = 4711 ;
1184}
1185
1186rule Shell
1187{
1188	Depends shell : $(<) ;
1189	Depends $(<) : $(>) ;
1190	SEARCH on $(>) = $(SEARCH_SOURCE) ;
1191	MODE on $(<) = $(SHELLMODE) ;
1192	Clean clean : $(<) ;
1193	Chmod $(<) ;
1194}
1195
1196rule SoftLink
1197{
1198	Depends files : $(<) ;
1199	Depends $(<) : $(>) ;
1200	SEARCH on $(>) = $(SEARCH_SOURCE) ;
1201	Clean clean : $(<) ;
1202}
1203
1204rule SubDir
1205{
1206	#
1207	# SubDir TOP d1 d2 ... ;
1208	#
1209	# Support for a project tree spanning multiple directories.
1210	#
1211	# SubDir declares a Jamfile's location in a project tree, setting
1212	# Jambase variables (SEARCH_SOURCE, LOCATE_TARGET) so that source
1213	# files can be found.
1214	#
1215	# TOP is a user-select variable name for root of the tree, and
1216	# d1 d2 ...  are the directory elements that lead from the root
1217	# of the tree to the directory of the Jamfile.
1218	#
1219	# TOP can be set externally, but normally the first SubDir call
1220	# computes TOP as the path up from the current directory; the
1221	# path contains one ../ for each of d1 d2 ...
1222	#
1223	# SubDir reads once the project-specific rules file Jamrules
1224	# in the TOP directory, if present.  This can be overridden
1225	# with the variable TOPRULES.
1226	#
1227	# SubDir supports multiple, overlaid project trees:  SubDir
1228	# invocations with different TOPs can appear in the same Jamfile.
1229	# The location established by the first SubDir call is used set
1230	# the TOPs for the subsequent SubDir calls.
1231	#
1232	# SubDir's public variables:
1233	#
1234	#	$(TOP) = path from CWD to root.
1235	#	$(SUBDIR) = path from CWD to the directory SubDir names.
1236	#	$(SUBDIR_TOKENS) = path from $(TOP) to $(SUBDIR) as dir names
1237	#	$(SEARCH_SOURCE) = $(SUBDIR)
1238	#	$(LOCATE_SOURCE) = $(ALL_LOCATE_TARGET) $(SUBDIR)
1239	#	$(LOCATE_TARGET) = $(ALL_LOCATE_TARGET) $(SUBDIR)
1240	#	$(SOURCE_GRIST) = $(SUBDIR_TOKENS) with !'s
1241	#
1242
1243	local _top = $(<[1]) ;
1244	local _tokens = $(<[2-]) ;
1245
1246	#
1247	# First time through sets up relative root and includes Jamrules.
1248	#
1249
1250	if ! $(_top)
1251	{
1252	    Exit SubDir syntax error ;
1253	}
1254
1255	if ! $($(_top)-SET)
1256	{
1257	    $(_top)-SET = true ;
1258
1259	    # First time we've seen this TOP.
1260	    # We'll initialize a number of internal variables:
1261	    #
1262	    #	$(TOP-UP) = directories from ROOT to a common point
1263	    #	$(TOP-DOWN) = directories from common point to TOP
1264	    #	$(TOP-ROOT) = root directory for UP/DOWN -- normally CWD
1265	    #	$(SUBDIR_UP) = current value of $(TOP-UP)
1266	    #	$(SUBDIR_DOWN) = current value of $(TOP-DOWN)
1267	    #	$(SUBDIR_ROOT) = current value of $(TOP-ROOT)
1268	    #
1269
1270	    if $($(_top))
1271	    {
1272		# TOP externally set.
1273		# We'll ignore the relative (UP/DOWN) path that
1274		# got us here, and instead remember the hard ROOT.
1275
1276		$(_top)-UP = ;
1277		$(_top)-DOWN = ;
1278		$(_top)-ROOT = $($(_top)) ;
1279	    }
1280	    else
1281	    {
1282		# TOP not preset.
1283
1284		# Establishing a new TOP.  In the simplest case,
1285		# (SUBDIR_UP/SUBDIR_DOWN/SUBDIR_ROOT unset), it's
1286		# merely a certain number of directories down from
1287		# the current directory, and FSubDirPath will set
1288		# TOP to a path consisting of ../ for each of the
1289		# elements of _tokens, because that represents how
1290		# far below TOP the current directory sits.
1291		#
1292		# In the more complicated case, the starting directory
1293		# isn't the directory of jam's invocation but an
1294		# location established by previous SubDir call.  The
1295		# starting directory is SUBDIR_UP directories up from
1296		# SUBDIR_ROOT, and then SUBDIR_DOWN directories down
1297		# from that.   If SUBDIR_ROOT is not set, that means
1298		# SUBDIR_DOWN and SUBDIR_UP represent the path from
1299		# the directory of jam's invocation.
1300		#
1301		# In the most complicated case, the _tokens also
1302		# represents directories down, because TOP is being
1303		# estalished in a directory other than TOP's root.
1304		# Hopefully, _tokens and SUBDIR_DOWN represent the
1305		# same final directory, relative to the new TOP and
1306		# the previous SubDIr's TOP.  To find the new TOP,
1307		# we have to chop off any common directories from
1308		# then ends of _tokens and SUBDIR_DOWN.  To do so,
1309		# we reverse each of them, call FStripCommon to
1310		# remove the initial common elements, and then
1311		# reverse them again.  After this process, if
1312		# both _tokens and SUBDIR_DOWN have elements, it
1313		# means the directory names estalished by the two
1314		# SubDir calls don't match, and a warning is issued.
1315		# All hell will likely break loose at this point,
1316		# since the whole SubDir scheme relies on the SubDir
1317		# calls accurately naming the current directory.
1318
1319		# Strip common trailing elements of _tokens and SUBDIR_DOWN.
1320
1321		_tokens = [ FReverse $(_tokens) ] ;
1322		SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
1323		FStripCommon _tokens : SUBDIR_DOWN ;
1324		SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
1325		_tokens = [ FReverse $(_tokens) ] ;
1326
1327		if $(SUBDIR_DOWN) && $(_tokens)
1328		{
1329		    Echo Warning: SubDir $(<) misplaced! ;
1330		}
1331
1332		# We'll remember the relative (UP/DOWN) path that
1333		# got us here, plus any hard ROOT starting point
1334		# for the UP/DOWN.  If TOP is never set externally,
1335		# ROOT will always be "" (directory of jam's invocation).
1336
1337		$(_top)-UP = $(SUBDIR_UP) $(_tokens) ;
1338		$(_top)-DOWN = $(SUBDIR_DOWN) ;
1339		$(_top)-ROOT = $(SUBDIR_ROOT:E="") ;
1340		$(_top) = [ FSubDirPath $(_top) ] ;
1341	    }
1342
1343	    # Set subdir vars for the inclusion of the Jamrules,
1344	    # just in case they have SubDir rules of their own.
1345	    # Note that SUBDIR_DOWN is empty: it's all the way
1346	    # up where the Jamrules live.  These gets overrided
1347	    # just after the inclusion.
1348
1349	    SUBDIR_UP = $($(_top)-UP) ;
1350	    SUBDIR_DOWN = ;
1351	    SUBDIR_ROOT = $($(_top)-ROOT) ;
1352
1353	    # Include $(TOPRULES) or $(TOP)/Jamrules.
1354	    # Include $(TOPRULES) if set.
1355	    # Otherwise include $(TOP)/Jamrules if present.
1356
1357	    if $($(_top)RULES) {
1358		include $($(_top)RULES) ;
1359	    } else {
1360		NoCare $(JAMRULES:R=$($(_top)):G=$(_top)) ;
1361		include $(JAMRULES:R=$($(_top)):G=$(_top)) ;
1362	    }
1363	}
1364
1365	# Get path from $(TOP) to named directory.
1366	# Save dir tokens for other potential uses.
1367
1368	SUBDIR_UP = $($(_top)-UP) ;
1369	SUBDIR_DOWN = $($(_top)-DOWN) $(_tokens) ;
1370	SUBDIR_ROOT = $($(_top)-ROOT) ;
1371	SUBDIR_TOKENS = $(SUBDIR_DOWN) ;
1372
1373	SUBDIR = [ FSubDirPath $(<) ] ;
1374
1375	# Now set up SEARCH_SOURCE, LOCATE_TARGET, SOURCE_GRIST
1376	# These can be reset if needed.	 For example, if the source
1377	# directory should not hold object files, LOCATE_TARGET can
1378	# subsequently be redefined.
1379
1380	SEARCH_SOURCE = $(SUBDIR) ;
1381	LOCATE_SOURCE = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
1382	LOCATE_TARGET = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
1383	SOURCE_GRIST = [ FGrist $(SUBDIR_TOKENS) ] ;
1384
1385	# Reset per-directory ccflags, hdrs, etc,
1386	# listed in SUBDIRRESET.
1387	# Note use of variable expanded assignment var
1388
1389	SUBDIR$(SUBDIRRESET) = ;
1390
1391	# Invoke user-specific SubDir extensions,
1392	# rule names listed in SUBDIRRULES.
1393	# Note use of variable expanded rule invocation
1394
1395	$(SUBDIRRULES) $(<) ;
1396}
1397
1398rule FSubDirPath
1399{
1400	# FSubDirPath TOP d1 ... ;
1401
1402	# Returns path to named directory.
1403
1404	# If jam is invoked in a subdirectory of the TOP, then we
1405	# need to prepend a ../ for every level we must climb up
1406	# (TOP-UP), and then append the directory names we must
1407	# climb down (TOP-DOWN), plus the named directories d1 ...
1408	# If TOP was set externally, or computed from another TOP
1409	# that was, we'll have to reroot the whole thing at TOP-ROOT.
1410
1411	local _r = [ FRelPath $($(<[1])-UP) : $($(<[1])-DOWN) $(<[2-]) ] ;
1412
1413	return $(_r:R=$($(<[1])-ROOT)) ;
1414}
1415
1416rule SubDirCcFlags
1417{
1418	SUBDIRCCFLAGS += $(<) ;
1419}
1420
1421rule SubDirC++Flags
1422{
1423	SUBDIRC++FLAGS += $(<) ;
1424}
1425
1426rule SubDirHdrs
1427{
1428	SUBDIRHDRS += [ FDirName $(<) ] ;
1429}
1430
1431rule SubInclude
1432{
1433	# SubInclude TOP d1 ... ;
1434	#
1435	# Include a subdirectory's Jamfile.
1436
1437	# We use SubDir to get there, in case the included Jamfile
1438	# either doesn't have its own SubDir (naughty) or is a subtree
1439	# with its own TOP.
1440
1441	if ! $($(<[1]))
1442	{
1443	    Exit SubInclude $(<[1]) without prior SubDir $(<[1]) ;
1444	}
1445
1446	SubDir $(<) ;
1447
1448	include $(JAMFILE:D=$(SUBDIR)) ;
1449}
1450
1451rule SubRules
1452{
1453	# SubRules TOP d1 ... : Other-TOP ;
1454	#
1455	# Read another tree's Jamrules, by giving it's path according
1456	# to this tree and it's own name.
1457
1458	if ! $($(<[1]))
1459	{
1460	    Exit SubRules $(<[1]) without prior SubDir $(<[1]) ;
1461	}
1462
1463	SubDir $(<) ;
1464	SubDir $(>) ;
1465}
1466
1467rule Undefines
1468{
1469	UNDEFS on [ FAppendSuffix $(<) : $(SUFEXE) ] += $(UNDEFFLAG)$(>) ;
1470}
1471
1472rule UserObject
1473{
1474	Exit "Unknown suffix on" $(>) "- see UserObject rule in Jamfile(5)." ;
1475}
1476
1477rule Yacc
1478{
1479	local _h ;
1480
1481	_h = $(<:BS=.h) ;
1482
1483	# Some places don't have a yacc.
1484
1485	MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ;
1486
1487	if $(YACC)
1488	{
1489	    Depends $(<) $(_h) : $(>) ;
1490	    Yacc1 $(<) $(_h) : $(>) ;
1491	    YaccMv $(<) $(_h) : $(>) ;
1492	    Clean clean : $(<) $(_h) ;
1493	}
1494
1495	# make sure someone includes $(_h) else it will be
1496	# a deadly independent target
1497
1498	Includes $(<) : $(_h) ;
1499
1500	# Handle #includes in .y file
1501
1502	HDRRULE on $(>) = YaccHdr ;
1503}
1504
1505rule YaccHdr
1506{
1507	# YaccHdr .y : hdrs ;
1508	# For yacc, includes are actually on the generated
1509	# .c file, not on the source .y.
1510
1511	HdrRule $(<:S=$(YACCGEN)) : $(>) ;
1512}
1513
1514#
1515# Utility rules; no side effects on these
1516#
1517
1518rule FGrist
1519{
1520	return $(<:J=!) ;
1521
1522}
1523
1524rule FGristFiles
1525{
1526	return $(<:G=$(SOURCE_GRIST:E)) ;
1527}
1528
1529rule FGristSourceFiles
1530{
1531	# Produce source file name name with grist in it,
1532	# if SOURCE_GRIST is set.
1533
1534	# Leave header files alone, because they have a global
1535	# visibility.
1536
1537	if ! $(SOURCE_GRIST)
1538	{
1539	    return $(<) ;
1540	}
1541	else
1542	{
1543	    local _i _o ;
1544
1545	    for _i in $(<)
1546	    {
1547		switch $(_i)
1548		{
1549		case *.h :	_o += $(_i) ;
1550		case * : 	_o += $(_i:G=$(SOURCE_GRIST)) ;
1551		}
1552	    }
1553
1554	    return $(_o) ;
1555	}
1556}
1557
1558rule FReverse
1559{
1560	# FReverse a1 a2 a3 ... ;
1561	# return ... a3 a2 a1 ;
1562
1563	if $(1) { return [ FReverse $(1[2-]) ] $(1[1]) ; }
1564}
1565
1566rule FSubDir
1567{
1568	# If $(>) is the path to the current directory, compute the
1569	# path (using ../../ etc) back to that root directory.
1570	# Sets result in $(<)
1571
1572	if ! $(<[1])
1573	{
1574	    return $(DOT) ;
1575	}
1576	else
1577	{
1578	    local _i _d ;
1579
1580	    _d = $(DOTDOT) ;
1581
1582	    for _i in $(<[2-])
1583	    {
1584		_d = $(_d:R=$(DOTDOT)) ;
1585	    }
1586
1587	    return $(_d) ;
1588	}
1589}
1590
1591rule FStripCommon
1592{
1593	# FStripCommon v1 : v2 ;
1594
1595	# Strip common initial elements of variables v1 and v2.
1596	# Modifies the variable values themselves.
1597
1598	if $($(<)[1]) && $($(<)[1]) = $($(>)[1])
1599	{
1600	    $(<) = $($(<)[2-]) ;
1601	    $(>) = $($(>)[2-]) ;
1602	    FStripCommon $(<) : $(>) ;
1603	}
1604}
1605
1606rule FRelPath
1607{
1608	local _l _r ;
1609
1610	# first strip off common parts
1611
1612	_l = $(<) ;
1613	_r = $(>) ;
1614
1615	FStripCommon _l : _r ;
1616
1617	# now make path to root and path down
1618
1619	_l = [ FSubDir $(_l) ] ;
1620	_r = [ FDirName $(_r) ] ;
1621
1622	# Concatenate and save
1623
1624	# XXX This should be better
1625
1626	if $(_r) = $(DOT) {
1627	    return $(_l) ;
1628	} else {
1629	    return $(_r:R=$(_l)) ;
1630	}
1631}
1632
1633rule FAppendSuffix
1634{
1635	# E.g., "FAppendSuffix yacc lex foo.bat : $(SUFEXE) ;"
1636	# returns (yacc,lex,foo.bat) on Unix and
1637	# (yacc.exe,lex.exe,foo.bat) on NT.
1638
1639	if $(>)
1640	{
1641	    local _i _o ;
1642
1643	    for _i in $(<)
1644	    {
1645		if $(_i:S)
1646		{
1647		    _o += $(_i) ;
1648		}
1649		else
1650		{
1651		    _o += $(_i:S=$(>)) ;
1652		}
1653	    }
1654	    return $(_o) ;
1655	}
1656	else
1657	{
1658	    return $(<) ;
1659	}
1660}
1661
1662#
1663# Operating system specific utility rules
1664# First, the (generic) UNIX versions
1665#
1666
1667rule FQuote { return \\\"$(<)\\\" ; }
1668rule FDefines { return -D$(<) ; }
1669rule FIncludes { return -I$(<) ; }
1670
1671rule FDirName
1672{
1673	# Turn individual elements in $(<) into a usable path.
1674
1675	local _i ;
1676	local _s = $(DOT) ;
1677
1678	for _i in $(<)
1679	{
1680	    _s = $(_i:R=$(_s)) ;
1681	}
1682
1683	return $(_s) ;
1684}
1685
1686if $(OS2)
1687{
1688	rule FQuote { return \"$(<)\" ; }
1689	rule FIncludes { return /I$(<) ; }
1690}
1691
1692else if $(NT)
1693{
1694	rule FDefines { return /D$(<) ; }
1695	rule FIncludes { return /I$(<) ; }
1696}
1697
1698else if $(MAC)
1699{
1700	rule FQuote { return \"$(<)\" ; }
1701	rule FDefines { return "-define '$(<)'" ; }
1702	rule FIncludes { return \"$(<:J=,)\" ; }
1703}
1704
1705else if $(VMS)
1706{
1707	rule FQuote { return \"\"\"$(<)\"\"\" ; }
1708	rule FDefines { return "/define=( $(<:J=,) )" ; }
1709	rule FIncludes { return "/inc=( $(<:J=,) )" ; }
1710
1711	rule FDirName
1712	{
1713		local _s _i ;
1714
1715		# Turn individual elements in $(<) into a usable path.
1716
1717		if ! $(<)
1718		{
1719		    _s = $(DOT) ;
1720		}
1721		else
1722		{
1723		    # This handles the following cases:
1724		    # 	a -> [.a]
1725		    # 	a b c -> [.a.b.c]
1726		    # 	x: -> x:
1727		    # 	x: a -> x:[a]
1728		    # 	x:[a] b -> x:[a.b]
1729
1730		    switch $(<[1])
1731		    {
1732		    case *:* : _s = $(<[1]) ;
1733		    case \\[*\\] : _s = $(<[1]) ;
1734		    case * : _s = [.$(<[1])] ;
1735		    }
1736
1737		    for _i in [.$(<[2-])]
1738		    {
1739			_s = $(_i:R=$(_s)) ;
1740		    }
1741		}
1742
1743		return $(_s) ;
1744	}
1745}
1746
1747#
1748# Actions
1749#
1750
1751#
1752# First the defaults
1753#
1754
1755actions updated together piecemeal Archive
1756{
1757	$(AR) $(<) $(>)
1758}
1759
1760actions As
1761{
1762	$(AS) $(ASFLAGS) $(ASHDRS) -o $(<) $(>)
1763}
1764
1765actions C++
1766{
1767	$(C++) -c -o $(<) $(C++FLAGS) $(CCDEFS) $(CCHDRS) $(>)
1768}
1769
1770actions Cc
1771{
1772	$(CC) -c -o $(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) $(>)
1773}
1774
1775actions Chgrp
1776{
1777	$(CHGRP) $(GROUP) $(<)
1778}
1779
1780actions Chmod1
1781{
1782	$(CHMOD) $(MODE) $(<)
1783}
1784
1785actions Chown
1786{
1787	$(CHOWN) $(OWNER) $(<)
1788}
1789
1790actions piecemeal together existing Clean
1791{
1792	$(RM) $(>)
1793}
1794
1795actions File
1796{
1797	$(CP) $(>) $(<)
1798}
1799
1800actions GenFile1
1801{
1802	$(>[1]) $(<) $(>[2-])
1803}
1804
1805actions Fortran
1806{
1807	$(FORTRAN) $(FORTRANFLAGS) -o $(<) $(>)
1808}
1809
1810actions HardLink
1811{
1812	$(RM) $(<) && $(LN) $(>) $(<)
1813}
1814
1815actions Install
1816{
1817	$(CP) $(>) $(<)
1818}
1819
1820actions Lex
1821{
1822	$(LEX) $(>)
1823}
1824
1825actions LexMv
1826{
1827	$(MV) lex.yy.c $(<)
1828}
1829
1830actions Link bind NEEDLIBS
1831{
1832	$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
1833}
1834
1835actions MkDir1
1836{
1837	$(MKDIR) $(<)
1838}
1839
1840actions together Ranlib
1841{
1842	$(RANLIB) $(<)
1843}
1844
1845actions quietly updated piecemeal together RmTemps
1846{
1847	$(RM) $(>)
1848}
1849
1850actions Shell
1851{
1852	$(AWK) '
1853		NR == 1 { print "$(SHELLHEADER)" }
1854		NR == 1 && /^[#:]/ { next }
1855		/^##/ { next }
1856		{ print }
1857	' < $(>) > $(<)
1858}
1859
1860actions SoftLink
1861{
1862	$(RM) $(<) && $(LN) -s $(>) $(<)
1863}
1864
1865actions Yacc1
1866{
1867	$(YACC) $(YACCFLAGS) $(>)
1868}
1869
1870actions YaccMv
1871{
1872	$(MV) $(YACCFILES).c $(<[1])
1873	$(MV) $(YACCFILES).h $(<[2])
1874}
1875
1876#
1877# RELOCATE - for compilers with broken -o flags
1878#
1879
1880if $(RELOCATE)
1881{
1882	actions C++
1883	{
1884	$(C++) -c $(C++FLAGS) $(CCDEFS) $(CCHDRS) $(>)
1885	}
1886
1887	actions Cc
1888	{
1889	$(CC) -c $(CCFLAGS) $(CCDEFS) $(CCHDRS) $(>)
1890	}
1891
1892	actions ignore CcMv
1893	{
1894	[ $(<) != $(>:BS=$(SUFOBJ)) ] && $(MV) $(>:BS=$(SUFOBJ)) $(<)
1895	}
1896}
1897
1898#
1899# NOARUPDATE - can't update an archive
1900#
1901
1902if $(NOARUPDATE)
1903{
1904	actions Archive
1905	{
1906	$(AR) $(<) $(>)
1907	}
1908}
1909
1910#
1911# UNIX specific actions
1912#
1913
1914if $(UNIX)
1915{
1916	actions GenFile1
1917	{
1918	PATH="$PATH:."
1919	$(>[1]) $(<) $(>[2-])
1920	}
1921}
1922
1923if $(AS400)
1924{
1925	#
1926	# AS/400's unix-style compiler, linker and archiver use the OUTPUTDIR
1927	# environment variable to decide which QSYS library the output file
1928	# should be placed in. These actions make sure that variable is
1929	# set when the command is run.
1930	#
1931
1932	actions updated piecemeal Archive
1933	{
1934	    OUTPUTDIR=$(QSYSLIB) $(AR) $(<) $(>)
1935	}
1936
1937	actions Cc
1938	{
1939	    OUTPUTDIR=$(QSYSLIB) $(CC) -c -o $(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) $(>)
1940	}
1941
1942	actions C++
1943	{
1944	    OUTPUTDIR=$(QSYSLIB) $(C++) -c -o $(<) $(C++FLAGS) $(CCDEFS) $(CCHDRS) $(>)
1945	}
1946
1947	actions Link bind NEEDLIBS
1948	{
1949	    OUTPUTDIR=$(QSYSLIB) $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
1950	}
1951
1952	#
1953	# On AS/400 we pre-create libraries by creating a symlink to a
1954	# Bound Directory in the QSYS library where the output goes. This
1955	# helps qar get the library name right.
1956	#
1957
1958	actions CreLib
1959	{
1960	    dest=`echo $(<) | sed -e 's#.*/\([^/]*\)\.a$#/qsys.lib/$(QSYSLIB).lib/\1.bnddir#'`
1961	    [ -h $(<) ] || ln -s $dest $(<)
1962	}
1963
1964}
1965
1966#
1967# NT specific actions
1968#
1969
1970if $(NT) && $(BCCROOT)
1971{
1972	actions updated together piecemeal Archive
1973	{
1974	$(AR) $(<) -+$(>)
1975	}
1976
1977	actions Link bind NEEDLIBS
1978	{
1979	$(LINK) -e$(<) $(LINKFLAGS) $(UNDEFS) -L$(LINKLIBS) $(NEEDLIBS) $(>)
1980	}
1981
1982	actions C++
1983	{
1984	$(C++) -c -o$(<) $(C++FLAGS) $(CCDEFS) $(CCHDRS) $(>)
1985	}
1986
1987	actions Cc
1988	{
1989	$(CC) -c -o$(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) $(>)
1990	}
1991}
1992else if $(NT)
1993{
1994	actions updated together piecemeal Archive
1995	{
1996	if exist $(<) set _$(<:B)_=$(<)
1997	$(AR) /out:$(<) %_$(<:B)_% $(>)
1998	}
1999
2000	actions As
2001	{
2002	$(AS) /Ml /p /v /w2 $(>) $(<) ,nul,nul;
2003	}
2004
2005	actions Cc
2006	{
2007	$(CC) /c /Fo$(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) /I"$(STDHDRS)" $(>)
2008	}
2009
2010	actions C++
2011	{
2012	$(C++) /c /Fo$(<) $(C++FLAGS) $(CCDEFS) $(CCHDRS) /I"$(STDHDRS)" /Tp$(>)
2013	}
2014
2015	actions Link bind NEEDLIBS
2016	{
2017	$(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) "$(LINKLIBS)"
2018	}
2019}
2020
2021#
2022# OS2 specific actions
2023#
2024
2025else if $(OS2) && $(WATCOM)
2026{
2027	actions together piecemeal Archive
2028	{
2029	$(AR) $(<) +-$(>)
2030	}
2031
2032	actions Cc
2033	{
2034	$(CC) /Fo=$(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) $(>)
2035	}
2036
2037	actions C++
2038	{
2039	$(C++) /Fo=$(<) $(C++FLAGS) $(CCDEFS) $(CCHDRS) $(>)
2040	}
2041
2042	actions Link bind NEEDLIBS
2043	{
2044	$(LINK) $(LINKFLAGS) /Fe=$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
2045	}
2046
2047	actions Shell
2048	{
2049	$(CP) $(>) $(<)
2050	}
2051}
2052
2053#
2054# VMS specific actions
2055#
2056
2057else if $(VMS)
2058{
2059	actions updated together piecemeal Archive
2060	{
2061	lib/replace $(<) $(>[1]) ,$(>[2-])
2062	}
2063
2064	actions Cc
2065	{
2066	$(CC)/obj=$(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) $(>)
2067	}
2068
2069	actions C++
2070	{
2071	$(C++)/obj=$(<) $(C++FLAGS) $(CCDEFS) $(CCHDRS) $(>)
2072	}
2073
2074	actions piecemeal together existing Clean
2075	{
2076	$(RM) $(>[1]);* ,$(>[2-]);*
2077	}
2078
2079	actions together quietly CreLib
2080	{
2081	if f$search("$(<)") .eqs. "" then lib/create $(<)
2082	}
2083
2084	actions GenFile1
2085	{
2086	mcr $(>[1]) $(<) $(>[2-])
2087	}
2088
2089	actions Link bind NEEDLIBS
2090	{
2091	$(LINK)/exe=$(<) $(LINKFLAGS) $(>:J=,) ,$(NEEDLIBS)/lib ,$(LINKLIBS)
2092	}
2093
2094	actions quietly updated piecemeal together RmTemps
2095	{
2096	$(RM) $(>[1]);* ,$(>[2-]);*
2097	}
2098
2099	actions Shell
2100	{
2101	$(CP) $(>) $(<)
2102	}
2103}
2104
2105#
2106# Mac specifc actions
2107#
2108
2109else if $(MAC)
2110{
2111	actions together Archive
2112	{
2113	$(LINK) -library -o $(<) $(>)
2114	}
2115
2116	actions Cc
2117	{
2118	set -e MWCincludes $(CCHDRS)
2119	$(CC) -o $(<) $(CCFLAGS) $(CCDEFS) $(>)
2120	}
2121
2122	actions C++
2123	{
2124	set -e MWCincludes $(CCHDRS)
2125	$(CC) -o $(<) $(C++FLAGS) $(CCDEFS) $(>)
2126	}
2127
2128	actions Link bind NEEDLIBS
2129	{
2130	$(LINK) -o $(<) $(LINKFLAGS) $(>) $(NEEDLIBS) "$(LINKLIBS)"
2131	}
2132}
2133
2134if $(WIN98)
2135{
2136	actions existing Clean
2137	{
2138	del $(>)
2139	}
2140}
2141
2142#
2143# Backwards compatibility with jam 1, where rules were uppercased.
2144#
2145
2146rule BULK      { Bulk          $(<) : $(>) ; }
2147rule FILE      { File          $(<) : $(>) ; }
2148rule HDRRULE   { HdrRule       $(<) : $(>) ; }
2149rule INSTALL   { Install       $(<) : $(>) ; }
2150rule LIBRARY   { Library       $(<) : $(>) ; }
2151rule LIBS      { LinkLibraries $(<) : $(>) ; }
2152rule LINK      { Link          $(<) : $(>) ; }
2153rule MAIN      { Main          $(<) : $(>) ; }
2154rule SETUID    { Setuid        $(<) ; }
2155rule SHELL     { Shell         $(<) : $(>) ; }
2156rule UNDEFINES { Undefines     $(<) : $(>) ; }
2157
2158# Old INSTALL* didn't take dest directory.
2159
2160rule INSTALLBIN { InstallBin $(BINDIR) : $(<) ; }
2161rule INSTALLLIB { InstallLib $(LIBDIR) : $(<) ; }
2162rule INSTALLMAN { InstallMan $(MANDIR) : $(<) ; }
2163
2164# Compatibility with jam 2.2.
2165
2166rule addDirName      { $(<) += [ FDirName $(>) ] ; }
2167rule makeCommon      { FStripCommon $(<) : $(>) ; }
2168rule _makeCommon     { FStripCommon $(<) : $(>) ; }
2169rule makeDirName     { $(<) = [ FDirName $(>) ] ; }
2170rule makeGrist       { $(<) = [ FGrist $(>) ] ; }
2171rule makeGristedName { $(<) = [ FGristSourceFiles $(>) ] ; }
2172rule makeRelPath     { $(<[1]) = [ FRelPath $(<[2-]) : $(>) ] ; }
2173rule makeString      { $(<) = $(>:J) ; }
2174rule makeSubDir      { $(<) = [ FSubDir $(>) ] ; }
2175rule makeSuffixed    { $(<[1]) = [ FAppendSuffix $(>) : $(<[2]) ] ; }
2176
2177#
2178# Now include the user's Jamfile.
2179#
2180
2181include $(JAMFILE) ;
2182