added 'pkg-config' rule
[k8jam.git] / Jambase
blobcc12a0fbaef00d78dfb63694733fc7691f593c41
2 # /+\
3 #  +\    Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 # \+/
6 # This file is part of Jam - see jam.c for Copyright information.
10 # JAMBASE - jam 2.5 ruleset providing make(1)-like functionality
12 # Supports UNIX, NT, and VMS.
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.
41 #Ketmar's changelog:
42 # [*] windoze support shortened (fuck it! %-)
43 # [-] OS/2 support removed (we'll cry for you...)
44 # [-] VMS support removed (nobody cares)
45 # [-] MAC support removed (should be rewritten!)
46 # [-] BEOS support removed (dead should be dead)
47 # [-] fortran support removed (who need that shit anyway?!)
48 # [+] C++ files will be compiled by g++, not gcc
49 # [+] MainC++ & MainC++FromObjects rules added (g++ linker instead of gcc)
50 # [+] LINKC++, LINKC++FLAGS, LINKC++LIBS, C++OPTIM variables added
51 # [+] LOCATE_BIN variable added (for Main rule)
52 # [+] PATH_SEPARATOR variable added
53 # [+] LOCATE_LIB and LOCATE_LIBSO variables added
54 # [+] xxxC++ renamed to C++xxx
55 # [+] SubIncludeOnce varname : TOP ... ;
56 # [-] xxxC++ rules removed (no need to keep obsolete crap)
57 # [-] aliases for compatibility with jam 2.2 removed
58 # [-] comented out all libtool crap
59 # [+] added rules: LinkFlagsOn, C++LinkFlagsOn, ObjCLinkFlagsOn
61 # Special targets defined in this file:
63 # all       - parent of first, shell, files, lib, exe
64 # first     - first dependent of 'all', for potential initialization
65 # shell     - parent of all Shell targets
66 # files     - parent of all File targets
67 # lib       - parent of all Library targets
68 # exe       - parent of all Main targets
69 # dirs      - parent of all MkDir targets
70 # clean     - removes all Shell, File, Library, and Main targets
71 # uninstall - removes all Install targets
74 # Rules defined by this file:
76 # as obj.o : source.s ;                  .s -> .o
77 # Bulk dir : files ;                     populate directory with many files
78 # Cc obj.o : source.c ;                  .c -> .o
79 # C++ obj.o : source.cc ;                .cc -> .o
80 # Clean clean : sources ;                remove sources with 'jam clean'
81 # File dest : source ;                   copy file
82 # GenFile source.c : program args ;      make custom file
83 # HardLink target : source ;             make link from source to target
84 # HdrRule source : headers ;             handle #includes
85 # InstallInto dir : sources ;            install any files
86 # InstallBin dir : sources ;             install binaries
87 # InstallLib dir : sources ;             install files
88 # InstallFile dir : sources ;            install files
89 # InstallMan dir : sources ;             install man pages
90 # InstallShell dir : sources ;           install shell scripts
91 # Lex source.c : source.l ;              .l -> .c
92 # Library lib : source ;                 archive library from compiled sources
93 # LibraryFromObjects lib : objects ;     archive library from objects
94 # LinkLibraries images : libraries ;     bag libraries onto Mains
95 # Main image : source ;                  link executable from compiled sources
96 # C++Main image : source ;               link c++ executable from compiled sources
97 # ObjC-Main image : source ;             link obj-c executable from compiled sources
98 # MainFromObjects image : objects ;      link executable from objects
99 # C++MainFromObjects image : objects ;   link c++ executable from objects
100 # ObjC-MainFromObjects image : objects ; link obj-c executable from objects
101 # MkDir dir ;                            make a directory, if not there
102 # Object object : source ;               compile object from source
103 # ObjectCcFlags source : flags ;         add compiler flags for object
104 # ObjectC++Flags source : flags ;        add compiler flags for object
105 # ObjectObjCFlags source : flags ;       add compiler flags for object
106 # ObjectHdrs source : dirs ;             add include directories for object
107 # Objects sources ;                      compile sources
108 # RmTemps target : sources ;             remove temp sources after target made
109 # Setuid images ;                        mark executables Setuid
110 # SoftLink target : source ;             make symlink from source to target
111 # SubDir TOP d1 d2 ... ;                 start a subdirectory Jamfile
112 # SubDirCcFlags flags ;                  add compiler flags until next SubDir
113 # SubDirC++Flags flags ;                 add compiler flags until next SubDir
114 # SubDirHdrs d1 d2 ... ;                 add include dir until next SubDir
115 # SubInclude TOP d1 d2 ... ;             include a subdirectory Jamfile
116 # Shell exe : source ;                   make a shell executable
117 # Undefines images : symbols ;           save undef's for linking
118 # UserObject object : source ;           handle unknown suffixes for Object
119 # Yacc source.c : source.y ;             .y -> .c
121 # Utility rules that have no side effects (not supported):
123 # FAppendSuffix f1 f2 ... : $(SUF) ;     return $(<) with suffixes
124 # FDirName d1 d2 ... ;                   return path from root to dir
125 # FGrist d1 d2 ... ;                     return d1!d2!...
126 # FGristFiles value ;                    return $(value:G=$(SOURCE_GRIST))
127 # FGristSourceFiles value ;              return $(value:G=$(SOURCE_GRIST))
128 # FStripCommon v1 : v2 ;                 strip common initial parts of v1 v2
129 # FReverse a1 a2 ... ;                   return ... a2 a1
130 # FRelPath d1 : d2 ;                     return rel path from d1 to d2
131 # FSubDir d1 d2 ... ;                    return path to root
135 # Brief review of the jam language:
137 # Statements:
138 #   rule RULE - statements to process a rule
139 #   actions RULE - system commands to carry out target update
141 # Modifiers on actions:
142 #   together - multiple instances of same rule on target get executed
143 #          once with their sources ($(>)) concatenated
144 #   updated - refers to updated sources ($(>)) only
145 #   ignore - ignore return status of command
146 #   quietly - don't trace its execution unless verbose
147 #   piecemeal - iterate command each time with a small subset of $(>)
148 #   existing - refers to currently existing sources ($(>)) only
149 #   bind vars - subject to binding before expanding in actions
151 # Special rules:
152 #   Always - always build a target
153 #   Depends - builds the dependency graph
154 #   Echo - blurt out targets on stdout
155 #   Exit - blurt out targets and exit
156 #   Includes - marks sources as headers for target (a codependency)
157 #   NoCare - don't panic if the target can't be built
158 #   NoUpdate - create the target if needed but never update it
159 #   NotFile - ignore the timestamp of the target (it's not a file)
160 #   Temporary - target need not be present if sources haven't changed
162 # Special variables set by jam:
163 #   $(<) - targets of a rule (to the left of the :)
164 #   $(>) - sources of a rule (to the right of the :)
165 #   $(xxx) - true on xxx (UNIX, VMS, NT, OS2, MAC)
166 #   $(OS) - name of OS - varies wildly
167 #   $(JAMVERSION) - version number (2.5)
169 # Special variables used by jam:
170 #   SEARCH - where to find something (used during binding and actions)
171 #   LOCATE - where to plop something not found with SEARCH
172 #   HDRRULE - rule to call to handle include files
173 #   HDRSCAN - egrep regex to extract include files
175 # Special targets:
176 #   all - default if none given on command line
179 # for perforce use -- jambase version
181 JAMBASEDATE = 2004.10.07 ;
183 #THIS_IS_KJAM = "tan" ; # we are using kjam; removed as obsolete
184 THIS_IS_K8JAM = "tan" ; # we are using k8jam
186 # set to 'tan' for old 'libtool' behavior
187 #!LIBTOOL!#K8_USE_LIBTOOL = ;
190 # Initialize variables
193 ###############################################################################
194 # special values
195 ###############################################################################
197 OPTIM_SPEED = -O3 -march=pentium3 -mtune=pentium3 -mfpmath=sse ;
198 #OPTIM_SPEED = -O3 -march=prescott -mtune=prescott -mfpmath=sse ;
199 LINKFLAGS_SPEED = -s ;
201 OPTIM_SIZE = -Os -march=i586 ;
202 LINKFLAGS_SIZE = -s ;
204 OPTIM_DEBUG = -O0 -g ;
205 LINKFLAGS_DEBUG = -g ;
207 OPTIM_NOALIAS = -fno-strict-aliasing ;
211 # OS specific variable settings
214 ###############################################################################
215 # Windoze
216 ###############################################################################
217 if $(NT) {
218   PATH_SEPARATOR = "\\" ;
219   local SUPPORTED_TOOLSETS =
220     MINGW
221     LCC
222     PELLESC
223   ;
225   # if the JAM_TOOLSET environment variable is defined, check that it is
226   # one of our supported values
227   #
228   if $(JAM_TOOLSET) {
229     if ! $(JAM_TOOLSET) in $(SUPPORTED_TOOLSETS) {
230       Echo "The JAM_TOOLSET environment variable is defined but its value" ;
231       Echo "is invalid, please use one of the following:" ;
232       Echo ;
233       for t in $(SUPPORTED_TOOLSETS) { Echo "  " $(t) ; }
234       Exit ;
235     }
236   }
238   if ! $(JAM_TOOLSET) {
239     Echo "The JAM_TOOLSET environment variable is not defined, defaults to MINGW" ;
240     JAM_TOOLSET = MINGW ;
241     MINGW = "c:\\mingw\\" ;
242   }
244   # if JAM_TOOLSET is empty, we'll try to detect the toolset from other
245   # environment variables to remain backwards compatible with Jam 2.5
246   #
247   if ! $(JAM_TOOLSET) {
248     if $(MSVC) {
249       JAM_TOOLSET = VISUALC ;
250       VISUALC     = $(MSVC) ;
251       MSVCNT      = $(MSVC) ;
252     } else if $(MSVCNT) {
253       JAM_TOOLSET = VISUALC ;
254       VISUALC     = $(MSVCNT) ;
255     } else if $(MINGW) {
256       # MINGW is defined when trying to compile FT-Jam with
257       # classic Jam
258       #
259       JAM_TOOLSET = MINGW ;
260     } else {
261       Echo "Jam cannot be run because you didn't indicate which compilation toolset" ;
262       Echo "to use. To do so, define the JAM_TOOLSET environment variable with" ;
263       Echo "one of the following values:" ;
264       Echo ;
265       Echo "  Value       Toolset Description" ;
266       Echo ;
267       Echo "  MINGW        MinGW (gcc)" ;
268       Echo "  LCC          Win32-LCC" ;
269       Echo "  PELLESC      Pelles C" ;
270       Echo ;
271       Echo "The corresponding compiler must be in your path" ;
272       Echo ;
273       Echo "  e.g.:  set JAM_TOOLSET=MINGW" ;
274       Exit ;
275     }
276   }
278   MV        ?= move /y ;
279   CP        ?= copy ;
280   RM        ?= del /f/q ;
281   RMDIR     ?= rmdir /s/q ;
282   SLASH     ?= \\ ;
283   SUFLIB    ?= .lib ;
284   SUFOBJ    ?= .obj ;
285   SUFEXE    ?= .exe ;
286   SUFLIBSHR ?= .dll ;
288   if $(JAM_TOOLSET) = MINGW {
289     Echo "Compiler is GCC with MinGW" ;
290     AR           ?= ar -ru ;
291     RANLIB       ?= ranlib ;
292     CC           ?= mingw-gcc ;
293     CCFLAGS      ?= "" ;
294     C++          ?= mingw-g++ ;
295     C++FLAGS     ?= $(CCFLAGS) ;
296     LINK         ?= $(CC) ;
297     LINKFLAGS    ?= "" ;
298     LINKLIBS     ?= -lkernel32 ;
299     OPTIM        ?= ;
300     SUFOBJ        = .o ;
301     SUFLIB        = .a ;
302     SLASH         = / ;
303     # MinGW-specific thingy
304     MINGW_GUI     = "-Wl,-subsystem,windows" ;
305     MINGW_THREADS = "-mthreads" ;
306     # k8
307     C++OPTIM     ?= $(OPTIM) ;
308     C++LINK      ?= $(C++) ;
309     C++LINKFLAGS ?= $(LINKFLAGS) ;
310     C++LINKLIBS  ?= $(LINKLIBS) ;
311     #NOARSCAN     ?= true ;
312     # set path if any
313     if $(MINGW) {
314       CC = "$(MINGW)$(CC:J= )" ;
315       C++ = "$(MINGW)$(C++:J= )" ;
316       LINK = "$(MINGW)$(LINK:J= )" ;
317       C++LINK = "$(MINGW)$(C++LINK:J= )" ;
318       AR = "$(MINGW)$(AR:J= )" ;
319       RANLIB = "$(MINGW)$(RANLIB:J= )" ;
320     }
321   } else if $(JAM_TOOLSET) = LCC {
322     Echo "Compiler is Win32-LCC" ;
323     AR        ?= lcclib ;
324     CC        ?= lcc ;
325     CCFLAGS   ?= "" ;
326     C++       ?= "error" ;
327     LINK      ?= lcclnk ;
328     LINKFLAGS ?= "" ;
329     LINKLIBS  ?= "" ;
330     OPTIM     ?= ;
331     NOARSCAN   = true ;
332     # k8
333     C++LINK    = "error" ;
334   } else if $(JAM_TOOLSET) = PELLESC {
335     Echo "Compiler is PellesC" ;
336     AR        ?= polib ;
337     CC        ?= pocc ;
338     CCFLAGS   ?= "" ;
339     C++       ?= "error" ;
340     LINK      ?= polink ;
341     LINKFLAGS ?= ;
342     LINKLIBS  ?= ;
343     OPTIM     ?= ;
344     NOARSCAN   = true ;
345     LINKLIBS  ?= crt.lib oldnames.lib Win\\kernel32.lib ;
346     # k8
347     C++LINK    = "error" ;
348   } else {
349     # XXX: We need better comments here !!
350     Exit "On NT, set MINGW to the root of the MinGW dir (but it won't help you anyway)" ;
351   }
352   STDHRS ?= "" ;
354 ###############################################################################
355 # UNIX
356 ###############################################################################
357 else if $(UNIX) {
358   PATH_SEPARATOR = "/" ;
359   switch $(OS) {
360     case CYGWIN :
361       CC           ?= gcc ;
362       CCFLAGS      += -D__cygwin__ ;
363       LEX          ?= flex ;
364       JAMSHELL     ?= sh -c ;
365       RANLIB       ?= "" ;
366       SUFEXE       ?= .exe ;
367       YACC         ?= bison -y ;
368     }
370     # UNIX defaults
372     CC        ?= gcc ;
373     C++       ?= g++ ;
374     OBJCC     ?= gcc ;
375     CCFLAGS   ?= ;
376     OBJCFLAGS ?= $(CCFLAGS) ;
377     C++FLAGS  ?= $(CCFLAGS) ;
378     CHMOD     ?= chmod ;
379     CHGRP     ?= chgrp ;
380     CHOWN     ?= chown ;
381     LEX       ?= lex ;
382     LINKFLAGS ?= $(CCFLAGS) ;
383     LINKLIBS  ?= ;
384     OPTIM     ?= ;
385     RANLIB    ?= ranlib ;
386     YACC      ?= yacc ;
387     YACCGEN   ?= .c ;
388     YACCFILES ?= y.tab ;
389     YACCFLAGS ?= -d ;
390 #!LIBTOOL!#    if $(K8_USE_LIBTOOL) {
391 #!LIBTOOL!#      SUFOBJSHR ?= .lo ;
392 #!LIBTOOL!#      SUFLIBSHR ?= .la ;
393 #!LIBTOOL!#    } else {
394 #!LIBTOOL!#      SUFOBJSHR ?= .o ;
395 #!LIBTOOL!#      SUFLIBSHR ?= .so ;
396 #!LIBTOOL!#    }
397     SUFOBJSHR ?= .o ;
398     SUFLIBSHR ?= .so ;
399 #!LIBTOOL!#
400     PICFLAGS  ?= -fpic ;
401     STDHDRS   ?= /usr/include ;
404 # shared library object file suffix. We assume that it is identical
405 # than the normal one
406 SUFOBJSHR ?= $(SUFOBJ) ;
407 SUFLIBSHR ?= $(SUFLIB) ;
410 # the D compiler
411 DC ?= dmd ;
414 # General defaults; a lot like UNIX
416 PATH_SEPARATOR ?= "/" ;
417 AR          ?= ar ru ;
418 AS          ?= as ;
419 ASFLAGS     ?= ;
420 AWK         ?= awk ;
421 BINDIR      ?= /usr/local/bin ;
422 C++         ?= g++ ;  # k8: was cc
423 C++FLAGS    ?= ;
424 CC          ?= gcc ;  # k8: was cc
425 CCFLAGS     ?= ;
426 CP          ?= cp -f ;
427 CRELIB      ?= ;
428 DOT         ?= . ;
429 DOTDOT      ?= .. ;
430 EXEMODE     ?= 755 ;
431 FILEMODE    ?= 644 ;
432 HDRS        ?= ;
433 INSTALLGRIST    ?= installed ;
434 JAMFILE     ?= Jamfile ;
435 JAMRULES    ?= Jamrules ;
436 LEX         ?= ;
437 LIBDIR      ?= /usr/local/lib ;
438 LINK        ?= $(CC) ;
439 LINKFLAGS   ?= ;
440 LINKLIBS    ?= ;
441 LN          ?= ln ;
442 MANDIR      ?= /usr/local/man ;
443 MKDIR       ?= mkdir ;
444 MV          ?= mv -f ;
445 OPTIM       ?= ;
446 RCP         ?= rcp ;
447 RM          ?= rm -f ;
448 RMDIR       ?= $(RM) ;
449 RSH         ?= rsh ;
450 SED         ?= sed ;
451 SHELLHEADER ?= "#!/bin/sh" ;
452 SHELLMODE   ?= 755 ;
453 SLASH       ?= / ;
454 SUBDIRRULES ?= ;
455 SUBDIRRESET ?= ASFLAGS HDRS C++FLAGS CCFLAGS ;
456 SUFEXE      ?= "" ;
457 SUFLIB      ?= .a ;
458 SUFOBJ      ?= .o ;
459 UNDEFFLAG   ?= "-u _" ;
460 YACC        ?= ;
461 YACCGEN     ?= ;
462 YACCFILES   ?= ;
463 YACCFLAGS   ?= ;
465 HDRPATTERN = "^[        ]*#[    ]*include[      ]*[<\"]([^\">]*)[\">].*$" ;
467 OSFULL = $(OS)$(OSVER)$(OSPLAT) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ;
469 # k8
470 C++OPTIM     ?= $(OPTIM) ;
471 C++LINK      ?= $(C++) ;
472 C++LINKFLAGS ?= $(LINKFLAGS) ;
473 C++LINKLIBS  ?= $(LINKLIBS) ;
475 OBJCOPTIM     ?= $(OPTIM) ;
476 OBJCLINK      ?= $(CC) ;
477 OBJCLINKFLAGS ?= $(LINKFLAGS) ;
478 OBJCLINKLIBS  ?= $(LINKLIBS) ;
479 OBJCLINKLIBS  += -lobjc ;
481 if $(OS) = "LINUX" {
482   if ( "gcc" in $(CC) ) && ! ( "-pipe" in $(CC) ) { CC += -pipe ; }
483   if ( "g++" in $(C++) ) && ! ( "-pipe" in $(C++) ) { C++ += -pipe ; }
486 #Echo "OS:" $(OS) ;
487 #Echo "OSFULL:" $(OSFULL) ;
488 #Echo "UNIX:" $(UNIX) ;
493 # Base dependencies - first for "bootstrap" kinds of rules
495 Depends all : shell files lib exe obj ;
496 Depends all shell files lib exe obj : first ;
497 NotFile all first shell files lib exe obj dirs clean uninstall ;
498 Always  clean uninstall ;
501 # Rules
504 # /As object : source ;
506 # Assemble the file _source_, called by the @Object rule.
508 # Do not call this rule directly, since _object_ and _source_ may have
509 # have platform-specific file extensions
511 rule As {
512   Depends $(<) : $(>) ;
513   ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
514   ASHDRS on $(<) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
517 # /Bulk  directory : sources ;
519 # Copies _sources_ into _directory_
521 rule Bulk {
522   local i ;
524   for i in $(>) {
525     File $(i:D=$(<)) : $(i) ;
526   }
530 # /Dc object : source ;
532 # Compile the file source into object, usin the D compiler $(DC), its
533 # flags $(DCFLAGS) and $(DOPTIM)
534 # Called by the @Object rule
536 # Do not call this rule directly, since _object_ and _source_ may have
537 # have platform-specific file extensions
539 rule Dc {
540   Depends $(<) : $(>) ;
541   # Just to clarify here: this sets the per-target DCFLAGS to
542   # be the current value of (global) DCFLAGS and SUBDIRDCFLAGS.
543   DCFLAGS on $(<) += $(DCFLAGS) $(SUBDIRDCFLAGS) ;
547 # /Cc object : source ;
549 # Compile the file source into object, using the C compiler $(CC), its
550 # flags $(CCFLAGS) and $(OPTIM), and the header file directories $(HDRS).
551 # Called by the @Object rule
553 # Do not call this rule directly, since _object_ and _source_ may have
554 # have platform-specific file extensions
556 rule Cc {
557   Depends $(<) : $(>) ;
559   # If the compiler's -o flag doesn't work, relocate the .o
560   if $(RELOCATE) { CcMv $(<) : $(>) ; }
562   # Just to clarify here: this sets the per-target CCFLAGS to
563   # be the current value of (global) CCFLAGS and SUBDIRCCFLAGS.
564   # CCHDRS and CCDEFS must be reformatted each time for some
565   # compiles (VMS, NT) that malign multiple -D or -I flags.
566   CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) ;
567   CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
568   CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
572 # /C++ object : source ;
574 # Compile the C++ source file _source_. Similar to @CC, called by @Object
576 # Do not call this rule directly, since _object_ and _source_ may have
577 # have platform-specific file extensions
579 rule C++ {
580   local ktmp ;
582   Depends $(<) : $(>) ;
584   if $(RELOCATE) { CcMv $(<) : $(>) ; }
586   # Just to clarify here: this sets the per-target CCFLAGS to
587   # be the current value of (global) CCFLAGS and SUBDIRCCFLAGS.
588   # CCHDRS and CCDEFS must be reformatted each time for some
589   # compiles (VMS, NT) that malign multiple -D or -I flags.
590   ktmp = $(C++FLAGS) ;
591   if ! $(ktmp) { ktmp = $(CCFLAGS) ; }
592   C++FLAGS on $(<) += $(ktmp) $(SUBDIRC++FLAGS) ;
594   ktmp = $(C++OPTIM) ;
595   if ! $(ktmp) { ktmp = $(OPTIM) ; }
596   C++OPTIM on $(<) += $(ktmp) ;
598   CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
599   CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
603 # /ObjC object : source ;
605 # Compile the ObjC source file _source_. Similar to @CC, called by @Object
607 # Do not call this rule directly, since _object_ and _source_ may have
608 # have platform-specific file extensions
610 rule ObjC {
611   local ktmp ;
613   Depends $(<) : $(>) ;
615   if $(RELOCATE) { CcMv $(<) : $(>) ; }
617   # Just to clarify here: this sets the per-target CCFLAGS to
618   # be the current value of (global) CCFLAGS and SUBDIRCCFLAGS.
619   # CCHDRS and CCDEFS must be reformatted each time for some
620   # compiles (VMS, NT) that malign multiple -D or -I flags.
621   ktmp = $(OBJCFLAGS) ;
622   if ! $(ktmp) { ktmp = $(CCFLAGS) ; }
623   OBJCFLAGS on $(<) += $(ktmp) $(SUBDIROBJCFLAGS) ;
625   ktmp = $(OBJCOPTIM) ;
626   if ! $(ktmp) { ktmp = $(OBJCOPTIM) ; }
627   OBJCOPTIM on $(<) += $(ktmp) ;
629   CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
630   CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
634 # /Chmod target ;
636 # (Unix and VMS only). Change file permissions on _target_ to target-specific
637 # $(MODE) value set by @Link, @File, @Install* and @Shell rules
639 rule Chmod {
640   if $(CHMOD) { Chmod1 $(<) ; }
643 # /Clean  clean : targets ;
645 # Removes existing _targets_ when _clean_ is built. clean is not a dependency
646 # of all, and must be built explicitely for targets to be removed
650 # /File target : source ;
652 # Copies _source_ into _target_
654 rule File {
655   Depends files : $(<) ;
656   Depends $(<) : $(>) ;
657   SEARCH on $(>) = $(SEARCH_SOURCE) ;
658   MODE on $(<) = $(FILEMODE) ;
659   Chmod $(<) ;
663 # /GenFile target : image sources ;
665 # Runs the command "_image_ _target_ _sources_" to create _target_ from
666 # _sources_ and _image_ (where _image_ is an executable built by the
667 # @Main rule)
669 rule GenFile {
670   local _t = [ FGristSourceFiles $(<) ] ;
671   local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;
672   Depends $(_t) : $(_s) $(>[2-]) ;
673   GenFile1 $(_t) : $(_s) $(>[2-]) ;
674   Clean clean : $(_t) ;
677 rule GenFile1 {
678   MakeLocate $(<) : $(LOCATE_SOURCE) ;
679   SEARCH on $(>) = $(SEARCH_SOURCE) ;
683 # /HardLink target : source ;
685 # Makes _target_ a hard link to _source_, if it isn't one already
686 # (Unix only)
688 rule HardLink {
689   Depends files : $(<) ;
690   Depends $(<) : $(>) ;
691   SEARCH on $(>) = $(SEARCH_SOURCE) ;
695 # /HdrMacroFile
697 # this rule is specific to FT-Jam. It is used to indicate that a given file
698 # contains definitions for filename macros (e.g. "#define MYFILE_H <myfile>.h")
699 # that can later be used in #include statements in the rest of the source
701 # these files must be parsed before any make is tried.
703 rule HdrMacroFile {
704   HDRMACRO $(<) ;
708 # /HdrRule source : headers ;
710 # Arranges the proper dependencies when the file _source_ includes the files
711 # _headers_ through the #include C preprocessor directive
713 # this rule is not intendend to be called explicitely. It is called
714 # automatically during header scanning on sources handled by the @Object
715 # rule (e.g. sources in @Main or @Library rules)
717 rule HdrRule {
718   # HdrRule source : headers ;
720   # N.B.  This rule is called during binding, potentially after
721   # the fate of many targets has been determined, and must be
722   # used with caution: don't add dependencies to unrelated
723   # targets, and don't set variables on $(<).
725   # Tell Jam that anything depending on $(<) also depends on $(>),
726   # set SEARCH so Jam can find the headers, but then say we don't
727   # care if we can't actually find the headers (they may have been
728   # within ifdefs),
730   local s = $(>:G=$(HDRGRIST:E)) ;
732   Includes $(<) : $(s) ;
733   SEARCH on $(s) = $(HDRSEARCH) ;
734   NoCare $(s) ;
736   # Propagate on $(<) to $(>)
738   HDRSEARCH on $(s) = $(HDRSEARCH) ;
739   HDRSCAN on $(s) = $(HDRSCAN) ;
740   HDRRULE on $(s) = $(HDRRULE) ;
741   HDRGRIST on $(s) = $(HDRGRIST) ;
745 # /Lex source.c : source.l ;
747 # Process the lex source file _source.l_ and rename the lex.yy.c
748 # to _source.c_ . Called by the @Object rule
750 rule Lex {
751   LexMv $(<) : $(>) ;
752   Depends $(<) : $(>) ;
753   MakeLocate $(<) : $(LOCATE_SOURCE) ;
754   Clean clean : $(<) ;
758 # /Library  library : sources ;
760 #  Compiles _sources_ and archives them into _library_. The intermediate
761 #  objects are deleted. Calles @Object and @LibraryFromObjects
763 #  If @Library is invoked with no suffix on _library_, the $(SUFLIB)
764 #  suffix is used
766 rule Library {
767   LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
768   Objects $(>) ;
772 # /SharedLibrary  library : sources : def : import ;
774 # Compiles _sources_ and generates a shared _library_ (i.e. DLL on Windows,
775 # or shared object on Unix). Calls @SharedObjects and @SharedLibraryFromObjects
777 # If @SharedLibrary is invoked with no suffix on _library_, then
778 # $(SUFLIBSHR) suffix is used
780 # _def_ is the name of the corresponding definition file used to generate
781 # the library on Windows and OS/2 (ignored otherwise). If undefined, it
782 # will default to _library_ with the .def suffix
784 # _import_ is the name of the corresponding import library for Windows
785 # and OS/2 platforms (ignored otherwise). If undefined, it will default
786 # to _library_ with the .dll.lib suffix.
788 rule SharedLibrary {
789   #Echo "SharedLibrary: $(<)" ; #dbg
790   #Echo "SharedLibrary: $(>:S=$(SUFOBJSHR))" ; #dbg
791   #Echo "SharedLibrary: $(3)" ; #dbg
792   #Echo "SharedLibrary: $(4)" ; #dbg
793   SharedLibraryFromObjects $(<) : $(>:S=$(SUFOBJSHR)) : $(3) : $(4) ;
794   SharedObjects $(>) ;
797 ######################################################
798 # k8: REWORK!
799 ######################################################
800 #!LIBTOOL!#if $(UNIX) {
801 #!LIBTOOL!#  # this rule is used to find the 'libtool' script in the current
802 #!LIBTOOL!#  # path, this is required when compiling shared objects on Unix
803 #!LIBTOOL!#  rule LibToolFind {
804 #!LIBTOOL!#    if $(LIBTOOL) { return $(LIBTOOL) ; }
805 #!LIBTOOL!#    local matches = [ Glob $(PATH) : libtool ] ;
806 #!LIBTOOL!#    if ! $(matches) { Exit "could not find 'libtool' program in current path. Aborting !" ; }
807 #!LIBTOOL!#    LIBTOOL = $(matches[1]) ;
808 #!LIBTOOL!#    return $(LIBTOOL) ;
809 #!LIBTOOL!#  }
810 #!LIBTOOL!#}
813 # /LibraryFromObjects library : objects ;
815 # Archives _objects_ into _library_. The _objects_ are then deleted
817 # If _library_ has no suffix, the $(SUFLIB) suffix is used
819 # Called by @Library rule. Most people should never call this rule
820 # directly.
822 rule LibraryFromObjects {
823   local _i _l _s ;
825   # Add grist to file names
826   _s = [ FGristFiles $(>) ] ;
827   _l = $(<:S=$(SUFLIB)) ;
829   # library depends on its member objects
830   if $(KEEPOBJS) {
831     Depends obj : $(_s) ;
832   } else {
833     Depends lib : $(_l) ;
834   }
836   # Set LOCATE for the library and its contents.  The bound
837   # value shows up as $(NEEDLIBS) on the Link actions.
838   # For compatibility, we only do this if the library doesn't
839   # already have a path.
840   if ! $(_l:D) {
841     #!!MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ;
842     MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_LIB) ;
843   }
845   if $(NOARSCAN) {
846     # If we can't scan the library to timestamp its contents,
847     # we have to just make the library depend directly on the
848     # on-disk object files.
849     Depends $(_l) : $(_s) ;
850   } else {
851     # If we can scan the library, we make the library depend
852     # on its members and each member depend on the on-disk
853     # object file.
854     Depends $(_l) : $(_l)($(_s:BS)) ;
855     for _i in $(_s) {
856       Depends $(_l)($(_i:BS)) : $(_i) ;
857     }
858   }
860   Clean clean : $(_l) ;
862   if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; }
864   Archive $(_l) : $(_s) ;
866   if $(RANLIB) { Ranlib $(_l) ; }
868   # If we can't scan the library, we have to leave the .o's around.
870   if ! ( $(NOARSCAN) || $(NOARUPDATE) ) { RmTemps $(_l) : $(_s) ; }
874 # /SharedLibraryFromObjects  library : objects : def : import ;
876 # Equivalent of @LibraryFromObjects for shared libraries.
878 # Called by @SharedLibrary. Most people shouldn't call this rule
879 # directly
881 rule SharedLibraryFromObjects {
882   local _i _l _s ;
884   # Add grist to file names
885   _s = [ FGristFiles $(>) ] ;
886   _l = $(<:S=$(SUFLIBSHR)) ;
888   #Echo "Library is $(_l)"    ;
889   # library depends on its member objects
890   if $(KEEPOBJS) {
891     Depends obj : $(_s) ;
892   } else {
893     Depends lib : $(_l) ;
894   }
896   # Set LOCATE for the library and its contents.  The bound
897   # value shows up as $(NEEDLIBS) on the Link actions.
898   # For compatibility, we only do this if the library doesn't
899   # already have a path.
900   if ! $(_l:D) {
901     #!!MakeLocate $(_l) : $(LOCATE_TARGET) ;
902     MakeLocate $(_l) : $(LOCATE_LIBSO) ;
903   }
905   #Echo "SharedLibraryFromObjects: _s = $(_s)" ; #dbg
906   #Echo "SharedLibraryFromObjects: _l = $(_l)" ; #dbg
908   # we never scan shared libraries for member objects
909   Depends $(_l) : $(_s) ;
911   Clean clean : $(_l) ;
913   # I don't know if VMS supports shared libraries, so I prefer
914   # to disable the following right now
915   #
916   #if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; }
918   # creating the library is so much fun on Unix :-)
919   if $(UNIX) {
920 #!LIBTOOL!#    if $(K8_USE_LIBTOOL) {
921 #!LIBTOOL!#      local libtool = [ LibToolFind ] ;  # find the right libtool
922 #!LIBTOOL!#      AR on $(_l) = "$(libtool) --mode=link $(AR:J= )" ;
923 #!LIBTOOL!#    } else {
924       LINKFLAGS on $(_l) += "-shared" ;
925       C++LINKFLAGS on $(_l) += "-shared" ;
926       LinkUnixLibrary $(_l) : $(_s) ;
927 #!LIBTOOL!#    }
928   } else if $(NT) {
929     local _implib = $(4) ;
930     local _def    = $(3) ;
932     _implib ?= $(_l:S=$(SUFLIBSHR)$(SUFLIB)) ;
933     _def    ?= $(_l:S=.def) ;
935     Clean    clean : $(_implib) ;
936     Depends  lib   : $(_implib) $(_def) ;
938     Depends $(_implib) : $(_def) $(_l) ;
939     Depends $(_l)      : $(_def) ;
941     DEFFILENAME on $(_l) = $(_def) ;
942     IMPLIBNAME  on $(_l) = $(_implib) ;
944     #!!MakeLocate $(_implib)        : $(LOCATE_TARGET) ;
945     #!!MakeLocate $(_implib:S=.exp) : $(LOCATE_TARGET) ;
946     MakeLocate $(_implib)        : $(LOCATE_LIBSO) ;
947     MakeLocate $(_implib:S=.exp) : $(LOCATE_LIBSO) ;
949     if $(JAM_TOOLSET) in VISUALC BORLANDC LCC WATCOM DIGITALMARS {
950       SharedLink-$(JAM_TOOLSET) $(_l) : $(_s) : $(_implib) : $(_def) ;
951     }
952     DllLink $(_l) : $(_s) ;
953   } else {
954     Echo "Sorry, I don't know how to make a shared library on your system" ;
955     Exit "Please *DON'T* contact the K8Jam maintainer for help" ;
956   }
960 # Since building shared libraries is so different depending on the
961 # compiler being used, I've broken this task into compiler-specific
962 # ones
965 rule SharedLink-LCC {
966   Echo "Sorry, but generating DLLs with LCC is not supported. That's" ;
967   Echo "because the 'lcclnk' tool that comes with this compiler is" ;
968   Echo "unreliable and doesn't work as expected." ;
969   Exit ;
971   # the 'lcclnk' tool is absolutely broken:
972   #   - its -o flag doesn't work when there is a LIBRARY statement
973   #     in the .def file.
974   #
975   #   - it uses the LIBRARY name in the .def file to determine
976   #     the name of the dll and its import library, and always
977   #     places them in the current directory !!
978   #
979   #   - if there is no LIBRARY statement, the -o flag is only
980   #     used to determine where the DLL is placed, the import
981   #     library will always be placed in the current directory !!
982   #
984   # clean the .exp file too, don't know how to get rid of it
985   Clean clean : $(4:S=.exp) ;
989 # /Link  image : objects ;
991 # Links _image_ from _objects_ and sets permissions on _image_ to
992 # $(EXEMODE). _image_ must be an actual filename; suffix is not
993 # supplied.
995 # Called by @Main, shouldn't be called by most people
997 rule Link {
998   MODE on $(<) = $(EXEMODE) ;
999   Chmod $(<) ;
1003 # /C++Link  image : objects ;
1005 # Links _image_ from _objects_ and sets permissions on _image_ to
1006 # $(EXEMODE). _image_ must be an actual filename; suffix is not
1007 # supplied.
1009 # Called by @Main, shouldn't be called by most people
1011 rule C++Link {
1012   MODE on $(<) = $(EXEMODE) ;
1013   Chmod $(<) ;
1016 rule ObjC-Link {
1017   MODE on $(<) = $(EXEMODE) ;
1018   Chmod $(<) ;
1022 # /LinkLibraries image : libraries ;
1024 # Makes _image_ depend on _libraries_ and includes them during linking
1026 # _image_ may be referenced without a suffix in this rule invocation.
1027 # @LinkLibraries supplies the suffix
1029 # You should only use this rule with libraries created through the
1030 # @Library rule. For external libraries, use something else (XXX)
1032 rule LinkLibraries {
1033   # make library dependencies of target
1034   # set NEEDLIBS variable used by 'actions Main'
1035   local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
1037   Depends $(_t) : $(>:S=$(SUFLIB)) ;
1038   NEEDLIBS on $(_t) += $(>:S=$(SUFLIB)) ;
1042 # /LinkSharedLibraries image : libraries :
1044 # Same as @LinkLibraries, but to link _image_ with shared libraries
1045 # generated through the @SharedLibrary rule
1047 rule LinkSharedLibraries {
1048   # make library dependencies of target
1049   # set NEEDLIBS variable used by 'actions Main'
1050   local _t   = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
1051   local _ext = $(SUFLIBSHR) ;
1053   if $(NT) {
1054     # on NT, we need to link agains the import library, not the DLL itself !!
1055     _ext = $(SUFLIBSHR)$(SUFLIB) ;
1056   }
1057   Depends $(_t) : $(>:S=$(_ext))  ;
1058   NEEDLIBS on $(_t) += $(>:S=$(_ext)) ;
1062 # /Main image : sources ;
1064 # Compiles _sources_ and links them into _image_. Calls @Objects and
1065 # @MainFromObjects.
1067 # _image_ may be supplied without suffix.
1069 rule Main {
1070   MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
1071   Objects $(>) ;
1075 # /C++Main image : sources ;
1077 # Compiles _sources_ and links them into _image_. Calls @Objects and
1078 # @C++MainFromObjects.
1080 # _image_ may be supplied without suffix.
1082 rule C++Main {
1083   C++MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
1084   Objects $(>) ;
1087 rule ObjC-Main {
1088   ObjC-MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
1089   Objects $(>) ;
1093 # /MainFromObjects image : objects ;
1095 # Links _objects_ into _image_. Dependency of exe.
1096 # @MainFromObjects provides a default suffix for _image_
1098 rule MainFromObjects {
1099   local _s _t ;
1101   # Add grist to file names
1102   # Add suffix to exe
1103   _s = [ FGristFiles $(>) ] ;
1104   _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
1105   # so 'jam foo' works when it's really foo.exe
1107   if $(_t) != $(<) {
1108     Depends $(<) : $(_t) ;
1109     NotFile $(<) ;
1110   }
1112   # make compiled sources a dependency of target
1113   Depends exe : $(_t) ;
1114   Depends $(_t) : $(_s) ;
1115   #k8:MakeLocate $(_t) : $(LOCATE_TARGET) ;
1116   MakeLocate $(_t) : $(LOCATE_BIN) ;
1117   Clean clean : $(_t) ;
1119   # special case for stupid Borland C++, which always generates a
1120   # .tds file for executables, even when no debug information is needed
1121   #
1122   #if $(JAM_TOOLSET) = BORLANDC {
1123   #  MakeLocate $(_t:S=.tds) : $(LOCATE_TARGET) ;
1124   #  Clean  clean : $(_t:S=.tds) ;
1125   #}
1127   Link $(_t) : $(_s) ;
1131 # /C++MainFromObjects image : objects ;
1133 # Links _objects_ into _image_. Dependency of exe.
1134 # @MainFromObjects provides a default suffix for _image_
1136 rule C++MainFromObjects {
1137   local _s _t ;
1139   # Add grist to file names
1140   # Add suffix to exe
1141   _s = [ FGristFiles $(>) ] ;
1142   _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
1143   # so 'jam foo' works when it's really foo.exe
1145   if $(_t) != $(<) {
1146     Depends $(<) : $(_t) ;
1147     NotFile $(<) ;
1148   }
1150   # make compiled sources a dependency of target
1151   Depends exe : $(_t) ;
1152   Depends $(_t) : $(_s) ;
1153   #k8:MakeLocate $(_t) : $(LOCATE_TARGET) ;
1154   MakeLocate $(_t) : $(LOCATE_BIN) ;
1155   Clean clean : $(_t) ;
1157   # special case for stupid Borland C++, which always generates a
1158   # .tds file for executables, even when no debug information is needed
1159   #
1160   #if $(JAM_TOOLSET) = BORLANDC {
1161   #  MakeLocate $(_t:S=.tds) : $(LOCATE_TARGET) ;
1162   #  Clean  clean : $(_t:S=.tds) ;
1163   #}
1165   C++Link $(_t) : $(_s) ;  ###k8:FIXME
1169 rule ObjC-MainFromObjects {
1170   local _s _t ;
1172   # Add grist to file names
1173   # Add suffix to exe
1174   _s = [ FGristFiles $(>) ] ;
1175   _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
1176   # so 'jam foo' works when it's really foo.exe
1178   if $(_t) != $(<) {
1179     Depends $(<) : $(_t) ;
1180     NotFile $(<) ;
1181   }
1183   # make compiled sources a dependency of target
1184   Depends exe : $(_t) ;
1185   Depends $(_t) : $(_s) ;
1186   #k8:MakeLocate $(_t) : $(LOCATE_TARGET) ;
1187   MakeLocate $(_t) : $(LOCATE_BIN) ;
1188   Clean clean : $(_t) ;
1190   ObjC-Link $(_t) : $(_s) ;  ###k8:FIXME
1194 # /MakeLocate  targets : directory
1196 # Creates _dir_ and causes _target_ to be built into _dir_
1198 # This is done by setting the target-specific variable LOCATE
1199 # on _targets_, and arranges with @MkDir to create the target
1200 # directory
1202 rule MakeLocate {
1203   # Note we grist the directory name with 'dir',
1204   # so that directory path components and other
1205   # targets don't conflict.
1206   if $(>) {
1207     LOCATE on $(<) = $(>) ;
1208     Depends $(<) : $(>[1]:G=dir) ;
1209     MkDir $(>[1]:G=dir) ;
1210   }
1214 # /MkDir  dir ;
1216 # Creates _dir_ and its parent directories
1218 rule MkDir {
1219   # Ignore timestamps on directories: we only care if they exist.
1220   NoUpdate $(<) ;
1222   # Don't create . or any directory already created.
1223   if $(<:G=) != $(DOT) && ! $($(<)-mkdir) {
1224     # Cheesy gate to prevent multiple invocations on same dir
1225     # Arrange for jam dirs
1226     # MkDir1 has the actions
1227     $(<)-mkdir = true ;
1228     Depends dirs : $(<) ;
1229     MkDir1 $(<) ;
1231     # Recursively make parent directories.
1232     # $(<:P) = $(<)'s parent, & we recurse until root
1233     local s = $(<:P) ;
1235     # Don't try to create A: or A:\ on windows
1236     if $(NT) {
1237       switch $(s) {
1238         case *:   : s = ;
1239         case *:\\ : s = ;
1240       }
1241     }
1242     # handle "C:", "C:/", "/cygdrive" and "/cygdrive/" in Cygwin
1243     if $(UNIX) && $(OS) = CYGWIN {
1244       switch $(s) {
1245         case ?:   : s = ;
1246         case ?:/  : s = ;
1247         case <dir>/cygdrive   : s = ;
1248         case <dir>/cygdrive/  : s = ;
1249       }
1250     }
1252     if $(s) = $(<) {
1253       # The parent is the same as the dir.
1254       # We're at the root, which some OS's can't stat, so we mark
1255       # it as NotFile.
1256       NotFile $(s) ;
1257     } else if $(s:G=) {
1258       # There's a parent; recurse.
1259       Depends $(<) : $(s) ;
1260       MkDir $(s) ;
1261     }
1262   }
1266 # /Object object : source ;
1268 # Compile s a single _source_ file into _object_. The @Main and @Library
1269 # rules use it to compile sources.
1271 # Causes _source_ to be scanned for #include directives and calls @HdrRule
1272 # to make all included files dependencies of _object_.
1274 # Calls one of the following rules depending on the suffix to do the
1275 # actual compilation:
1277 rule Object {
1278   # locate object and search for source, if wanted
1280   Clean clean : $(<) ;
1281   MakeLocate $(<) : $(LOCATE_TARGET) ;
1282   SEARCH on $(>) = $(SEARCH_SOURCE) ;
1284   # Save HDRS for -I$(HDRS) on compile.
1285   # We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers
1286   # in the .c file's directory, but generated .c files (from
1287   # yacc, lex, etc) are located in $(LOCATE_TARGET), possibly
1288   # different from $(SEARCH_SOURCE).
1289   HDRS on $(<) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ;
1291   # handle #includes for source: Jam scans for headers with
1292   # the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE)
1293   # with the scanned file as the target and the found headers
1294   # as the sources.  HDRSEARCH is the value of SEARCH used for
1295   # the found header files.  Finally, if jam must deal with
1296   # header files of the same name in different directories,
1297   # they can be distinguished with HDRGRIST.
1299   # $(SEARCH_SOURCE:E) is where cc first looks for #include
1300   # "foo.h" files.  If the source file is in a distant directory,
1301   # look there.  Else, look in "" (the current directory).
1303   HDRRULE on $(>) = HdrRule ;
1304   HDRSCAN on $(>) = $(HDRPATTERN) ;
1305   HDRSEARCH on $(>) = $(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ;
1306   HDRGRIST on $(>) = $(HDRGRIST) ;
1308   # propagate target specific-defines
1309   DEFINES on $(<) += $(DEFINES) ;
1311   # if source is not .c, generate .c with specific rule
1312   switch $(>:S) {
1313     case .asm : As $(<) : $(>) ;
1314     case .c :   Cc $(<) : $(>) ;
1315     case .C :   C++ $(<) : $(>) ;
1316     case .cc :  C++ $(<) : $(>) ;
1317     case .cpp : C++ $(<) : $(>) ;
1318     case .cxx : C++ $(<) : $(>) ;
1319     case .c++ : C++ $(<) : $(>) ;
1320     case .C++ : C++ $(<) : $(>) ;
1321     case .m :   ObjC $(<) : $(>) ;
1322     case .d :   Dc $(<) : $(>) ;
1323     case .l :   Cc $(<) : $(<:S=.c) ;
1324                 Lex $(<:S=.c) : $(>) ;
1325     case .s :   As $(<) : $(>) ;
1326     case .y :   Cc $(<) : $(<:S=$(YACCGEN)) ;
1327                 Yacc $(<:S=$(YACCGEN)) : $(>) ;
1328     case * :    UserObject $(<) : $(>) ;
1329   }
1333 # /ObjectCcFlags  sources : flags ;
1335 # this rule is used to add compiler flags to the compilation of
1336 # specific C sources files.
1338 rule ObjectCcFlags {
1339   CCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
1343 # /ObjectC++Flags  sources : flags ;
1345 # this rule is used to add compiler flags to the compilation of
1346 # specific C++ source files
1348 rule ObjectC++Flags {
1349   C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
1353 rule ObjectObjCFlags {
1354   OBJCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
1358 # /LinkFlagsOn  mains : flags ;
1360 # this rule is used to add compiler flags to the compilation of
1361 # specific C sources files.
1363 rule LinkFlagsOn {
1364   LINKFLAGS on [ FGristFiles $(<) ] += $(>) ;
1368 # /C++LinkFlagsOn  mains : flags ;
1370 # this rule is used to add compiler flags to the compilation of
1371 # specific C++ source files
1373 rule C++LinkFlagsOn {
1374   C++LINKFLAGS on [ FGristFiles $(<) ] += $(>) ;
1378 rule ObjCLinkFlagsOn {
1379   OBJCLINKFLAGS on [ FGristFiles $(<) ] += $(>) ;
1383 # /ObjectDefines  objects : macros ;
1385 # this rule is used to add macro defines to the compilation of
1386 # specific C and C++ source files
1388 rule ObjectDefines {
1389   # must reformat CCDEFS according to current defines
1390   local s = [ FGristFiles $(<:S=$(SUFOBJ)) ] ;
1392   DEFINES on $(s) += $(>) ;
1393   CCDEFS on $(s) = [ on $(s) FDefines $(DEFINES) ] ;
1397 # /ObjectHdrs  sources : paths ;
1399 # this rule is used to add include paths to the compilation of
1400 # specific C and C++ source files
1402 rule ObjectHdrs {
1403   # Add to HDRS for HdrScan's benefit.
1404   # must reformat CCHDRS according to headers
1405   local s = [ FGristFiles $(<:S=$(SUFOBJ)) ] ;
1407   HDRS on $(s) += $(>) ;
1408   CCHDRS on $(s) = [ on $(s) FIncludes $(HDRS) ] ;
1412 # /Objects sources ;
1414 # this rule is used to compile one or more sources into object files.
1415 # do not call it directly, it is used by the Main and Library rules
1416 # automatically
1418 rule Objects {
1419   local _i ;
1421   for _i in [ FGristFiles $(<) ] {
1422     Object $(_i:S=$(SUFOBJ)) : $(_i) ;
1423     Depends obj : $(_i:S=$(SUFOBJ)) ;
1424   }
1428 # /SharedObjects
1430 # this rule is used to compile one or more sources into 'shared object
1431 # files'. This means object files used to build either DLLs or Unix shared
1432 # libraries.
1434 # do not call this rule directly, it is called by SharedLibrary automatically
1436 rule SharedObjects {
1437   # temporarily override SUFOBJ with $(SUFOBJSHR) to
1438   local SUFOBJ = $(SUFOBJSHR) ;
1440   # call the normal Objects rule
1441   Objects $(<) ;
1443   # add the compiler-specific position-independent-code flag  where needed
1444   ObjectCcFlags $(<) : $(PICFLAGS) ;
1446   # change the compiler invokation for all these objects
1447   # to use Libtool on Unix systems. We explicitely disable the
1448   # generation of static objects here
1449 #!LIBTOOL!#  if $(UNIX) {
1450 #!LIBTOOL!#    #libtool on $(<:S=$(SUFOBJ)) = [ LibToolFind ] ;
1451 #!LIBTOOL!#    if $(K8_USE_LIBTOOL) {
1452 #!LIBTOOL!#      local libtool = [ LibToolFind ] ;
1453 #!LIBTOOL!#      CC on $(<:S=$(SUFOBJ)) = "$(libtool) --mode=compile $(CC:J= ) -dynamic" ;
1454 #!LIBTOOL!#      C++ on $(<:S=$(SUFOBJ)) = "$(libtool) --mode=compile $(C++:J= ) -dynamic" ; #k8:?
1455 #!LIBTOOL!#    }
1456 #!LIBTOOL!#  }
1460 rule RmTemps {
1461   Temporary $(>) ;
1465 rule Setuid {
1466   MODE on [ FAppendSuffix $(<) : $(SUFEXE) ] = 4711 ;
1470 rule Shell {
1471   Depends shell : $(<) ;
1472   Depends $(<) : $(>) ;
1473   SEARCH on $(>) = $(SEARCH_SOURCE) ;
1474   MODE on $(<) = $(SHELLMODE) ;
1475   Clean clean : $(<) ;
1476   Chmod $(<) ;
1480 rule SoftLink {
1481   Depends files : $(<) ;
1482   Depends $(<) : $(>) ;
1483   SEARCH on $(>) = $(SEARCH_SOURCE) ;
1484   Clean clean : $(<) ;
1488 rule SubDir {
1489   #
1490   # SubDir TOP d1 d2 ... ;
1491   #
1492   # Support for a project tree spanning multiple directories.
1493   #
1494   # SubDir declares a Jamfile's location in a project tree, setting
1495   # Jambase variables (SEARCH_SOURCE, LOCATE_TARGET) so that source
1496   # files can be found.
1497   #
1498   # TOP is a user-select variable name for root of the tree, and
1499   # d1 d2 ...  are the directory elements that lead from the root
1500   # of the tree to the directory of the Jamfile.
1501   #
1502   # TOP can be set externally, but normally the first SubDir call
1503   # computes TOP as the path up from the current directory; the
1504   # path contains one ../ for each of d1 d2 ...
1505   #
1506   # SubDir reads once the project-specific rules file Jamrules
1507   # in the TOP directory, if present.  This can be overridden
1508   # with the variable TOPRULES.
1509   #
1510   # SubDir supports multiple, overlaid project trees:  SubDir
1511   # invocations with different TOPs can appear in the same Jamfile.
1512   # The location established by the first SubDir call is used set
1513   # the TOPs for the subsequent SubDir calls.
1514   #
1515   # SubDir's public variables:
1516   #
1517   #   $(TOP) = path from CWD to root.
1518   #   $(SUBDIR) = path from CWD to the directory SubDir names.
1519   #   $(SUBDIR_TOKENS) = path from $(TOP) to $(SUBDIR) as dir names
1520   #   $(SEARCH_SOURCE) = $(SUBDIR)
1521   #   $(LOCATE_SOURCE) = $(ALL_LOCATE_TARGET) $(SUBDIR)
1522   #   $(LOCATE_TARGET) = $(ALL_LOCATE_TARGET) $(SUBDIR)
1523   #   $(LOCATE_BIN) = $(ALL_LOCATE_BIN) $(ALL_LOCATE_TARGET) $(SUBDIR)
1524   #   $(LOCATE_LIB) = $(ALL_LOCATE_LIB) $(ALL_LOCATE_TARGET) $(SUBDIR)
1525   #   $(LOCATE_LIBSO) = $(ALL_LOCATE_LIBSO) $(ALL_LOCATE_LIB) $(ALL_LOCATE_TARGET) $(SUBDIR)
1526   #   $(SOURCE_GRIST) = $(SUBDIR_TOKENS) with !'s
1527   #
1528   local _top = $(<[1]) ;
1529   local _tokens = $(<[2-]) ;
1531   local ktmp ;
1533   # First time through sets up relative root and includes Jamrules.
1534   if ! $(_top) { Exit SubDir syntax error ; }
1536   if ! $($(_top)-SET) {
1537     $(_top)-SET = true ;
1538     # First time we've seen this TOP.
1539     # We'll initialize a number of internal variables:
1540     #
1541     #   $(TOP-UP) = directories from ROOT to a common point
1542     #   $(TOP-DOWN) = directories from common point to TOP
1543     #   $(TOP-ROOT) = root directory for UP/DOWN -- normally CWD
1544     #   $(SUBDIR_UP) = current value of $(TOP-UP)
1545     #   $(SUBDIR_DOWN) = current value of $(TOP-DOWN)
1546     #   $(SUBDIR_ROOT) = current value of $(TOP-ROOT)
1547     #
1548     if $($(_top)) {
1549       # TOP externally set.
1550       # We'll ignore the relative (UP/DOWN) path that
1551       # got us here, and instead remember the hard ROOT.
1552       $(_top)-UP = ;
1553       $(_top)-DOWN = ;
1554       $(_top)-ROOT = $($(_top)) ;
1555     } else {
1556       # TOP not preset.
1558       # Establishing a new TOP.  In the simplest case,
1559       # (SUBDIR_UP/SUBDIR_DOWN/SUBDIR_ROOT unset), it's
1560       # merely a certain number of directories down from
1561       # the current directory, and FSubDirPath will set
1562       # TOP to a path consisting of ../ for each of the
1563       # elements of _tokens, because that represents how
1564       # far below TOP the current directory sits.
1565       #
1566       # In the more complicated case, the starting directory
1567       # isn't the directory of jam's invocation but an
1568       # location established by previous SubDir call.  The
1569       # starting directory is SUBDIR_UP directories up from
1570       # SUBDIR_ROOT, and then SUBDIR_DOWN directories down
1571       # from that.   If SUBDIR_ROOT is not set, that means
1572       # SUBDIR_DOWN and SUBDIR_UP represent the path from
1573       # the directory of jam's invocation.
1574       #
1575       # In the most complicated case, the _tokens also
1576       # represents directories down, because TOP is being
1577       # estalished in a directory other than TOP's root.
1578       # Hopefully, _tokens and SUBDIR_DOWN represent the
1579       # same final directory, relative to the new TOP and
1580       # the previous SubDIr's TOP.  To find the new TOP,
1581       # we have to chop off any common directories from
1582       # then ends of _tokens and SUBDIR_DOWN.  To do so,
1583       # we reverse each of them, call FStripCommon to
1584       # remove the initial common elements, and then
1585       # reverse them again.  After this process, if
1586       # both _tokens and SUBDIR_DOWN have elements, it
1587       # means the directory names estalished by the two
1588       # SubDir calls don't match, and a warning is issued.
1589       # All hell will likely break loose at this point,
1590       # since the whole SubDir scheme relies on the SubDir
1591       # calls accurately naming the current directory.
1593       # Strip common trailing elements of _tokens and SUBDIR_DOWN.
1594       _tokens = [ FReverse $(_tokens) ] ;
1595       SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
1596       FStripCommon _tokens : SUBDIR_DOWN ;
1597       SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
1598       _tokens = [ FReverse $(_tokens) ] ;
1600       if $(SUBDIR_DOWN) && $(_tokens) { Echo Warning: SubDir $(<) misplaced! ; }
1602       # We'll remember the relative (UP/DOWN) path that
1603       # got us here, plus any hard ROOT starting point
1604       # for the UP/DOWN.  If TOP is never set externally,
1605       # ROOT will always be "" (directory of jam's invocation).
1606       $(_top)-UP = $(SUBDIR_UP) $(_tokens) ;
1607       $(_top)-DOWN = $(SUBDIR_DOWN) ;
1608       $(_top)-ROOT = $(SUBDIR_ROOT:E="") ;
1609       $(_top) = [ FSubDirPath $(_top) ] ;
1610     }
1612     # Set subdir vars for the inclusion of the Jamrules,
1613     # just in case they have SubDir rules of their own.
1614     # Note that SUBDIR_DOWN is empty: it's all the way
1615     # up where the Jamrules live.  These gets overrided
1616     # just after the inclusion.
1617     SUBDIR_UP = $($(_top)-UP) ;
1618     SUBDIR_DOWN = ;
1619     SUBDIR_ROOT = $($(_top)-ROOT) ;
1621     # Include $(TOPRULES) or $(TOP)/Jamrules.
1622     # Include $(TOPRULES) if set.
1623     # Otherwise include $(TOP)/Jamrules if present.
1624     if $($(_top)RULES) {
1625       include $($(_top)RULES) ;
1626     } else {
1627       NoCare $(JAMRULES:R=$($(_top)):G=$(_top)) ;
1628       include $(JAMRULES:R=$($(_top)):G=$(_top)) ;
1629     }
1630   }
1632   # Get path from $(TOP) to named directory.
1633   # Save dir tokens for other potential uses.
1634   SUBDIR_UP = $($(_top)-UP) ;
1635   SUBDIR_DOWN = $($(_top)-DOWN) $(_tokens) ;
1636   SUBDIR_ROOT = $($(_top)-ROOT) ;
1637   SUBDIR_TOKENS = $(SUBDIR_DOWN) ;
1639   SUBDIR = [ FSubDirPath $(<) ] ;
1641   # Now set up SEARCH_SOURCE, LOCATE_TARGET, LOCATE_BIN, SOURCE_GRIST
1642   # These can be reset if needed.  For example, if the source
1643   # directory should not hold object files, LOCATE_TARGET can
1644   # subsequently be redefined.
1645   SEARCH_SOURCE = $(SUBDIR) ;
1646   LOCATE_SOURCE = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
1647   LOCATE_TARGET = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
1649   ktmp = $(ALL_LOCATE_BIN) ;
1650   if ! $(ktmp) { ktmp = $(ALL_LOCATE_TARGET) ; }
1651   LOCATE_BIN = $(ktmp) $(SUBDIR) ;
1653   ktmp = $(ALL_LOCATE_LIB) ;
1654   if ! $(ktmp) { ktmp = $(ALL_LOCATE_TARGET) ; }
1655   LOCATE_LIB = $(ktmp) $(SUBDIR) ;
1657   ktmp = $(ALL_LOCATE_LIBSO) ;
1658   if ! $(ktmp) { ktmp = $(ALL_LOCATE_LIB) ; }
1659   if ! $(ktmp) { ktmp = $(ALL_LOCATE_TARGET) ; }
1660   LOCATE_LIBSO = $(ktmp) $(SUBDIR) ;
1662   SOURCE_GRIST = [ FGrist $(SUBDIR_TOKENS) ] ;
1663   #if ! $(LOCATE_BIN) { LOCATE_BIN = $(LOCATE_TARGET) ; }
1665   # Reset per-directory ccflags, hdrs, etc,
1666   # listed in SUBDIRRESET.
1667   # Note use of variable expanded assignment var
1668   SUBDIR$(SUBDIRRESET) = ;
1670   # Invoke user-specific SubDir extensions,
1671   # rule names listed in SUBDIRRULES.
1672   # Note use of variable expanded rule invocation
1673   $(SUBDIRRULES) $(<) ;
1677 rule FSubDirPath {
1678   # FSubDirPath TOP d1 ... ;
1680   # Returns path to named directory.
1682   # If jam is invoked in a subdirectory of the TOP, then we
1683   # need to prepend a ../ for every level we must climb up
1684   # (TOP-UP), and then append the directory names we must
1685   # climb down (TOP-DOWN), plus the named directories d1 ...
1686   # If TOP was set externally, or computed from another TOP
1687   # that was, we'll have to reroot the whole thing at TOP-ROOT.
1688   local _r = [ FRelPath $($(<[1])-UP) : $($(<[1])-DOWN) $(<[2-]) ] ;
1690   return $(_r:R=$($(<[1])-ROOT)) ;
1694 rule SubDirDcFlags {
1695   SUBDIRDCFLAGS += $(<) ;
1699 rule SubDirCcFlags {
1700   SUBDIRCCFLAGS += $(<) ;
1704 rule SubDirC++Flags {
1705   SUBDIRC++FLAGS += $(<) ;
1709 rule SubDirObjCFlags {
1710   SUBDIROBJCFLAGS += $(<) ;
1714 rule SubDirHdrs {
1715   SUBDIRHDRS += [ FDirName $(<) ] ;
1719 rule SubInclude {
1720   # SubInclude TOP d1 ... ;
1721   #
1722   # Include a subdirectory's Jamfile.
1724   # We use SubDir to get there, in case the included Jamfile
1725   # either doesn't have its own SubDir (naughty) or is a subtree
1726   # with its own TOP.
1727   #Echo "including " $(<) " : " $(>) ;
1729   if ! $($(<[1])) { Exit SubInclude $(<[1]) without prior SubDir $(<[1]) ; }
1730   SubDir $(<) ;
1731   include $(JAMFILE:D=$(SUBDIR)) ;
1735 rule SubIncludeOnce {
1736   # SubIncludeOnce varname : TOP d1 ... ;
1737   #
1738   # Include a subdirectory's Jamfile.
1740   local _vn = $(<[1]) ;
1741   if ! $($(_vn)) {
1742     #Echo "processing $(_vn)" ;
1743     #Echo "$(>)" ;
1744     $(_vn) = tan ;
1745     SubInclude $(>) ;
1746   #} else {
1747   #  Echo "skiped $(_vn) -- $($(_vn))" ;
1748   #  Echo "$(>)" ;
1749   }
1753 rule SubRules {
1754   # SubRules TOP d1 ... : Other-TOP ;
1755   #
1756   # Read another tree's Jamrules, by giving it's path according
1757   # to this tree and it's own name.
1758   if ! $($(<[1])) { Exit SubRules $(<[1]) without prior SubDir $(<[1]) ; }
1759   SubDir $(<) ;
1760   SubDir $(>) ;
1764 rule Undefines {
1765   UNDEFS on [ FAppendSuffix $(<) : $(SUFEXE) ] += $(UNDEFFLAG)$(>) ;
1769 rule UserObject {
1770   Exit "Unknown suffix on" $(>) "- see UserObject rule in Jamfile(5)." ;
1774 rule Yacc {
1775   local _h ;
1777   _h = $(<:BS=.h) ;
1779   # Some places don't have a yacc.
1780   MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ;
1782   if $(YACC) {
1783     Depends $(<) $(_h) : $(>) ;
1784     Yacc1 $(<) $(_h) : $(>) ;
1785     YaccMv $(<) $(_h) : $(>) ;
1786     Clean clean : $(<) $(_h) ;
1787   }
1789   # make sure someone includes $(_h) else it will be
1790   # a deadly independent target
1791   Includes $(<) : $(_h) ;
1796 # Utility rules; no side effects on these
1800 # /FGrist path to file ;
1802 # Returns a single string that is used as grist
1804 rule FGrist {
1805   return $(<:J=!) ;
1809 rule FGristFiles {
1810   return $(<:G=$(SOURCE_GRIST:E)) ;
1814 rule FGristSourceFiles {
1815   # Produce source file name name with grist in it,
1816   # if SOURCE_GRIST is set.
1818   # Leave header files alone, because they have a global
1819   # visibility.
1820   if ! $(SOURCE_GRIST) {
1821     return $(<) ;
1822   } else {
1823     local _i _o ;
1825     for _i in $(<) {
1826       switch $(_i) {
1827         case *.h : _o += $(_i) ;
1828         case * :   _o += $(_i:G=$(SOURCE_GRIST)) ;
1829       }
1830     }
1831     return $(_o) ;
1832   }
1836 rule FReverse {
1837   if $(1) { return [ FReverse $(1[2-]) ] $(1[1]) ; }
1841 rule FSubDir {
1842   # If $(>) is the path to the current directory, compute the
1843   # path (using ../../ etc) back to that root directory.
1844   # Sets result in $(<)
1845   if ! $(<[1]) {
1846     return $(DOT) ;
1847   } else {
1848     local _i _d ;
1850     _d = $(DOTDOT) ;
1851     for _i in $(<[2-]) { _d = $(_d:R=$(DOTDOT)) ; }
1852     return $(_d) ;
1853   }
1857 rule FStripCommon {
1858   # FStripCommon v1 : v2 ;
1860   # Strip common initial elements of variables v1 and v2.
1861   # Modifies the variable values themselves.
1862   if $($(<)[1]) && $($(<)[1]) = $($(>)[1]) {
1863     $(<) = $($(<)[2-]) ;
1864     $(>) = $($(>)[2-]) ;
1865     FStripCommon $(<) : $(>) ;
1866   }
1870 rule FRelPath {
1871   local _l _r ;
1873   # first strip off common parts
1874   _l = $(<) ;
1875   _r = $(>) ;
1876   FStripCommon _l : _r ;
1878   # now make path to root and path down
1879   _l = [ FSubDir $(_l) ] ;
1880   _r = [ FDirName $(_r) ] ;
1882   # Concatenate and save
1883   # XXX This should be better
1884   if $(_r) = $(DOT) { return $(_l) ; } else { return $(_r:R=$(_l)) ; }
1888 rule FAppendSuffix {
1889   # E.g., "FAppendSuffix yacc lex foo.bat : $(SUFEXE) ;"
1890   # returns (yacc,lex,foo.bat) on Unix and
1891   # (yacc.exe,lex.exe,foo.bat) on NT.
1892   if $(>) {
1893     local _i _o ;
1895     for _i in $(<) {
1896       if $(_i:S) { _o += $(_i) ; } else { _o += $(_i:S=$(>)) ; }
1897     }
1898     return $(_o) ;
1899   } else {
1900     return $(<) ;
1901   }
1906 # Operating system specific utility rules
1907 # First, the (generic) UNIX versions
1910 rule FQuote { return "\\\"$(<)\\\"" ; }
1911 rule FDefines { return -D$(<) ; }
1912 rule FIncludes { return -I$(<) ; }
1914 rule FDirName {
1915   # Turn individual elements in $(<) into a usable path.
1916   local _i ;
1917   local _s = $(DOT) ;
1919   for _i in $(<) { _s = $(_i:R=$(_s)) ; }
1920   return $(_s) ;
1924 if $(NT) && $(JAM_TOOLSET) != MINGW && $(JAM_TOOLSET) != LCC {
1925   rule FDefines { return /D$(<) ; }
1926   rule FIncludes { return /I$(<) ; }
1931 # various install rules
1934 rule InstallInto {
1935   # InstallInto dir : sources ;
1937   local i t ;
1939   t = $(>:G=$(INSTALLGRIST)) ;
1941   # Arrange for jam install
1942   # Arrange for jam uninstall
1943   # sources are in SEARCH_SOURCE
1944   # targets are in dir
1946   Depends install : $(t) ;
1947   Clean uninstall : $(t) ;
1948   SEARCH on $(>) = $(SEARCH_SOURCE) ;
1949   MakeLocate $(t) : $(<) ;
1951   # For each source, make gristed target name
1952   # and Install, Chmod, Chown, and Chgrp
1953   for i in $(>) {
1954     local tt = $(i:G=$(INSTALLGRIST)) ;
1956     Depends $(tt) : $(i) ;
1957     Install $(tt) : $(i) ;
1958     Chmod $(tt) ;
1960     if $(OWNER) && $(CHOWN) {
1961       Chown $(tt) ;
1962       OWNER on $(tt) = $(OWNER) ;
1963     }
1964     if $(GROUP) && $(CHGRP) {
1965       Chgrp $(tt) ;
1966       GROUP on $(tt) = $(GROUP) ;
1967     }
1968   }
1972 # /InstallBin dir : sources ;
1974 # Copy _sources_ into _dir_ with mode $(EXEMODE)
1976 rule InstallBin {
1977   local _t = [ FAppendSuffix $(>) : $(SUFEXE) ] ;
1979   InstallInto $(<) : $(_t) ;
1980   MODE on $(_t:G=$(INSTALLGRIST)) = $(EXEMODE) ;
1984 # /InstallFile dir : sources ;
1986 # Copy _sources_ into _dir_ with mode $(FILEMODE)
1988 rule InstallFile {
1989   InstallInto $(<) : $(>) ;
1990   MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
1994 # /InstallLib dir : sources ;
1996 # Copy _sources_ into _dir_ with mode $(FILEMODE)
1998 rule InstallLib {
1999   InstallInto $(<) : $(>) ;
2000   MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
2004 # /InstallMan dir : sources ;
2006 #  Copy _sources_ into the appropriate subdirectory of _dir_ with mode
2007 #  $(FILEMODE). The subdirectory is manS, where S is the suffix of each of
2008 #  sources.
2010 rule InstallMan {
2011   # Really this just strips the . from the suffix
2012   local i s d ;
2014   for i in $(>) {
2015     switch $(i:S) {
2016       case .1 : s = 1 ; case .2 : s = 2 ; case .3 : s = 3 ;
2017       case .4 : s = 4 ; case .5 : s = 5 ; case .6 : s = 6 ;
2018       case .7 : s = 7 ; case .8 : s = 8 ; case .l : s = l ;
2019       case .n : s = n ; case .man : s = 1 ;
2020     }
2021     d = man$(s) ;
2022     InstallInto $(d:R=$(<)) : $(i) ;
2023   }
2024   MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
2028 # /InstallShell dir : sources ;
2030 # Copy _sources_ into _dir_ with mode $(SHELLMODE)
2032 rule InstallShell {
2033   InstallInto $(<) : $(>) ;
2034   MODE on $(>:G=$(INSTALLGRIST)) = $(SHELLMODE) ;
2039 # Actions
2043 # First the defaults
2045 actions updated together piecemeal Archive {
2046   $(AR) $(<) $(>)
2050 actions As {
2051   $(AS) $(ASFLAGS) $(ASHDRS) -o $(<) $(>)
2055 actions C++ {
2056   $(C++) -c -o $(<) $(C++FLAGS) $(C++OPTIM) $(CCDEFS) $(CCHDRS) $(>)
2060 actions Cc {
2061   $(CC) -c -o $(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>)
2065 actions ObjC {
2066   $(OBJCC) -c -o $(<) $(OBJCFLAGS) $(OBJCOPTIM) $(CCDEFS) $(CCHDRS) $(>)
2070 actions Dc {
2071   $(DC) -c -of$(<) $(DCFLAGS) $(DOPTIM) $(>)
2075 actions Chgrp {
2076   $(CHGRP) $(GROUP) $(<)
2080 actions Chmod1 {
2081   $(CHMOD) $(MODE) $(<)
2085 actions Chown {
2086   $(CHOWN) $(OWNER) $(<)
2090 actions piecemeal together existing Clean {
2091   $(RM) $(>)
2095 actions File {
2096   $(CP) $(>) $(<)
2100 actions GenFile1 {
2101   $(>[1]) $(<) $(>[2-])
2105 actions HardLink {
2106   $(RM) $(<) && $(LN) $(>) $(<)
2110 actions Install {
2111   $(CP) $(>) $(<)
2115 actions Lex {
2116   $(LEX) $(>)
2120 actions LexMv {
2121   $(MV) lex.yy.c $(<)
2125 actions Link bind NEEDLIBS {
2126   $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
2129 actions C++Link bind NEEDLIBS {
2130   $(C++LINK) $(C++LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(C++LINKLIBS)
2133 actions ObjC-Link bind NEEDLIBS {
2134   $(OBJCLINK) $(OBJCLINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(OBJCLINKLIBS)
2138 actions updated together piecemeal LinkUnixLibrary bind NEEDLIBS {
2139   $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
2142 actions updated together piecemeal C++LinkUnixLibrary bind NEEDLIBS {
2143   $(C++LINK) $(C++LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(C++LINKLIBS)
2147 actions MkDir1 {
2148   $(MKDIR) $(<)
2152 actions together Ranlib {
2153   $(RANLIB) $(<)
2157 actions quietly updated piecemeal together RmTemps {
2158   $(RM) $(>)
2162 actions Shell {
2163 #DONT_TOUCH
2164   $(AWK) '
2165     NR == 1 { print "$(SHELLHEADER)" }
2166     NR == 1 && /^[#:]/ { next }
2167     /^##/ { next }
2168     { print }
2169   ' < $(>) > $(<)
2170 #DONT_TOUCH
2174 actions SoftLink {
2175   $(RM) $(<) && $(LN) -s $(>) $(<)
2179 actions Yacc1 {
2180   $(YACC) $(YACCFLAGS) $(>)
2184 actions YaccMv {
2185   $(MV) $(YACCFILES).c $(<[1])
2186   $(MV) $(YACCFILES).h $(<[2])
2191 # RELOCATE - for compilers with broken -o flags
2193 if $(RELOCATE) {
2194   actions C++ {
2195     $(C++) -c $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>)
2196   }
2197   actions Cc {
2198     $(CC) -c $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>)
2199   }
2200   actions ignore CcMv {
2201     [ $(<) != $(>:BS=$(SUFOBJ)) ] && $(MV) $(>:BS=$(SUFOBJ)) $(<)
2202   }
2207 # NOARUPDATE - can't update an archive
2209 if $(NOARUPDATE) {
2210   actions Archive {
2211     $(AR) $(<) $(>)
2212   }
2217 # UNIX specific actions
2219 if $(UNIX) {
2220   actions GenFile1 {
2221     PATH="$PATH:."
2222     $(>[1]) $(<) $(>[2-])
2223   }
2228 # NT specific actions
2230 if $(NT) {
2231   if $(JAM_TOOLSET) = MINGW {
2232     actions together piecemeal Archive {
2233       $(AR) $(<) $(>:T)
2234     }
2235     actions Cc {
2236       $(CC) -c -o $(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) -I$(STDHDRS) $(>)
2237     }
2238     actions C++ {
2239       $(C++) -c -o $(<) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) -I$(STDHDRS) $(>)
2240     }
2241     actions DllLink bind DEFFILENAME IMPLIBNAME {
2242       $(LINK) $(LINKFLAGS) -shared -o $(<) $(>) $(DEFFILENAME) -Wl,--out-implib,$(IMPLIBNAME)
2243     }
2244   } else if $(JAM_TOOLSET) = LCC {
2245     actions together piecemeal Archive {
2246       $(AR) /out:$(<) $(>)
2247     }
2248     actions Cc {
2249       $(CC) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) -Fo$(<) -I$(STDHDRS) $(>)
2250     }
2251     actions Link bind NEEDLIBS {
2252       $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
2253     }
2254     actions DllLink bind NEEDLIBS DEFFILENAME {
2255       $(LINK) $(LINKFLAGS) -DLL -o $(<) $(UNDEFS) $(>) $(DEFFILENAME) $(NEEDLIBS) $(LINKLIBS)
2256     }
2257     actions ignore DllLinkMv {
2258       $(MV) $(2) $(1)
2259     }
2260     actions Shell {
2261       $(CP) $(>) $(<)
2262     }
2263   } else if $(JAM_TOOLSET) = PELLESC {
2264     actions together piecemeal Archive {
2265       $(AR) /OUT:$(<) $(>)
2266     }
2267     actions Cc {
2268       $(CC) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS)   /Fo $(<) -I$(STDHDRS)  $(>)
2269     }
2270     actions Link bind NEEDLIBS {
2271       $(LINK) $(LINKFLAGS) /OUT:$(<) $(>) $(NEEDLIBS) $(LINKLIBS)
2272     }
2273     actions DllLink bind NEEDLIBS DEFFILENAME IMPLIBNAME {
2274       $(LINK) $(LINKFLAGS) /DLL /DEF:$(DEFFILENAME) /IMPLIB:$(IMPLIBNAME) /OUT:$(<) $(>) $(NEEDLIBS) $(LINKLIBS)
2275     }
2276     actions Shell {
2277       $(CP) $(>) $(<)
2278     }
2279   }
2284 # Ketmar's additions
2287 rule CheckGCC42Plus {
2288   local t gccv ;
2290   t = [ Match "(gcc)" : "$(CC)" ] ;
2291   if $(t) != "gcc" { return "ona" ; }
2292   gccv = [ Command "gcc --version | line 1" ] ;
2294   t = [ Match "[\t\r\n ]+([0-9]+\\.)[0-9]+\\." : "$(gccv)" ] ;
2295   if $(t) != "4." { return "ona" ; }
2297   t = [ Match "[\t\r\n ]+[0-9]+\\.([0-9]+\\.)" : "$(gccv)" ] ;
2298   if $(t) = "0." { return "ona" ; }
2299   if $(t) = "1." { return "ona" ; }
2301   return "tan" ;
2305 rule SetCPUFlags {
2306   local t flg f skiping seting ;
2308   if $(OS) != "LINUX" {
2309     DETECTED_CPU = "i486" ;
2310     OPTIM_SPEED = -O3 -march=i486 -mtune=i486 ;
2311     return ;
2312   }
2314   t = [ CheckGCC42Plus ] ;
2315   if $(t) = "tan" {
2316     DETECTED_CPU = native ;
2317     OPTIM_SPEED = -O3 -march=native -mtune=native ;
2318     return ;
2319   }
2321   OPTIM_SPEED = ;
2322   # regexp, flags, empty
2323   flg =
2324     "([Ii]ntel.*[Cc]ore.*[Dd]uo)"
2325     "prescott"
2326     -O3 -march=prescott -mtune=prescott -mfpmath=sse
2327     ""
2328     "([Pp]entium.*III)"
2329     "pentium3"
2330     -O3 -march=pentium3 -mtune=pentium3 -mfpmath=sse
2331     ""
2332     "([Pp]entium.*II)"
2333     "pentium2"
2334     -O3 -march=pentium2 -mtune=pentium2
2335     ""
2336     "([Pp]entium)"
2337     "pentium"
2338     -O3 -march=pentium -mtune=pentium
2339     ""
2340   ;
2341   DETECTED_CPU = [ Command "uname -p" ] ;
2342   for f in $(flg) {
2343     if $(skiping) {
2344       if ! $(f) { skiping = ; }
2345     } else if $(seting) {
2346       if ! $(f) { return ; }
2347       if $(seting) = "first" {
2348         DETECTED_CPU = "$(f)" ;
2349         seting = tan ;
2350       } else {
2351         OPTIM_SPEED += "$(f)" ;
2352       }
2353     } else {
2354       t = [ Match "$(f)" : "$(DETECTED_CPU)" ] ;
2355       if $(t) { seting = first ; } else { skiping = tan ; }
2356     }
2357   }
2361 # VAR = [ RemoveOpt options-to-remove : options-list ] ;
2362 # remove options from list
2363 rule RemoveOpt {
2364   local oname = $(1) ;
2365   local str = $(2) ;
2366   local res = ;
2367   local f ;
2368   local oo ;
2369   #Echo "removing " $(oname) " from " $(str) ;
2370   for f in $(str) {
2371     if ! $(f) in $(oname) {
2372       res += $(f) ;
2373     }
2374   }
2375   return $(res) ;
2379 # VAR = [ RemoveOpt regexp-options-to-remove : options-list ] ;
2380 # remove options from list with egrep-like regexps
2381 rule RemoveOptWild {
2382   local oname = $(1) ;
2383   local str = $(2) ;
2384   local res = ;
2385   local f ;
2386   local t ;
2387   #Echo "removing " $(oname) " from " $(str) ;
2388   for f in $(str) {
2389     t = [ Match $(oname) : $(f) ] ;
2390     #Echo $(f) ": " $(t) ;
2391     if $(t[1]) = "" {
2392       #Echo "include: " $(f) ;
2393       res += $(f) ;
2394     }
2395   }
2396   return $(res) ;
2400 # profile "name" ;
2401 # set compile flags for profile; works only for gcc/g++
2402 # available profiles:
2403 #  none, default: don't change
2404 #  empty: remove optimisation flags
2405 #  speed: optimise for speed and pIII
2406 #  size: optimise for size
2407 #  debug: don't optimize, add debug info
2408 #  standard: -O2
2409 rule profile {
2410   local orm = "(^\\-march\\=)" "(^\\-mtune\\=)" "(^\\-mfpmath\\=)" "(^\\-O.$)" ;
2411   local ormff = "(^\\-f[^n][^o])" ;
2412   local t ;
2414   local isGCC = "ona" ;
2415   local isG++ = "ona" ;
2416   if ( "gcc" in $(CC) ) || ( $(JAM_TOOLSET) = MINGW ) { isGCC = "tan" ; }
2417   if ( "g++" in $(C++) ) || ( $(JAM_TOOLSET) = MINGW ) { isG++ = "tan" ; }
2418   if $(JAM_FORCE_GCC_OPTIONS) { isGCC = "tan" ; isG++ = "tan" ; }
2420   if $(isGCC) = "tan" { OPTIM = [ RemoveOptWild $(orm) $(ormff) : $(OPTIM) ] ; }
2421   if $(isG++) = "tan" { C++OPTIM = [ RemoveOptWild $(orm) $(ormff) : $(C++OPTIM) ] ; }
2422   OBJCOPTIM = [ RemoveOptWild $(orm) $(ormff) : $(OBJCOPTIM) ] ;
2423   if ( "gcc" in $(LINK) ) || ( $(JAM_FORCE_GCC_OPTIONS) ) { LINKFLAGS = [ RemoveOpt "-g" "-s" : $(LINKFLAGS) ] ; }
2424   if $(isG++) = "tan" { C++LINKFLAGS = [ RemoveOpt "-g" "-s" : $(C++LINKFLAGS) ] ; }
2425   OBJCLINKFLAGS = [ RemoveOpt "-g" "-s" : $(OBJCLINKFLAGS) ] ;
2427   switch $(1) {
2428     case "none" :
2429       Echo "MSG: default profile" ;
2430       OPT_PROFILE = ;
2431     case "default" :
2432       Echo "MSG: default profile" ;
2433       OPT_PROFILE = "default" ;
2434     case "empty" :
2435       Echo "MSG: removing default optimization flags" ;
2436       LINKFLAGS += -s ;
2437       if $(isG++) = "tan" { C++LINKFLAGS += -s ; }
2438       OBJCLINKFLAGS += -s ;
2439       SLACK_PKG_ARCH = "i486" ;
2440       OPT_PROFILE = "empty" ;
2441     case "speed" :
2442       SetCPUFlags ;
2443       Echo "MSG: optimizing for speed; CPU: $(DETECTED_CPU)" ;
2444       if $(isGCC) = "tan" { OPTIM += $(OPTIM_SPEED) ; }
2445       if $(isG++) = "tan" { C++OPTIM += $(OPTIM_SPEED) ; }
2446       OBJCOPTIM += $(OPTIM_SPEED) ;
2447       if $(isGCC) = "tan" { LINKFLAGS += $(LINKFLAGS_SPEED) ; }
2448       if $(isG++) = "tan" { C++LINKFLAGS += $(LINKFLAGS_SPEED) ; }
2449       OBJCLINKFLAGS += $(LINKFLAGS_SPEED) ;
2450       SLACK_PKG_ARCH = "i686" ;
2451       OPT_PROFILE = "speed" ;
2452     case "size" :
2453       Echo "MSG: optimizing for size" ;
2454       if $(isGCC) = "tan" { OPTIM += $(OPTIM_SIZE) ; }
2455       if $(isG++) = "tan" { C++OPTIM += $(OPTIM_SIZE) ; }
2456       OBJCOPTIM += $(OPTIM_SIZE) ;
2457       if $(isGCC) = "tan" { LINKFLAGS += $(LINKFLAGS_SIZE) ; }
2458       if $(isG++) = "tan" { C++LINKFLAGS += $(LINKFLAGS_SIZE) ; }
2459       OBJCLINKFLAGS += $(LINKFLAGS_SIZE) ;
2460       SLACK_PKG_ARCH = "i686" ;
2461       OPT_PROFILE = "size" ;
2462     case "debug" :
2463       Echo "MSG: debug build" ;
2464       if $(isGCC) = "tan" { OPTIM += $(OPTIM_DEBUG) ; }
2465       if $(isG++) = "tan" { C++OPTIM += $(OPTIM_DEBUG) ; }
2466       OBJCOPTIM += $(OPTIM_DEBUG) ;
2467       if $(isGCC) = "tan" { LINKFLAGS += $(LINKFLAGS_DEBUG) ; }
2468       if $(isG++) = "tan" { C++LINKFLAGS += $(LINKFLAGS_DEBUG) ; }
2469       OBJCLINKFLAGS += $(LINKFLAGS_DEBUG) ;
2470       SLACK_PKG_ARCH = "i486" ;
2471       OPT_PROFILE = "debug" ;
2472     case "standard" :
2473       Echo "MSG: standard build" ;
2474       if $(isGCC) = "tan" { OPTIM += -O2 ; }
2475       if $(isG++) = "tan" { C++OPTIM += -O2 ; }
2476       OBJCOPTIM += -O2 ;
2477       if $(isGCC) = "tan" { LINKFLAGS += -s ; }
2478       if $(isG++) = "tan" { C++LINKFLAGS += -s ; }
2479       OBJCLINKFLAGS += -s ;
2480       SLACK_PKG_ARCH = "i486" ;
2481       OPT_PROFILE = "standard" ;
2482     case "*" :
2483       Exit "unknown profile; possible values are: default; empty; speed; size; debug; standard" ;
2484   }
2486 SLACK_PKG_ARCH ?= "i486" ;
2489 # selects 'debug', 'standard', 'speed' or 'size' profile according to vars:
2490 #  DEBUG = 1 : debug
2491 #  OPT_SIZE = 1 : size
2492 #  OPT_SPEED = 1 : speed
2493 #  default: standard
2494 rule set-profile {
2495   if $(DEBUG) {
2496     profile "debug" ;
2497   } else if $(OPT_SIZE) {
2498     profile "size" ;
2499   } else if $(OPT_SPEED) {
2500     profile "speed" ;
2501   } else {
2502     profile "standard" ;
2503   }
2507 # set default 'locate' vars -- _build/, etc
2508 rule set-default-subdir-locates {
2509   ALL_LOCATE_BIN = $(TOP) ;
2510   ALL_LOCATE_LIBSO = $(TOP) ;
2511   if $(WINDOZE) {
2512     ALL_LOCATE_TARGET = $(TOP)$(PATH_SEPARATOR)_wbuild ;
2513     ALL_LOCATE_LIB = $(TOP)$(PATH_SEPARATOR)_wbuild$(PATH_SEPARATOR)lib ;
2514   } else {
2515     ALL_LOCATE_TARGET = $(TOP)$(PATH_SEPARATOR)_build ;
2516     ALL_LOCATE_LIB = $(TOP)$(PATH_SEPARATOR)_build$(PATH_SEPARATOR)lib ;
2517   }
2521 rule set-default-target-locations {
2522   set-default-subdir-locates ;
2526 # ObjectNoAliasing filelist ;
2527 # turn off aliasing optimization for specified files
2528 # works only for gcc/g++
2529 rule ObjectNoAliasing {
2530   local isGCC = "ona" ;
2531   local isG++ = "ona" ;
2532   if ( "gcc" in $(CC) ) || ( $(JAM_TOOLSET) = MINGW ) { isGCC = "tan" ; }
2533   if ( "g++" in $(C++) ) || ( $(JAM_TOOLSET) = MINGW ) { isG++ = "tan" ; }
2534   if $(JAM_FORCE_GCC_OPTIONS) { isGCC = "tan" ; isG++ = "tan" ; }
2536   if $(isGCC) = "tan" { CCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(OPTIM_NOALIAS) ; }
2537   if $(isG++) = "tan" { C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(OPTIM_NOALIAS) ; }
2538   OBJCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(OPTIM_NOALIAS) ;
2542 # call $(1)
2543 # add output to var $(2)
2544 # return resulting (non-empty) string if library is present
2545 # if $(2) = "" -- don't add flags, just return
2546 # [ lib-config-ex "pkg-config sdl -cflags" : "CFLAGS" ]
2547 rule lib-config-ex {
2548   local cf lf res ;
2549   cf = [ Command "$(1) 2>/dev/null" : parse-output exit-code code-first ] ;
2550   if $(cf[1]) = "0" && $(cf[2]) {
2551     res = $(cf[2-]) ;
2552     if $(2) {
2553       $(2) += $(cf[2-]) ;
2554     }
2555   } else {
2556     res = ;
2557   }
2558   return $(res) ;
2562 # call $(1) --cflags and $(1) --libs (many libs provides such configurators)
2563 # add necessary flags to compiler and linker vars
2564 # return "tan" (non-empty string) if library is present
2565 # if $(2) != "" -- don't add flags, just check
2566 # [ lib-config "pkg-config sdl" ]
2567 rule lib-config {
2568   local cf lf hasit ;
2570   cf = [ Command "$(1) --cflags 2>/dev/null" : parse-output exit-code code-first ] ;
2571   #Echo "cf:" $(cf) ;
2572   if $(cf[1]) = "0" && $(cf[2]) {
2573     hasit = "tan" ;
2574     #Echo "flags:" $(cf[2-]) ;
2575     if ! $(2) {
2576       CCFLAGS += $(cf[2-]) ;
2577       C++FLAGS += $(cf[2-]) ;
2578       OBJCFLAGS += $(cf[2-]) ;
2579     }
2580   }
2582   lf = [ Command "$(1) --libs 2>/dev/null" : parse-output exit-code code-first ] ;
2583   #Echo "lf:" $(lf) ;
2584   if $(lf[1]) = "0" && $(lf[2]) {
2585     hasit = "tan" ;
2586     #Echo "flags:" $(lf[2-]) ;
2587     if ! $(2) {
2588       LINKFLAGS += $(lf[2-]) ;
2589       C++LINKFLAGS += $(lf[2-]) ;
2590       OBJCLINKFLAGS += $(lf[2-]) ;
2591     }
2592   }
2594   return $(hasit) ;
2597 rule pkg-config {
2598   local res ;
2599   res = [ lib-config "pkg-config $(1)" ] ;
2600   return res ;
2605 # Objective C vars
2608 OBJC_GNUSTEP_BASE_LIB = gnustep-base ;
2609 OBJC_GNUSTEP_GUI_LIB = gnustep-gui ;
2612 # Objective C rules
2614 rule ObjCUseGNUstepBase {
2615   if ! $(K8_INTERNAL_GNUSTEP_BASE) {
2616     #Echo "-l$(OBJC_GNUSTEP_BASE_LIB)" ;
2617     OBJCLINKLIBS += "-l$(OBJC_GNUSTEP_BASE_LIB)" ;
2618     K8_INTERNAL_GNUSTEP_BASE = tan ;
2619   }
2622 rule ObjCUseGNUstepGui {
2623   ObjCUseGNUstepBase ;
2624   if ! $(K8_INTERNAL_GNUSTEP_GUI) {
2625     K8_INTERNAL_GNUSTEP_GUI = tan ;
2626     #Echo "-l$(OBJC_GNUSTEP_GUI_LIB)" ;
2627     OBJCLINKLIBS += "-l$(OBJC_GNUSTEP_GUI_LIB)" ;
2628   }
2631 rule ObjCUseGNUstep {
2632   ObjCUseGNUstepBase ;
2633   ObjCUseGNUstepGui ;
2638 # Now include the user's Jamfile.
2640 include $(JAMFILE) ;