xxxC++ renamed to C++xxx; added *LOCATE_LIB[SO]
[k8jam.git] / Jambase
blob37409b6b742e918c2918dec54784eb36b86cce9b
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 this 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
56 # Special targets defined in this file:
58 # all       - parent of first, shell, files, lib, exe
59 # first     - first dependent of 'all', for potential initialization
60 # shell     - parent of all Shell targets
61 # files     - parent of all File targets
62 # lib       - parent of all Library targets
63 # exe       - parent of all Main targets
64 # dirs      - parent of all MkDir targets
65 # clean     - removes all Shell, File, Library, and Main targets
66 # uninstall - removes all Install targets
69 # Rules defined by this file:
71 # as obj.o : source.s ;                 .s -> .o
72 # Bulk dir : files ;                    populate directory with many files
73 # Cc obj.o : source.c ;                 .c -> .o
74 # C++ obj.o : source.cc ;               .cc -> .o
75 # Clean clean : sources ;               remove sources with 'jam clean'
76 # File dest : source ;                  copy file
77 # GenFile source.c : program args ;     make custom file
78 # HardLink target : source ;            make link from source to target
79 # HdrRule source : headers ;            handle #includes
80 # InstallInto dir : sources ;           install any files
81 # InstallBin dir : sources ;            install binaries
82 # InstallLib dir : sources ;            install files
83 # InstallFile dir : sources ;           install files
84 # InstallMan dir : sources ;            install man pages
85 # InstallShell dir : sources ;          install shell scripts
86 # Lex source.c : source.l ;             .l -> .c
87 # Library lib : source ;                archive library from compiled sources
88 # LibraryFromObjects lib : objects ;    archive library from objects
89 # LinkLibraries images : libraries ;    bag libraries onto Mains
90 # Main image : source ;                 link executable from compiled sources
91 # MainC++ image : source ;              link c++ executable from compiled sources
92 # MainFromObjects image : objects ;     link executable from objects
93 # MainC++FromObjects image : objects ;  link c++ executable from objects
94 # MkDir dir ;                           make a directory, if not there
95 # Object object : source ;              compile object from source
96 # ObjectCcFlags source : flags ;        add compiler flags for object
97 # ObjectC++Flags source : flags ;       add compiler flags for object
98 # ObjectHdrs source : dirs ;            add include directories for object
99 # Objects sources ;                     compile sources
100 # RmTemps target : sources ;            remove temp sources after target made
101 # Setuid images ;                       mark executables Setuid
102 # SoftLink target : source ;            make symlink from source to target
103 # SubDir TOP d1 d2 ... ;                start a subdirectory Jamfile
104 # SubDirCcFlags flags ;                 add compiler flags until next SubDir
105 # SubDirC++Flags flags ;                add compiler flags until next SubDir
106 # SubDirHdrs d1 d2 ... ;                add include dir until next SubDir
107 # SubInclude TOP d1 d2 ... ;            include a subdirectory Jamfile
108 # Shell exe : source ;                  make a shell executable
109 # Undefines images : symbols ;          save undef's for linking
110 # UserObject object : source ;          handle unknown suffixes for Object
111 # Yacc source.c : source.y ;            .y -> .c
113 # Utility rules that have no side effects (not supported):
115 # FAppendSuffix f1 f2 ... : $(SUF) ;    return $(<) with suffixes
116 # FDirName d1 d2 ... ;                  return path from root to dir
117 # FGrist d1 d2 ... ;                    return d1!d2!...
118 # FGristFiles value ;                   return $(value:G=$(SOURCE_GRIST))
119 # FGristSourceFiles value ;             return $(value:G=$(SOURCE_GRIST))
120 # FStripCommon v1 : v2 ;                strip common initial parts of v1 v2
121 # FReverse a1 a2 ... ;                  return ... a2 a1
122 # FRelPath d1 : d2 ;                    return rel path from d1 to d2
123 # FSubDir d1 d2 ... ;                   return path to root
127 # Brief review of the jam language:
129 # Statements:
130 #   rule RULE - statements to process a rule
131 #   actions RULE - system commands to carry out target update
133 # Modifiers on actions:
134 #   together - multiple instances of same rule on target get executed
135 #          once with their sources ($(>)) concatenated
136 #   updated - refers to updated sources ($(>)) only
137 #   ignore - ignore return status of command
138 #   quietly - don't trace its execution unless verbose
139 #   piecemeal - iterate command each time with a small subset of $(>)
140 #   existing - refers to currently existing sources ($(>)) only
141 #   bind vars - subject to binding before expanding in actions
143 # Special rules:
144 #   Always - always build a target
145 #   Depends - builds the dependency graph
146 #   Echo - blurt out targets on stdout
147 #   Exit - blurt out targets and exit
148 #   Includes - marks sources as headers for target (a codependency)
149 #   NoCare - don't panic if the target can't be built
150 #   NoUpdate - create the target if needed but never update it
151 #   NotFile - ignore the timestamp of the target (it's not a file)
152 #   Temporary - target need not be present if sources haven't changed
154 # Special variables set by jam:
155 #   $(<) - targets of a rule (to the left of the :)
156 #   $(>) - sources of a rule (to the right of the :)
157 #   $(xxx) - true on xxx (UNIX, VMS, NT, OS2, MAC)
158 #   $(OS) - name of OS - varies wildly
159 #   $(JAMVERSION) - version number (2.5)
161 # Special variables used by jam:
162 #   SEARCH - where to find something (used during binding and actions)
163 #   LOCATE - where to plop something not found with SEARCH
164 #   HDRRULE - rule to call to handle include files
165 #   HDRSCAN - egrep regex to extract include files
167 # Special targets:
168 #   all - default if none given on command line
171 # for perforce use -- jambase version
173 JAMBASEDATE = 2004.10.07 ;
175 THIS_IS_KJAM = "tan" ; # we are using kjam
176 THIS_IS_K8JAM = "tan" ; # we are using kjam
178 # set to 'tan' for old 'libtool' behavior
179 K8_USE_LIBTOOL = ;
182 # Initialize variables
185 ###############################################################################
186 # special values
187 ###############################################################################
189 OPTIM_SPEED = -O3 -march=pentium3 -mtune=pentium3 -mfpmath=sse ;
190 #OPTIM_SPEED = -O3 -march=prescott -mtune=prescott -mfpmath=sse ;
191 LINKFLAGS_SPEED = -s ;
193 OPTIM_SIZE = -Os -march=i586 ;
194 LINKFLAGS_SIZE = -s ;
196 OPTIM_DEBUG = -O0 -g ;
197 LINKFLAGS_DEBUG = -g ;
199 OPTIM_NOALIAS = -fno-strict-aliasing ;
203 # OS specific variable settings
206 ###############################################################################
207 # Windoze
208 ###############################################################################
209 if $(NT) {
210   PATH_SEPARATOR = "\\" ;
211   local SUPPORTED_TOOLSETS =
212     MINGW
213     LCC
214     PELLESC
215   ;
217   # if the JAM_TOOLSET environment variable is defined, check that it is
218   # one of our supported values
219   #
220   if $(JAM_TOOLSET) {
221     if ! $(JAM_TOOLSET) in $(SUPPORTED_TOOLSETS) {
222       Echo "The JAM_TOOLSET environment variable is defined but its value" ;
223       Echo "is invalid, please use one of the following:" ;
224       Echo ;
225       for t in $(SUPPORTED_TOOLSETS) { Echo "  " $(t) ; }
226       Exit ;
227     }
228   }
230   if ! $(JAM_TOOLSET) {
231     Echo "The JAM_TOOLSET environment variable is not defined, defaults to MINGW" ;
232     JAM_TOOLSET = MINGW ;
233     MINGW = "c:\\mingw\\" ;
234   }
236   # if JAM_TOOLSET is empty, we'll try to detect the toolset from other
237   # environment variables to remain backwards compatible with Jam 2.5
238   #
239   if ! $(JAM_TOOLSET) {
240     if $(MSVC) {
241       JAM_TOOLSET = VISUALC ;
242       VISUALC     = $(MSVC) ;
243       MSVCNT      = $(MSVC) ;
244     } else if $(MSVCNT) {
245       JAM_TOOLSET = VISUALC ;
246       VISUALC     = $(MSVCNT) ;
247     } else if $(MINGW) {
248       # MINGW is defined when trying to compile FT-Jam with
249       # classic Jam
250       #
251       JAM_TOOLSET = MINGW ;
252     } else {
253       Echo "Jam cannot be run because you didn't indicate which compilation toolset" ;
254       Echo "to use. To do so, define the JAM_TOOLSET environment variable with" ;
255       Echo "one of the following values:" ;
256       Echo ;
257       Echo "  Value       Toolset Description" ;
258       Echo ;
259       Echo "  MINGW        MinGW (gcc)" ;
260       Echo "  LCC          Win32-LCC" ;
261       Echo "  PELLESC      Pelles C" ;
262       Echo ;
263       Echo "The corresponding compiler must be in your path" ;
264       Echo ;
265       Echo "  e.g.:  set JAM_TOOLSET=MINGW" ;
266       Exit ;
267     }
268   }
270   MV        ?= move /y ;
271   CP        ?= copy ;
272   RM        ?= del /f/q ;
273   RMDIR     ?= rmdir /s/q ;
274   SLASH     ?= \\ ;
275   SUFLIB    ?= .lib ;
276   SUFOBJ    ?= .obj ;
277   SUFEXE    ?= .exe ;
278   SUFLIBSHR ?= .dll ;
280   if $(JAM_TOOLSET) = MINGW {
281     Echo "Compiler is GCC with MinGW" ;
282     AR           ?= ar -ru ;
283     RANLIB       ?= ranlib ;
284     CC           ?= mingw-gcc ;
285     CCFLAGS      ?= "" ;
286     C++          ?= mingw-g++ ;
287     C++FLAGS     ?= $(CCFLAGS) ;
288     LINK         ?= $(CC) ;
289     LINKFLAGS    ?= "" ;
290     LINKLIBS     ?= -lkernel32 ;
291     OPTIM        ?= ;
292     SUFOBJ        = .o ;
293     SUFLIB        = .a ;
294     SLASH         = / ;
295     # MinGW-specific thingy
296     MINGW_GUI     = "-Wl,-subsystem,windows" ;
297     MINGW_THREADS = "-mthreads" ;
298     # k8
299     C++OPTIM     ?= $(OPTIM) ;
300     C++LINK      ?= $(C++) ;
301     C++LINKFLAGS ?= $(LINKFLAGS) ;
302     C++LINKLIBS  ?= $(LINKLIBS) ;
303     #NOARSCAN     ?= true ;
304     # set path if any
305     if $(MINGW) {
306       CC = "$(MINGW)$(CC:J= )" ;
307       C++ = "$(MINGW)$(C++:J= )" ;
308       LINK = "$(MINGW)$(LINK:J= )" ;
309       C++LINK = "$(MINGW)$(C++LINK:J= )" ;
310       AR = "$(MINGW)$(AR:J= )" ;
311       RANLIB = "$(MINGW)$(RANLIB:J= )" ;
312     }
313   } else if $(JAM_TOOLSET) = LCC {
314     Echo "Compiler is Win32-LCC" ;
315     AR        ?= lcclib ;
316     CC        ?= lcc ;
317     CCFLAGS   ?= "" ;
318     C++       ?= "error" ;
319     LINK      ?= lcclnk ;
320     LINKFLAGS ?= "" ;
321     LINKLIBS  ?= "" ;
322     OPTIM     ?= ;
323     NOARSCAN   = true ;
324     # k8
325     C++LINK    = "error" ;
326   } else if $(JAM_TOOLSET) = PELLESC {
327     Echo "Compiler is PellesC" ;
328     AR        ?= polib ;
329     CC        ?= pocc ;
330     CCFLAGS   ?= "" ;
331     C++       ?= "error" ;
332     LINK      ?= polink ;
333     LINKFLAGS ?= ;
334     LINKLIBS  ?= ;
335     OPTIM     ?= ;
336     NOARSCAN   = true ;
337     LINKLIBS  ?= crt.lib oldnames.lib Win\\kernel32.lib ;
338     # k8
339     C++LINK    = "error" ;
340   } else {
341     # XXX: We need better comments here !!
342     Exit "On NT, set MINGW to the root of the MinGW dir (but it won't help you anyway)" ;
343   }
344   STDHRS ?= "" ;
346 ###############################################################################
347 # UNIX
348 ###############################################################################
349 else if $(UNIX) {
350   PATH_SEPARATOR = "/" ;
351   switch $(OS) {
352     case CYGWIN :
353       CC           ?= gcc ;
354       CCFLAGS      += -D__cygwin__ ;
355       LEX          ?= flex ;
356       JAMSHELL     ?= sh -c ;
357       RANLIB       ?= "" ;
358       SUFEXE       ?= .exe ;
359       YACC         ?= bison -y ;
360     }
362     # UNIX defaults
364     CC        ?= gcc ;
365     C++       ?= g++ ;
366     CCFLAGS   ?= ;
367     C++FLAGS  ?= $(CCFLAGS) ;
368     CHMOD     ?= chmod ;
369     CHGRP     ?= chgrp ;
370     CHOWN     ?= chown ;
371     LEX       ?= lex ;
372     LINKFLAGS ?= $(CCFLAGS) ;
373     LINKLIBS  ?= ;
374     OPTIM     ?= ;
375     RANLIB    ?= ranlib ;
376     YACC      ?= yacc ;
377     YACCGEN   ?= .c ;
378     YACCFILES ?= y.tab ;
379     YACCFLAGS ?= -d ;
381     if $(K8_USE_LIBTOOL) {
382       SUFOBJSHR ?= .lo ;
383       SUFLIBSHR ?= .la ;
384     } else {
385       SUFOBJSHR ?= .o ;
386       SUFLIBSHR ?= .so ;
387     }
388     PICFLAGS  ?= -fpic ;
389     STDHDRS   ?= /usr/include ;
392 # shared library object file suffix. We assume that it is identical
393 # than the normal one
394 SUFOBJSHR ?= $(SUFOBJ) ;
395 SUFLIBSHR ?= $(SUFLIB) ;
398 # the D compiler
399 DC ?= dmd ;
402 # General defaults; a lot like UNIX
404 PATH_SEPARATOR ?= "/" ;
405 AR          ?= ar ru ;
406 AS          ?= as ;
407 ASFLAGS     ?= ;
408 AWK         ?= awk ;
409 BINDIR      ?= /usr/local/bin ;
410 C++         ?= g++ ;  # k8: was cc
411 C++FLAGS    ?= ;
412 CC          ?= gcc ;  # k8: was cc
413 CCFLAGS     ?= ;
414 CP          ?= cp -f ;
415 CRELIB      ?= ;
416 DOT         ?= . ;
417 DOTDOT      ?= .. ;
418 EXEMODE     ?= 755 ;
419 FILEMODE    ?= 644 ;
420 HDRS        ?= ;
421 INSTALLGRIST    ?= installed ;
422 JAMFILE     ?= Jamfile ;
423 JAMRULES    ?= Jamrules ;
424 LEX         ?= ;
425 LIBDIR      ?= /usr/local/lib ;
426 LINK        ?= $(CC) ;
427 LINKFLAGS   ?= ;
428 LINKLIBS    ?= ;
429 LN          ?= ln ;
430 MANDIR      ?= /usr/local/man ;
431 MKDIR       ?= mkdir ;
432 MV          ?= mv -f ;
433 OPTIM       ?= ;
434 RCP         ?= rcp ;
435 RM          ?= rm -f ;
436 RMDIR       ?= $(RM) ;
437 RSH         ?= rsh ;
438 SED         ?= sed ;
439 SHELLHEADER ?= "#!/bin/sh" ;
440 SHELLMODE   ?= 755 ;
441 SLASH       ?= / ;
442 SUBDIRRULES ?= ;
443 SUBDIRRESET ?= ASFLAGS HDRS C++FLAGS CCFLAGS ;
444 SUFEXE      ?= "" ;
445 SUFLIB      ?= .a ;
446 SUFOBJ      ?= .o ;
447 UNDEFFLAG   ?= "-u _" ;
448 YACC        ?= ;
449 YACCGEN     ?= ;
450 YACCFILES   ?= ;
451 YACCFLAGS   ?= ;
453 HDRPATTERN = "^[        ]*#[    ]*include[      ]*[<\"]([^\">]*)[\">].*$" ;
455 OSFULL = $(OS)$(OSVER)$(OSPLAT) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ;
457 # k8
458 C++OPTIM     ?= $(OPTIM) ;
459 C++LINK      ?= $(C++) ;
460 C++LINKFLAGS ?= $(LINKFLAGS) ;
461 C++LINKLIBS  ?= $(LINKLIBS) ;
463 if $(OS) = "LINUX" {
464   if ( "gcc" in $(CC) ) && ! ( "-pipe" in $(CC) ) { CC += -pipe ; }
465   if ( "g++" in $(C++) ) && ! ( "-pipe" in $(C++) ) { C++ += -pipe ; }
468 #Echo "OS:" $(OS) ;
469 #Echo "OSFULL:" $(OSFULL) ;
470 #Echo "UNIX:" $(UNIX) ;
475 # Base dependencies - first for "bootstrap" kinds of rules
477 Depends all : shell files lib exe obj ;
478 Depends all shell files lib exe obj : first ;
479 NotFile all first shell files lib exe obj dirs clean uninstall ;
480 Always  clean uninstall ;
483 # Rules
486 # /As object : source ;
488 # Assemble the file _source_, called by the @Object rule.
490 # Do not call this rule directly, since _object_ and _source_ may have
491 # have platform-specific file extensions
493 rule As {
494   Depends $(<) : $(>) ;
495   ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
496   ASHDRS on $(<) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
499 # /Bulk  directory : sources ;
501 # Copies _sources_ into _directory_
503 rule Bulk {
504   local i ;
506   for i in $(>) {
507     File $(i:D=$(<)) : $(i) ;
508   }
512 # /Dc object : source ;
514 # Compile the file source into object, usin the D compiler $(DC), its
515 # flags $(DCFLAGS) and $(DOPTIM)
516 # Called by the @Object rule
518 # Do not call this rule directly, since _object_ and _source_ may have
519 # have platform-specific file extensions
521 rule Dc {
522   Depends $(<) : $(>) ;
523   # Just to clarify here: this sets the per-target DCFLAGS to
524   # be the current value of (global) DCFLAGS and SUBDIRDCFLAGS.
525   DCFLAGS on $(<) += $(DCFLAGS) $(SUBDIRDCFLAGS) ;
529 # /Cc object : source ;
531 # Compile the file source into object, using the C compiler $(CC), its
532 # flags $(CCFLAGS) and $(OPTIM), and the header file directories $(HDRS).
533 # Called by the @Object rule
535 # Do not call this rule directly, since _object_ and _source_ may have
536 # have platform-specific file extensions
538 rule Cc {
539   Depends $(<) : $(>) ;
541   # If the compiler's -o flag doesn't work, relocate the .o
542   if $(RELOCATE) { CcMv $(<) : $(>) ; }
544   # Just to clarify here: this sets the per-target CCFLAGS to
545   # be the current value of (global) CCFLAGS and SUBDIRCCFLAGS.
546   # CCHDRS and CCDEFS must be reformatted each time for some
547   # compiles (VMS, NT) that malign multiple -D or -I flags.
548   CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) ;
549   CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
550   CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
554 # /C++ object : source ;
556 # Compile the C++ source file _source_. Similar to @CC, called by @Object
558 # Do not call this rule directly, since _object_ and _source_ may have
559 # have platform-specific file extensions
561 rule C++ {
562   local ktmp ;
564   Depends $(<) : $(>) ;
566   if $(RELOCATE) { CcMv $(<) : $(>) ; }
568   # Just to clarify here: this sets the per-target CCFLAGS to
569   # be the current value of (global) CCFLAGS and SUBDIRCCFLAGS.
570   # CCHDRS and CCDEFS must be reformatted each time for some
571   # compiles (VMS, NT) that malign multiple -D or -I flags.
572   ktmp = $(C++FLAGS) ;
573   if ! $(ktmp) { ktmp = $(CCFLAGS) ; }
574   C++FLAGS on $(<) += $(ktmp) $(SUBDIRC++FLAGS) ;
576   ktmp = $(C++OPTIM) ;
577   if ! $(ktmp) { ktmp = $(OPTIM) ; }
578   C++OPTIM on $(<) += $(ktmp) ;
580   CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
581   CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
585 # /Chmod target ;
587 # (Unix and VMS only). Change file permissions on _target_ to target-specific
588 # $(MODE) value set by @Link, @File, @Install* and @Shell rules
590 rule Chmod {
591   if $(CHMOD) { Chmod1 $(<) ; }
594 # /Clean  clean : targets ;
596 # Removes existing _targets_ when _clean_ is built. clean is not a dependency
597 # of all, and must be built explicitely for targets to be removed
601 # /File target : source ;
603 # Copies _source_ into _target_
605 rule File {
606   Depends files : $(<) ;
607   Depends $(<) : $(>) ;
608   SEARCH on $(>) = $(SEARCH_SOURCE) ;
609   MODE on $(<) = $(FILEMODE) ;
610   Chmod $(<) ;
614 # /GenFile target : image sources ;
616 # Runs the command "_image_ _target_ _sources_" to create _target_ from
617 # _sources_ and _image_ (where _image_ is an executable built by the
618 # @Main rule)
620 rule GenFile {
621   local _t = [ FGristSourceFiles $(<) ] ;
622   local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;
623   Depends $(_t) : $(_s) $(>[2-]) ;
624   GenFile1 $(_t) : $(_s) $(>[2-]) ;
625   Clean clean : $(_t) ;
628 rule GenFile1 {
629   MakeLocate $(<) : $(LOCATE_SOURCE) ;
630   SEARCH on $(>) = $(SEARCH_SOURCE) ;
634 # /HardLink target : source ;
636 # Makes _target_ a hard link to _source_, if it isn't one already
637 # (Unix only)
639 rule HardLink {
640   Depends files : $(<) ;
641   Depends $(<) : $(>) ;
642   SEARCH on $(>) = $(SEARCH_SOURCE) ;
646 # /HdrMacroFile
648 # this rule is specific to FT-Jam. It is used to indicate that a given file
649 # contains definitions for filename macros (e.g. "#define MYFILE_H <myfile>.h")
650 # that can later be used in #include statements in the rest of the source
652 # these files must be parsed before any make is tried.
654 rule HdrMacroFile {
655   HDRMACRO $(<) ;
659 # /HdrRule source : headers ;
661 # Arranges the proper dependencies when the file _source_ includes the files
662 # _headers_ through the #include C preprocessor directive
664 # this rule is not intendend to be called explicitely. It is called
665 # automatically during header scanning on sources handled by the @Object
666 # rule (e.g. sources in @Main or @Library rules)
668 rule HdrRule {
669   # HdrRule source : headers ;
671   # N.B.  This rule is called during binding, potentially after
672   # the fate of many targets has been determined, and must be
673   # used with caution: don't add dependencies to unrelated
674   # targets, and don't set variables on $(<).
676   # Tell Jam that anything depending on $(<) also depends on $(>),
677   # set SEARCH so Jam can find the headers, but then say we don't
678   # care if we can't actually find the headers (they may have been
679   # within ifdefs),
681   local s = $(>:G=$(HDRGRIST:E)) ;
683   Includes $(<) : $(s) ;
684   SEARCH on $(s) = $(HDRSEARCH) ;
685   NoCare $(s) ;
687   # Propagate on $(<) to $(>)
689   HDRSEARCH on $(s) = $(HDRSEARCH) ;
690   HDRSCAN on $(s) = $(HDRSCAN) ;
691   HDRRULE on $(s) = $(HDRRULE) ;
692   HDRGRIST on $(s) = $(HDRGRIST) ;
696 rule InstallInto {
697   # InstallInto dir : sources ;
699   local i t ;
701   t = $(>:G=$(INSTALLGRIST)) ;
703   # Arrange for jam install
704   # Arrange for jam uninstall
705   # sources are in SEARCH_SOURCE
706   # targets are in dir
708   Depends install : $(t) ;
709   Clean uninstall : $(t) ;
710   SEARCH on $(>) = $(SEARCH_SOURCE) ;
711   MakeLocate $(t) : $(<) ;
713   # For each source, make gristed target name
714   # and Install, Chmod, Chown, and Chgrp
715   for i in $(>) {
716     local tt = $(i:G=$(INSTALLGRIST)) ;
718     Depends $(tt) : $(i) ;
719     Install $(tt) : $(i) ;
720     Chmod $(tt) ;
722     if $(OWNER) && $(CHOWN) {
723       Chown $(tt) ;
724       OWNER on $(tt) = $(OWNER) ;
725     }
726     if $(GROUP) && $(CHGRP) {
727       Chgrp $(tt) ;
728       GROUP on $(tt) = $(GROUP) ;
729     }
730   }
734 # /InstallBin dir : sources ;
736 # Copy _sources_ into _dir_ with mode $(EXEMODE)
738 rule InstallBin {
739   local _t = [ FAppendSuffix $(>) : $(SUFEXE) ] ;
741   InstallInto $(<) : $(_t) ;
742   MODE on $(_t:G=$(INSTALLGRIST)) = $(EXEMODE) ;
746 # /InstallFile dir : sources ;
748 # Copy _sources_ into _dir_ with mode $(FILEMODE)
750 rule InstallFile {
751   InstallInto $(<) : $(>) ;
752   MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
756 # /InstallLib dir : sources ;
758 # Copy _sources_ into _dir_ with mode $(FILEMODE)
760 rule InstallLib {
761   InstallInto $(<) : $(>) ;
762   MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
766 # /InstallMan dir : sources ;
768 #  Copy _sources_ into the appropriate subdirectory of _dir_ with mode
769 #  $(FILEMODE). The subdirectory is manS, where S is the suffix of each of
770 #  sources.
772 rule InstallMan {
773   # Really this just strips the . from the suffix
774   local i s d ;
776   for i in $(>) {
777     switch $(i:S) {
778       case .1 : s = 1 ; case .2 : s = 2 ; case .3 : s = 3 ;
779       case .4 : s = 4 ; case .5 : s = 5 ; case .6 : s = 6 ;
780       case .7 : s = 7 ; case .8 : s = 8 ; case .l : s = l ;
781       case .n : s = n ; case .man : s = 1 ;
782     }
783     d = man$(s) ;
784     InstallInto $(d:R=$(<)) : $(i) ;
785   }
786   MODE on $(>:G=$(INSTALLGRIST)) = $(FILEMODE) ;
790 # /InstallShell dir : sources ;
792 # Copy _sources_ into _dir_ with mode $(SHELLMODE)
794 rule InstallShell {
795   InstallInto $(<) : $(>) ;
796   MODE on $(>:G=$(INSTALLGRIST)) = $(SHELLMODE) ;
800 # /Lex source.c : source.l ;
802 # Process the lex source file _source.l_ and rename the lex.yy.c
803 # to _source.c_ . Called by the @Object rule
805 rule Lex {
806   LexMv $(<) : $(>) ;
807   Depends $(<) : $(>) ;
808   MakeLocate $(<) : $(LOCATE_SOURCE) ;
809   Clean clean : $(<) ;
813 # /Library  library : sources ;
815 #  Compiles _sources_ and archives them into _library_. The intermediate
816 #  objects are deleted. Calles @Object and @LibraryFromObjects
818 #  If @Library is invoked with no suffix on _library_, the $(SUFLIB)
819 #  suffix is used
821 rule Library {
822   LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
823   Objects $(>) ;
827 # /SharedLibrary  library : sources : def : import ;
829 # Compiles _sources_ and generates a shared _library_ (i.e. DLL on Windows,
830 # or shared object on Unix). Calls @SharedObjects and @SharedLibraryFromObjects
832 # If @SharedLibrary is invoked with no suffix on _library_, then
833 # $(SUFLIBSHR) suffix is used
835 # _def_ is the name of the corresponding definition file used to generate
836 # the library on Windows and OS/2 (ignored otherwise). If undefined, it
837 # will default to _library_ with the .def suffix
839 # _import_ is the name of the corresponding import library for Windows
840 # and OS/2 platforms (ignored otherwise). If undefined, it will default
841 # to _library_ with the .dll.lib suffix.
843 rule SharedLibrary {
844   #Echo "SharedLibrary: $(<)" ; #dbg
845   #Echo "SharedLibrary: $(>:S=$(SUFOBJSHR))" ; #dbg
846   #Echo "SharedLibrary: $(3)" ; #dbg
847   #Echo "SharedLibrary: $(4)" ; #dbg
848   SharedLibraryFromObjects $(<) : $(>:S=$(SUFOBJSHR)) : $(3) : $(4) ;
849   SharedObjects $(>) ;
852 ######################################################
853 # k8: REWORK!
854 ######################################################
855 if $(UNIX) {
856   # this rule is used to find the 'libtool' script in the current
857   # path, this is required when compiling shared objects on Unix
858   rule LibToolFind {
859     if $(LIBTOOL) { return $(LIBTOOL) ; }
860     local matches = [ Glob $(PATH) : libtool ] ;
861     if ! $(matches) { Exit "could not find 'libtool' program in current path. Aborting !" ; }
862     LIBTOOL = $(matches[1]) ;
863     return $(LIBTOOL) ;
864   }
868 # /LibraryFromObjects library : objects ;
870 # Archives _objects_ into _library_. The _objects_ are then deleted
872 # If _library_ has no suffix, the $(SUFLIB) suffix is used
874 # Called by @Library rule. Most people should never call this rule
875 # directly.
877 rule LibraryFromObjects {
878   local _i _l _s ;
880   # Add grist to file names
881   _s = [ FGristFiles $(>) ] ;
882   _l = $(<:S=$(SUFLIB)) ;
884   # library depends on its member objects
885   if $(KEEPOBJS) {
886     Depends obj : $(_s) ;
887   } else {
888     Depends lib : $(_l) ;
889   }
891   # Set LOCATE for the library and its contents.  The bound
892   # value shows up as $(NEEDLIBS) on the Link actions.
893   # For compatibility, we only do this if the library doesn't
894   # already have a path.
895   if ! $(_l:D) {
896     #!!MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ;
897     MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_LIB) ;
898   }
900   if $(NOARSCAN) {
901     # If we can't scan the library to timestamp its contents,
902     # we have to just make the library depend directly on the
903     # on-disk object files.
904     Depends $(_l) : $(_s) ;
905   } else {
906     # If we can scan the library, we make the library depend
907     # on its members and each member depend on the on-disk
908     # object file.
909     Depends $(_l) : $(_l)($(_s:BS)) ;
910     for _i in $(_s) {
911       Depends $(_l)($(_i:BS)) : $(_i) ;
912     }
913   }
915   Clean clean : $(_l) ;
917   if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; }
919   Archive $(_l) : $(_s) ;
921   if $(RANLIB) { Ranlib $(_l) ; }
923   # If we can't scan the library, we have to leave the .o's around.
925   if ! ( $(NOARSCAN) || $(NOARUPDATE) ) { RmTemps $(_l) : $(_s) ; }
929 # /SharedLibraryFromObjects  library : objects : def : import ;
931 # Equivalent of @LibraryFromObjects for shared libraries.
933 # Called by @SharedLibrary. Most people shouldn't call this rule
934 # directly
936 rule SharedLibraryFromObjects {
937   local _i _l _s ;
939   # Add grist to file names
940   _s = [ FGristFiles $(>) ] ;
941   _l = $(<:S=$(SUFLIBSHR)) ;
943   #Echo "Library is $(_l)"    ;
944   # library depends on its member objects
945   if $(KEEPOBJS) {
946     Depends obj : $(_s) ;
947   } else {
948     Depends lib : $(_l) ;
949   }
951   # Set LOCATE for the library and its contents.  The bound
952   # value shows up as $(NEEDLIBS) on the Link actions.
953   # For compatibility, we only do this if the library doesn't
954   # already have a path.
955   if ! $(_l:D) {
956     #!!MakeLocate $(_l) : $(LOCATE_TARGET) ;
957     MakeLocate $(_l) : $(LOCATE_LIBSO) ;
958   }
960   #Echo "SharedLibraryFromObjects: _s = $(_s)" ; #dbg
961   #Echo "SharedLibraryFromObjects: _l = $(_l)" ; #dbg
963   # we never scan shared libraries for member objects
964   Depends $(_l) : $(_s) ;
966   Clean clean : $(_l) ;
968   # I don't know if VMS supports shared libraries, so I prefer
969   # to disable the following right now
970   #
971   #if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; }
973   # creating the library is so much fun on Unix :-)
974   if $(UNIX) {
975     if $(K8_USE_LIBTOOL) {
976       local libtool = [ LibToolFind ] ;  # find the right libtool
977       AR on $(_l) = "$(libtool) --mode=link $(AR:J= )" ;
978     } else {
979       LINKFLAGS on $(_l) += "-shared" ;
980       C++LINKFLAGS on $(_l) += "-shared" ;
981       LinkUnixLibrary $(_l) : $(_s) ;
982     }
983   } else if $(NT) {
984     local _implib = $(4) ;
985     local _def    = $(3) ;
987     _implib ?= $(_l:S=$(SUFLIBSHR)$(SUFLIB)) ;
988     _def    ?= $(_l:S=.def) ;
990     Clean    clean : $(_implib) ;
991     Depends  lib   : $(_implib) $(_def) ;
993     Depends $(_implib) : $(_def) $(_l) ;
994     Depends $(_l)      : $(_def) ;
996     DEFFILENAME on $(_l) = $(_def) ;
997     IMPLIBNAME  on $(_l) = $(_implib) ;
999     #!!MakeLocate $(_implib)        : $(LOCATE_TARGET) ;
1000     #!!MakeLocate $(_implib:S=.exp) : $(LOCATE_TARGET) ;
1001     MakeLocate $(_implib)        : $(LOCATE_LIBSO) ;
1002     MakeLocate $(_implib:S=.exp) : $(LOCATE_LIBSO) ;
1004     if $(JAM_TOOLSET) in VISUALC BORLANDC LCC WATCOM DIGITALMARS {
1005       SharedLink-$(JAM_TOOLSET) $(_l) : $(_s) : $(_implib) : $(_def) ;
1006     }
1007     DllLink $(_l) : $(_s) ;
1008   } else {
1009     Echo "Sorry, I don't know how to make a shared library on your system" ;
1010     Exit "Please *DON'T* contact the KJam maintainer for help" ;
1011   }
1015 # Since building shared libraries is so different depending on the
1016 # compiler being used, I've broken this task into compiler-specific
1017 # ones
1020 rule SharedLink-LCC {
1021   Echo "Sorry, but generating DLLs with LCC is not supported. That's" ;
1022   Echo "because the 'lcclnk' tool that comes with this compiler is" ;
1023   Echo "unreliable and doesn't work as expected." ;
1024   Exit ;
1026   # the 'lcclnk' tool is absolutely broken:
1027   #   - its -o flag doesn't work when there is a LIBRARY statement
1028   #     in the .def file.
1029   #
1030   #   - it uses the LIBRARY name in the .def file to determine
1031   #     the name of the dll and its import library, and always
1032   #     places them in the current directory !!
1033   #
1034   #   - if there is no LIBRARY statement, the -o flag is only
1035   #     used to determine where the DLL is placed, the import
1036   #     library will always be placed in the current directory !!
1037   #
1039   # clean the .exp file too, don't know how to get rid of it
1040   Clean clean : $(4:S=.exp) ;
1044 # /Link  image : objects ;
1046 # Links _image_ from _objects_ and sets permissions on _image_ to
1047 # $(EXEMODE). _image_ must be an actual filename; suffix is not
1048 # supplied.
1050 # Called by @Main, shouldn't be called by most people
1052 rule Link {
1053   MODE on $(<) = $(EXEMODE) ;
1054   Chmod $(<) ;
1058 # /LinkC++  image : objects ;
1060 # Links _image_ from _objects_ and sets permissions on _image_ to
1061 # $(EXEMODE). _image_ must be an actual filename; suffix is not
1062 # supplied.
1064 # Called by @Main, shouldn't be called by most people
1066 rule LinkC++ {
1067   MODE on $(<) = $(EXEMODE) ;
1068   Chmod $(<) ;
1072 # /LinkLibraries image : libraries ;
1074 # Makes _image_ depend on _libraries_ and includes them during linking
1076 # _image_ may be referenced without a suffix in this rule invocation.
1077 # @LinkLibraries supplies the suffix
1079 # You should only use this rule with libraries created through the
1080 # @Library rule. For external libraries, use something else (XXX)
1082 rule LinkLibraries {
1083   # make library dependencies of target
1084   # set NEEDLIBS variable used by 'actions Main'
1085   local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
1087   Depends $(_t) : $(>:S=$(SUFLIB)) ;
1088   NEEDLIBS on $(_t) += $(>:S=$(SUFLIB)) ;
1092 # /LinkSharedLibraries image : libraries :
1094 # Same as @LinkLibraries, but to link _image_ with shared libraries
1095 # generated through the @SharedLibrary rule
1097 rule LinkSharedLibraries {
1098   # make library dependencies of target
1099   # set NEEDLIBS variable used by 'actions Main'
1100   local _t   = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
1101   local _ext = $(SUFLIBSHR) ;
1103   if $(NT) {
1104     # on NT, we need to link agains the import library, not the DLL itself !!
1105     _ext = $(SUFLIBSHR)$(SUFLIB) ;
1106   }
1107   Depends $(_t) : $(>:S=$(_ext))  ;
1108   NEEDLIBS on $(_t) += $(>:S=$(_ext)) ;
1112 # /Main image : sources ;
1114 # Compiles _sources_ and links them into _image_. Calls @Objects and
1115 # @MainFromObjects.
1117 # _image_ may be supplied without suffix.
1119 rule Main {
1120   MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
1121   Objects $(>) ;
1125 # /MainC++ image : sources ;
1127 # Compiles _sources_ and links them into _image_. Calls @Objects and
1128 # @MainFromObjectsC++.
1130 # _image_ may be supplied without suffix.
1132 rule MainC++ {
1133   MainFromObjectsC++ $(<) : $(>:S=$(SUFOBJ)) ;
1134   Objects $(>) ;
1138 # /MainFromObjects image : objects ;
1140 # Links _objects_ into _image_. Dependency of exe.
1141 # @MainFromObjects provides a default suffix for _image_
1143 rule MainFromObjects {
1144   local _s _t ;
1146   # Add grist to file names
1147   # Add suffix to exe
1148   _s = [ FGristFiles $(>) ] ;
1149   _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
1150   # so 'jam foo' works when it's really foo.exe
1152   if $(_t) != $(<) {
1153     Depends $(<) : $(_t) ;
1154     NotFile $(<) ;
1155   }
1157   # make compiled sources a dependency of target
1158   Depends exe : $(_t) ;
1159   Depends $(_t) : $(_s) ;
1160   #k8:MakeLocate $(_t) : $(LOCATE_TARGET) ;
1161   MakeLocate $(_t) : $(LOCATE_BIN) ;
1162   Clean clean : $(_t) ;
1164   # special case for stupid Borland C++, which always generates a
1165   # .tds file for executables, even when no debug information is needed
1166   #
1167   #if $(JAM_TOOLSET) = BORLANDC {
1168   #  MakeLocate $(_t:S=.tds) : $(LOCATE_TARGET) ;
1169   #  Clean  clean : $(_t:S=.tds) ;
1170   #}
1172   Link $(_t) : $(_s) ;
1176 # /MainFromObjectsC++ image : objects ;
1178 # Links _objects_ into _image_. Dependency of exe.
1179 # @MainFromObjects provides a default suffix for _image_
1181 rule MainFromObjectsC++ {
1182   local _s _t ;
1184   # Add grist to file names
1185   # Add suffix to exe
1186   _s = [ FGristFiles $(>) ] ;
1187   _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
1188   # so 'jam foo' works when it's really foo.exe
1190   if $(_t) != $(<) {
1191     Depends $(<) : $(_t) ;
1192     NotFile $(<) ;
1193   }
1195   # make compiled sources a dependency of target
1196   Depends exe : $(_t) ;
1197   Depends $(_t) : $(_s) ;
1198   #k8:MakeLocate $(_t) : $(LOCATE_TARGET) ;
1199   MakeLocate $(_t) : $(LOCATE_BIN) ;
1200   Clean clean : $(_t) ;
1202   # special case for stupid Borland C++, which always generates a
1203   # .tds file for executables, even when no debug information is needed
1204   #
1205   #if $(JAM_TOOLSET) = BORLANDC {
1206   #  MakeLocate $(_t:S=.tds) : $(LOCATE_TARGET) ;
1207   #  Clean  clean : $(_t:S=.tds) ;
1208   #}
1210   LinkC++ $(_t) : $(_s) ;  ###k8:FIXME
1214 # /MakeLocate  targets : directory
1216 # Creates _dir_ and causes _target_ to be built into _dir_
1218 # This is done by setting the target-specific variable LOCATE
1219 # on _targets_, and arranges with @MkDir to create the target
1220 # directory
1222 rule MakeLocate {
1223   # Note we grist the directory name with 'dir',
1224   # so that directory path components and other
1225   # targets don't conflict.
1226   if $(>) {
1227     LOCATE on $(<) = $(>) ;
1228     Depends $(<) : $(>[1]:G=dir) ;
1229     MkDir $(>[1]:G=dir) ;
1230   }
1234 # /MkDir  dir ;
1236 # Creates _dir_ and its parent directories
1238 rule MkDir {
1239   # Ignore timestamps on directories: we only care if they exist.
1240   NoUpdate $(<) ;
1242   # Don't create . or any directory already created.
1243   if $(<:G=) != $(DOT) && ! $($(<)-mkdir) {
1244     # Cheesy gate to prevent multiple invocations on same dir
1245     # Arrange for jam dirs
1246     # MkDir1 has the actions
1247     $(<)-mkdir = true ;
1248     Depends dirs : $(<) ;
1249     MkDir1 $(<) ;
1251     # Recursively make parent directories.
1252     # $(<:P) = $(<)'s parent, & we recurse until root
1253     local s = $(<:P) ;
1255     # Don't try to create A: or A:\ on windows
1256     if $(NT) {
1257       switch $(s) {
1258         case *:   : s = ;
1259         case *:\\ : s = ;
1260       }
1261     }
1262     # handle "C:", "C:/", "/cygdrive" and "/cygdrive/" in Cygwin
1263     if $(UNIX) && $(OS) = CYGWIN {
1264       switch $(s) {
1265         case ?:   : s = ;
1266         case ?:/  : s = ;
1267         case <dir>/cygdrive   : s = ;
1268         case <dir>/cygdrive/  : s = ;
1269       }
1270     }
1272     if $(s) = $(<) {
1273       # The parent is the same as the dir.
1274       # We're at the root, which some OS's can't stat, so we mark
1275       # it as NotFile.
1276       NotFile $(s) ;
1277     } else if $(s:G=) {
1278       # There's a parent; recurse.
1279       Depends $(<) : $(s) ;
1280       MkDir $(s) ;
1281     }
1282   }
1286 # /Object object : source ;
1288 # Compile s a single _source_ file into _object_. The @Main and @Library
1289 # rules use it to compile sources.
1291 # Causes _source_ to be scanned for #include directives and calls @HdrRule
1292 # to make all included files dependencies of _object_.
1294 # Calls one of the following rules depending on the suffix to do the
1295 # actual compilation:
1297 rule Object {
1298   # locate object and search for source, if wanted
1300   Clean clean : $(<) ;
1301   MakeLocate $(<) : $(LOCATE_TARGET) ;
1302   SEARCH on $(>) = $(SEARCH_SOURCE) ;
1304   # Save HDRS for -I$(HDRS) on compile.
1305   # We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers
1306   # in the .c file's directory, but generated .c files (from
1307   # yacc, lex, etc) are located in $(LOCATE_TARGET), possibly
1308   # different from $(SEARCH_SOURCE).
1309   HDRS on $(<) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ;
1311   # handle #includes for source: Jam scans for headers with
1312   # the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE)
1313   # with the scanned file as the target and the found headers
1314   # as the sources.  HDRSEARCH is the value of SEARCH used for
1315   # the found header files.  Finally, if jam must deal with
1316   # header files of the same name in different directories,
1317   # they can be distinguished with HDRGRIST.
1319   # $(SEARCH_SOURCE:E) is where cc first looks for #include
1320   # "foo.h" files.  If the source file is in a distant directory,
1321   # look there.  Else, look in "" (the current directory).
1323   HDRRULE on $(>) = HdrRule ;
1324   HDRSCAN on $(>) = $(HDRPATTERN) ;
1325   HDRSEARCH on $(>) = $(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ;
1326   HDRGRIST on $(>) = $(HDRGRIST) ;
1328   # propagate target specific-defines
1329   DEFINES on $(<) += $(DEFINES) ;
1331   # if source is not .c, generate .c with specific rule
1332   switch $(>:S) {
1333     case .asm : As $(<) : $(>) ;
1334     case .c :   Cc $(<) : $(>) ;
1335     case .C :   C++ $(<) : $(>) ;
1336     case .cc :  C++ $(<) : $(>) ;
1337     case .cpp : C++ $(<) : $(>) ;
1338     case .cxx : C++ $(<) : $(>) ;
1339     case .c++ : C++ $(<) : $(>) ;
1340     case .C++ : C++ $(<) : $(>) ;
1341     case .d :   Dc $(<) : $(>) ;
1342     case .l :   Cc $(<) : $(<:S=.c) ;
1343                 Lex $(<:S=.c) : $(>) ;
1344     case .s :   As $(<) : $(>) ;
1345     case .y :   Cc $(<) : $(<:S=$(YACCGEN)) ;
1346                 Yacc $(<:S=$(YACCGEN)) : $(>) ;
1347     case * :    UserObject $(<) : $(>) ;
1348   }
1352 # /ObjectCcFlags  sources : flags ;
1354 # this rule is used to add compiler flags to the compilation of
1355 # specific C sources files.
1357 rule ObjectCcFlags {
1358   CCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
1362 # /ObjectC++Flags  sources : flags ;
1364 # this rule is used to add compiler flags to the compilation of
1365 # specific C++ source files
1367 rule ObjectC++Flags {
1368   C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(>) ;
1372 # /ObjectDefines  objects : macros ;
1374 # this rule is used to add macro defines to the compilation of
1375 # specific C and C++ source files
1377 rule ObjectDefines {
1378   # must reformat CCDEFS according to current defines
1379   local s = [ FGristFiles $(<:S=$(SUFOBJ)) ] ;
1381   DEFINES on $(s) += $(>) ;
1382   CCDEFS on $(s) = [ on $(s) FDefines $(DEFINES) ] ;
1386 # /ObjectHdrs  sources : paths ;
1388 # this rule is used to add include paths to the compilation of
1389 # specific C and C++ source files
1391 rule ObjectHdrs {
1392   # Add to HDRS for HdrScan's benefit.
1393   # must reformat CCHDRS according to headers
1394   local s = [ FGristFiles $(<:S=$(SUFOBJ)) ] ;
1396   HDRS on $(s) += $(>) ;
1397   CCHDRS on $(s) = [ on $(s) FIncludes $(HDRS) ] ;
1401 # /Objects sources ;
1403 # this rule is used to compile one or more sources into object files.
1404 # do not call it directly, it is used by the Main and Library rules
1405 # automatically
1407 rule Objects {
1408   local _i ;
1410   for _i in [ FGristFiles $(<) ] {
1411     Object $(_i:S=$(SUFOBJ)) : $(_i) ;
1412     Depends obj : $(_i:S=$(SUFOBJ)) ;
1413   }
1417 # /SharedObjects
1419 # this rule is used to compile one or more sources into 'shared object
1420 # files'. This means object files used to build either DLLs or Unix shared
1421 # libraries.
1423 # do not call this rule directly, it is called by SharedLibrary automatically
1425 rule SharedObjects {
1426   # temporarily override SUFOBJ with $(SUFOBJSHR) to
1427   local SUFOBJ = $(SUFOBJSHR) ;
1429   # call the normal Objects rule
1430   Objects $(<) ;
1432   # add the compiler-specific position-independent-code flag  where needed
1433   ObjectCcFlags $(<) : $(PICFLAGS) ;
1435   # change the compiler invokation for all these objects
1436   # to use Libtool on Unix systems. We explicitely disable the
1437   # generation of static objects here
1438   if $(UNIX) {
1439     #libtool on $(<:S=$(SUFOBJ)) = [ LibToolFind ] ;
1440     if $(K8_USE_LIBTOOL) {
1441       local libtool = [ LibToolFind ] ;
1442       CC on $(<:S=$(SUFOBJ)) = "$(libtool) --mode=compile $(CC:J= ) -dynamic" ;
1443       C++ on $(<:S=$(SUFOBJ)) = "$(libtool) --mode=compile $(C++:J= ) -dynamic" ; #k8:?
1444     }
1445   }
1449 rule RmTemps {
1450   Temporary $(>) ;
1454 rule Setuid {
1455   MODE on [ FAppendSuffix $(<) : $(SUFEXE) ] = 4711 ;
1459 rule Shell {
1460   Depends shell : $(<) ;
1461   Depends $(<) : $(>) ;
1462   SEARCH on $(>) = $(SEARCH_SOURCE) ;
1463   MODE on $(<) = $(SHELLMODE) ;
1464   Clean clean : $(<) ;
1465   Chmod $(<) ;
1469 rule SoftLink {
1470   Depends files : $(<) ;
1471   Depends $(<) : $(>) ;
1472   SEARCH on $(>) = $(SEARCH_SOURCE) ;
1473   Clean clean : $(<) ;
1477 rule SubDir {
1478   #
1479   # SubDir TOP d1 d2 ... ;
1480   #
1481   # Support for a project tree spanning multiple directories.
1482   #
1483   # SubDir declares a Jamfile's location in a project tree, setting
1484   # Jambase variables (SEARCH_SOURCE, LOCATE_TARGET) so that source
1485   # files can be found.
1486   #
1487   # TOP is a user-select variable name for root of the tree, and
1488   # d1 d2 ...  are the directory elements that lead from the root
1489   # of the tree to the directory of the Jamfile.
1490   #
1491   # TOP can be set externally, but normally the first SubDir call
1492   # computes TOP as the path up from the current directory; the
1493   # path contains one ../ for each of d1 d2 ...
1494   #
1495   # SubDir reads once the project-specific rules file Jamrules
1496   # in the TOP directory, if present.  This can be overridden
1497   # with the variable TOPRULES.
1498   #
1499   # SubDir supports multiple, overlaid project trees:  SubDir
1500   # invocations with different TOPs can appear in the same Jamfile.
1501   # The location established by the first SubDir call is used set
1502   # the TOPs for the subsequent SubDir calls.
1503   #
1504   # SubDir's public variables:
1505   #
1506   #   $(TOP) = path from CWD to root.
1507   #   $(SUBDIR) = path from CWD to the directory SubDir names.
1508   #   $(SUBDIR_TOKENS) = path from $(TOP) to $(SUBDIR) as dir names
1509   #   $(SEARCH_SOURCE) = $(SUBDIR)
1510   #   $(LOCATE_SOURCE) = $(ALL_LOCATE_TARGET) $(SUBDIR)
1511   #   $(LOCATE_TARGET) = $(ALL_LOCATE_TARGET) $(SUBDIR)
1512   #   $(LOCATE_BIN) = $(ALL_LOCATE_BIN) $(ALL_LOCATE_TARGET) $(SUBDIR)
1513   #   $(LOCATE_LIB) = $(ALL_LOCATE_LIB) $(ALL_LOCATE_TARGET) $(SUBDIR)
1514   #   $(LOCATE_LIBSO) = $(ALL_LOCATE_LIBSO) $(ALL_LOCATE_LIB) $(ALL_LOCATE_TARGET) $(SUBDIR)
1515   #   $(SOURCE_GRIST) = $(SUBDIR_TOKENS) with !'s
1516   #
1517   local _top = $(<[1]) ;
1518   local _tokens = $(<[2-]) ;
1520   local ktmp ;
1522   # First time through sets up relative root and includes Jamrules.
1523   if ! $(_top) { Exit SubDir syntax error ; }
1525   if ! $($(_top)-SET) {
1526     $(_top)-SET = true ;
1527     # First time we've seen this TOP.
1528     # We'll initialize a number of internal variables:
1529     #
1530     #   $(TOP-UP) = directories from ROOT to a common point
1531     #   $(TOP-DOWN) = directories from common point to TOP
1532     #   $(TOP-ROOT) = root directory for UP/DOWN -- normally CWD
1533     #   $(SUBDIR_UP) = current value of $(TOP-UP)
1534     #   $(SUBDIR_DOWN) = current value of $(TOP-DOWN)
1535     #   $(SUBDIR_ROOT) = current value of $(TOP-ROOT)
1536     #
1537     if $($(_top)) {
1538       # TOP externally set.
1539       # We'll ignore the relative (UP/DOWN) path that
1540       # got us here, and instead remember the hard ROOT.
1541       $(_top)-UP = ;
1542       $(_top)-DOWN = ;
1543       $(_top)-ROOT = $($(_top)) ;
1544     } else {
1545       # TOP not preset.
1547       # Establishing a new TOP.  In the simplest case,
1548       # (SUBDIR_UP/SUBDIR_DOWN/SUBDIR_ROOT unset), it's
1549       # merely a certain number of directories down from
1550       # the current directory, and FSubDirPath will set
1551       # TOP to a path consisting of ../ for each of the
1552       # elements of _tokens, because that represents how
1553       # far below TOP the current directory sits.
1554       #
1555       # In the more complicated case, the starting directory
1556       # isn't the directory of jam's invocation but an
1557       # location established by previous SubDir call.  The
1558       # starting directory is SUBDIR_UP directories up from
1559       # SUBDIR_ROOT, and then SUBDIR_DOWN directories down
1560       # from that.   If SUBDIR_ROOT is not set, that means
1561       # SUBDIR_DOWN and SUBDIR_UP represent the path from
1562       # the directory of jam's invocation.
1563       #
1564       # In the most complicated case, the _tokens also
1565       # represents directories down, because TOP is being
1566       # estalished in a directory other than TOP's root.
1567       # Hopefully, _tokens and SUBDIR_DOWN represent the
1568       # same final directory, relative to the new TOP and
1569       # the previous SubDIr's TOP.  To find the new TOP,
1570       # we have to chop off any common directories from
1571       # then ends of _tokens and SUBDIR_DOWN.  To do so,
1572       # we reverse each of them, call FStripCommon to
1573       # remove the initial common elements, and then
1574       # reverse them again.  After this process, if
1575       # both _tokens and SUBDIR_DOWN have elements, it
1576       # means the directory names estalished by the two
1577       # SubDir calls don't match, and a warning is issued.
1578       # All hell will likely break loose at this point,
1579       # since the whole SubDir scheme relies on the SubDir
1580       # calls accurately naming the current directory.
1582       # Strip common trailing elements of _tokens and SUBDIR_DOWN.
1583       _tokens = [ FReverse $(_tokens) ] ;
1584       SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
1585       FStripCommon _tokens : SUBDIR_DOWN ;
1586       SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
1587       _tokens = [ FReverse $(_tokens) ] ;
1589       if $(SUBDIR_DOWN) && $(_tokens) { Echo Warning: SubDir $(<) misplaced! ; }
1591       # We'll remember the relative (UP/DOWN) path that
1592       # got us here, plus any hard ROOT starting point
1593       # for the UP/DOWN.  If TOP is never set externally,
1594       # ROOT will always be "" (directory of jam's invocation).
1595       $(_top)-UP = $(SUBDIR_UP) $(_tokens) ;
1596       $(_top)-DOWN = $(SUBDIR_DOWN) ;
1597       $(_top)-ROOT = $(SUBDIR_ROOT:E="") ;
1598       $(_top) = [ FSubDirPath $(_top) ] ;
1599     }
1601     # Set subdir vars for the inclusion of the Jamrules,
1602     # just in case they have SubDir rules of their own.
1603     # Note that SUBDIR_DOWN is empty: it's all the way
1604     # up where the Jamrules live.  These gets overrided
1605     # just after the inclusion.
1606     SUBDIR_UP = $($(_top)-UP) ;
1607     SUBDIR_DOWN = ;
1608     SUBDIR_ROOT = $($(_top)-ROOT) ;
1610     # Include $(TOPRULES) or $(TOP)/Jamrules.
1611     # Include $(TOPRULES) if set.
1612     # Otherwise include $(TOP)/Jamrules if present.
1613     if $($(_top)RULES) {
1614       include $($(_top)RULES) ;
1615     } else {
1616       NoCare $(JAMRULES:R=$($(_top)):G=$(_top)) ;
1617       include $(JAMRULES:R=$($(_top)):G=$(_top)) ;
1618     }
1619   }
1621   # Get path from $(TOP) to named directory.
1622   # Save dir tokens for other potential uses.
1623   SUBDIR_UP = $($(_top)-UP) ;
1624   SUBDIR_DOWN = $($(_top)-DOWN) $(_tokens) ;
1625   SUBDIR_ROOT = $($(_top)-ROOT) ;
1626   SUBDIR_TOKENS = $(SUBDIR_DOWN) ;
1628   SUBDIR = [ FSubDirPath $(<) ] ;
1630   # Now set up SEARCH_SOURCE, LOCATE_TARGET, LOCATE_BIN, SOURCE_GRIST
1631   # These can be reset if needed.  For example, if the source
1632   # directory should not hold object files, LOCATE_TARGET can
1633   # subsequently be redefined.
1634   SEARCH_SOURCE = $(SUBDIR) ;
1635   LOCATE_SOURCE = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
1636   LOCATE_TARGET = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
1638   ktmp = $(ALL_LOCATE_BIN) ;
1639   if ! $(ktmp) { ktmp = $(ALL_LOCATE_TARGET) ; }
1640   LOCATE_BIN = $(ktmp) $(SUBDIR) ;
1642   ktmp = $(ALL_LOCATE_LIB) ;
1643   if ! $(ktmp) { ktmp = $(ALL_LOCATE_TARGET) ; }
1644   LOCATE_LIB = $(ktmp) $(SUBDIR) ;
1646   ktmp = $(ALL_LOCATE_LIBSO) ;
1647   if ! $(ktmp) { ktmp = $(ALL_LOCATE_LIB) ; }
1648   if ! $(ktmp) { ktmp = $(ALL_LOCATE_TARGET) ; }
1649   LOCATE_LIBSO = $(ktmp) $(SUBDIR) ;
1651   SOURCE_GRIST = [ FGrist $(SUBDIR_TOKENS) ] ;
1652   #if ! $(LOCATE_BIN) { LOCATE_BIN = $(LOCATE_TARGET) ; }
1654   # Reset per-directory ccflags, hdrs, etc,
1655   # listed in SUBDIRRESET.
1656   # Note use of variable expanded assignment var
1657   SUBDIR$(SUBDIRRESET) = ;
1659   # Invoke user-specific SubDir extensions,
1660   # rule names listed in SUBDIRRULES.
1661   # Note use of variable expanded rule invocation
1662   $(SUBDIRRULES) $(<) ;
1666 rule FSubDirPath {
1667   # FSubDirPath TOP d1 ... ;
1669   # Returns path to named directory.
1671   # If jam is invoked in a subdirectory of the TOP, then we
1672   # need to prepend a ../ for every level we must climb up
1673   # (TOP-UP), and then append the directory names we must
1674   # climb down (TOP-DOWN), plus the named directories d1 ...
1675   # If TOP was set externally, or computed from another TOP
1676   # that was, we'll have to reroot the whole thing at TOP-ROOT.
1677   local _r = [ FRelPath $($(<[1])-UP) : $($(<[1])-DOWN) $(<[2-]) ] ;
1679   return $(_r:R=$($(<[1])-ROOT)) ;
1683 rule SubDirDcFlags {
1684   SUBDIRDCFLAGS += $(<) ;
1688 rule SubDirCcFlags {
1689   SUBDIRCCFLAGS += $(<) ;
1693 rule SubDirC++Flags {
1694   SUBDIRC++FLAGS += $(<) ;
1698 rule SubDirHdrs {
1699   SUBDIRHDRS += [ FDirName $(<) ] ;
1703 rule SubInclude {
1704   # SubInclude TOP d1 ... ;
1705   #
1706   # Include a subdirectory's Jamfile.
1708   # We use SubDir to get there, in case the included Jamfile
1709   # either doesn't have its own SubDir (naughty) or is a subtree
1710   # with its own TOP.
1711   if ! $($(<[1])) { Exit SubInclude $(<[1]) without prior SubDir $(<[1]) ; }
1712   SubDir $(<) ;
1713   include $(JAMFILE:D=$(SUBDIR)) ;
1717 rule SubRules {
1718   # SubRules TOP d1 ... : Other-TOP ;
1719   #
1720   # Read another tree's Jamrules, by giving it's path according
1721   # to this tree and it's own name.
1722   if ! $($(<[1])) { Exit SubRules $(<[1]) without prior SubDir $(<[1]) ; }
1723   SubDir $(<) ;
1724   SubDir $(>) ;
1728 rule Undefines {
1729   UNDEFS on [ FAppendSuffix $(<) : $(SUFEXE) ] += $(UNDEFFLAG)$(>) ;
1733 rule UserObject {
1734   Exit "Unknown suffix on" $(>) "- see UserObject rule in Jamfile(5)." ;
1738 rule Yacc {
1739   local _h ;
1741   _h = $(<:BS=.h) ;
1743   # Some places don't have a yacc.
1744   MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ;
1746   if $(YACC) {
1747     Depends $(<) $(_h) : $(>) ;
1748     Yacc1 $(<) $(_h) : $(>) ;
1749     YaccMv $(<) $(_h) : $(>) ;
1750     Clean clean : $(<) $(_h) ;
1751   }
1753   # make sure someone includes $(_h) else it will be
1754   # a deadly independent target
1755   Includes $(<) : $(_h) ;
1760 # Utility rules; no side effects on these
1764 # /FGrist path to file ;
1766 # Returns a single string that is used as grist
1768 rule FGrist {
1769   return $(<:J=!) ;
1773 rule FGristFiles {
1774   return $(<:G=$(SOURCE_GRIST:E)) ;
1778 rule FGristSourceFiles {
1779   # Produce source file name name with grist in it,
1780   # if SOURCE_GRIST is set.
1782   # Leave header files alone, because they have a global
1783   # visibility.
1784   if ! $(SOURCE_GRIST) {
1785     return $(<) ;
1786   } else {
1787     local _i _o ;
1789     for _i in $(<) {
1790       switch $(_i) {
1791         case *.h : _o += $(_i) ;
1792         case * :   _o += $(_i:G=$(SOURCE_GRIST)) ;
1793       }
1794     }
1795     return $(_o) ;
1796   }
1800 rule FReverse {
1801   if $(1) { return [ FReverse $(1[2-]) ] $(1[1]) ; }
1805 rule FSubDir {
1806   # If $(>) is the path to the current directory, compute the
1807   # path (using ../../ etc) back to that root directory.
1808   # Sets result in $(<)
1809   if ! $(<[1]) {
1810     return $(DOT) ;
1811   } else {
1812     local _i _d ;
1814     _d = $(DOTDOT) ;
1815     for _i in $(<[2-]) { _d = $(_d:R=$(DOTDOT)) ; }
1816     return $(_d) ;
1817   }
1821 rule FStripCommon {
1822   # FStripCommon v1 : v2 ;
1824   # Strip common initial elements of variables v1 and v2.
1825   # Modifies the variable values themselves.
1826   if $($(<)[1]) && $($(<)[1]) = $($(>)[1]) {
1827     $(<) = $($(<)[2-]) ;
1828     $(>) = $($(>)[2-]) ;
1829     FStripCommon $(<) : $(>) ;
1830   }
1834 rule FRelPath {
1835   local _l _r ;
1837   # first strip off common parts
1838   _l = $(<) ;
1839   _r = $(>) ;
1840   FStripCommon _l : _r ;
1842   # now make path to root and path down
1843   _l = [ FSubDir $(_l) ] ;
1844   _r = [ FDirName $(_r) ] ;
1846   # Concatenate and save
1847   # XXX This should be better
1848   if $(_r) = $(DOT) { return $(_l) ; } else { return $(_r:R=$(_l)) ; }
1852 rule FAppendSuffix {
1853   # E.g., "FAppendSuffix yacc lex foo.bat : $(SUFEXE) ;"
1854   # returns (yacc,lex,foo.bat) on Unix and
1855   # (yacc.exe,lex.exe,foo.bat) on NT.
1856   if $(>) {
1857     local _i _o ;
1859     for _i in $(<) {
1860       if $(_i:S) { _o += $(_i) ; } else { _o += $(_i:S=$(>)) ; }
1861     }
1862     return $(_o) ;
1863   } else {
1864     return $(<) ;
1865   }
1870 # Operating system specific utility rules
1871 # First, the (generic) UNIX versions
1874 rule FQuote { return "\\\"$(<)\\\"" ; }
1875 rule FDefines { return -D$(<) ; }
1876 rule FIncludes { return -I$(<) ; }
1878 rule FDirName {
1879   # Turn individual elements in $(<) into a usable path.
1880   local _i ;
1881   local _s = $(DOT) ;
1883   for _i in $(<) { _s = $(_i:R=$(_s)) ; }
1884   return $(_s) ;
1888 if $(NT) && $(JAM_TOOLSET) != MINGW && $(JAM_TOOLSET) != LCC {
1889   rule FDefines { return /D$(<) ; }
1890   rule FIncludes { return /I$(<) ; }
1895 # Actions
1899 # First the defaults
1901 actions updated together piecemeal Archive {
1902   $(AR) $(<) $(>)
1906 actions As {
1907   $(AS) $(ASFLAGS) $(ASHDRS) -o $(<) $(>)
1911 actions C++ {
1912   $(C++) -c -o $(<) $(C++FLAGS) $(C++OPTIM) $(CCDEFS) $(CCHDRS) $(>)
1916 actions Cc {
1917   $(CC) -c -o $(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>)
1921 actions Dc {
1922   $(DC) -c -of$(<) $(DCFLAGS) $(DOPTIM) $(>)
1926 actions Chgrp {
1927   $(CHGRP) $(GROUP) $(<)
1931 actions Chmod1 {
1932   $(CHMOD) $(MODE) $(<)
1936 actions Chown {
1937   $(CHOWN) $(OWNER) $(<)
1941 actions piecemeal together existing Clean {
1942   $(RM) $(>)
1946 actions File {
1947   $(CP) $(>) $(<)
1951 actions GenFile1 {
1952   $(>[1]) $(<) $(>[2-])
1956 actions HardLink {
1957   $(RM) $(<) && $(LN) $(>) $(<)
1961 actions Install {
1962   $(CP) $(>) $(<)
1966 actions Lex {
1967   $(LEX) $(>)
1971 actions LexMv {
1972   $(MV) lex.yy.c $(<)
1976 actions Link bind NEEDLIBS {
1977   $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
1980 actions LinkC++ bind NEEDLIBS {
1981   $(C++LINK) $(C++LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(C++LINKLIBS)
1985 actions updated together piecemeal LinkUnixLibrary bind NEEDLIBS {
1986   $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
1989 actions updated together piecemeal LinkC++UnixLibrary bind NEEDLIBS {
1990   $(C++LINK) $(C++LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(C++LINKLIBS)
1994 actions MkDir1 {
1995   $(MKDIR) $(<)
1999 actions together Ranlib {
2000   $(RANLIB) $(<)
2004 actions quietly updated piecemeal together RmTemps {
2005   $(RM) $(>)
2009 actions Shell {
2010 #DONT_TOUCH
2011   $(AWK) '
2012     NR == 1 { print "$(SHELLHEADER)" }
2013     NR == 1 && /^[#:]/ { next }
2014     /^##/ { next }
2015     { print }
2016   ' < $(>) > $(<)
2017 #DONT_TOUCH
2021 actions SoftLink {
2022   $(RM) $(<) && $(LN) -s $(>) $(<)
2026 actions Yacc1 {
2027   $(YACC) $(YACCFLAGS) $(>)
2031 actions YaccMv {
2032   $(MV) $(YACCFILES).c $(<[1])
2033   $(MV) $(YACCFILES).h $(<[2])
2038 # RELOCATE - for compilers with broken -o flags
2040 if $(RELOCATE) {
2041   actions C++ {
2042     $(C++) -c $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>)
2043   }
2044   actions Cc {
2045     $(CC) -c $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) $(>)
2046   }
2047   actions ignore CcMv {
2048     [ $(<) != $(>:BS=$(SUFOBJ)) ] && $(MV) $(>:BS=$(SUFOBJ)) $(<)
2049   }
2054 # NOARUPDATE - can't update an archive
2056 if $(NOARUPDATE) {
2057   actions Archive {
2058     $(AR) $(<) $(>)
2059   }
2064 # UNIX specific actions
2066 if $(UNIX) {
2067   actions GenFile1 {
2068     PATH="$PATH:."
2069     $(>[1]) $(<) $(>[2-])
2070   }
2075 # NT specific actions
2077 if $(NT) {
2078   if $(JAM_TOOLSET) = MINGW {
2079     actions together piecemeal Archive {
2080       $(AR) $(<) $(>:T)
2081     }
2082     actions Cc {
2083       $(CC) -c -o $(<) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) -I$(STDHDRS) $(>)
2084     }
2085     actions C++ {
2086       $(C++) -c -o $(<) $(C++FLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) -I$(STDHDRS) $(>)
2087     }
2088     actions DllLink bind DEFFILENAME IMPLIBNAME {
2089       $(LINK) $(LINKFLAGS) -shared -o $(<) $(>) $(DEFFILENAME) -Wl,--out-implib,$(IMPLIBNAME)
2090     }
2091   } else if $(JAM_TOOLSET) = LCC {
2092     actions together piecemeal Archive {
2093       $(AR) /out:$(<) $(>)
2094     }
2095     actions Cc {
2096       $(CC) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS) -Fo$(<) -I$(STDHDRS) $(>)
2097     }
2098     actions Link bind NEEDLIBS {
2099       $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
2100     }
2101     actions DllLink bind NEEDLIBS DEFFILENAME {
2102       $(LINK) $(LINKFLAGS) -DLL -o $(<) $(UNDEFS) $(>) $(DEFFILENAME) $(NEEDLIBS) $(LINKLIBS)
2103     }
2104     actions ignore DllLinkMv {
2105       $(MV) $(2) $(1)
2106     }
2107     actions Shell {
2108       $(CP) $(>) $(<)
2109     }
2110   } else if $(JAM_TOOLSET) = PELLESC {
2111     actions together piecemeal Archive {
2112       $(AR) /OUT:$(<) $(>)
2113     }
2114     actions Cc {
2115       $(CC) $(CCFLAGS) $(OPTIM) $(CCDEFS) $(CCHDRS)   /Fo $(<) -I$(STDHDRS)  $(>)
2116     }
2117     actions Link bind NEEDLIBS {
2118       $(LINK) $(LINKFLAGS) /OUT:$(<) $(>) $(NEEDLIBS) $(LINKLIBS)
2119     }
2120     actions DllLink bind NEEDLIBS DEFFILENAME IMPLIBNAME {
2121       $(LINK) $(LINKFLAGS) /DLL /DEF:$(DEFFILENAME) /IMPLIB:$(IMPLIBNAME) /OUT:$(<) $(>) $(NEEDLIBS) $(LINKLIBS)
2122     }
2123     actions Shell {
2124       $(CP) $(>) $(<)
2125     }
2126   }
2131 # Backwards compatibility with jam 1, where rules were uppercased.
2132 # k8: removed
2134 ##rule BULK { Bulk $(<) : $(>) ; }
2135 ##rule FILE { File $(<) : $(>) ; }
2136 ##rule HDRRULE { HdrRule $(<) : $(>) ; }
2137 ##rule INSTALL { Install $(<) : $(>) ; }
2138 ##rule LIBRARY { Library $(<) : $(>) ; }
2139 ##rule LIBS { LinkLibraries $(<) : $(>) ; }
2140 ##rule LINK { Link $(<) : $(>) ; }
2141 ##rule C++LINK { LinkC++ $(<) : $(>) ; }
2142 ##rule MAIN { Main $(<) : $(>) ; }
2143 ##rule MAINC++ { MainC++ $(<) : $(>) ; }
2144 ##rule SETUID { Setuid $(<) ; }
2145 ##rule SHELL { Shell $(<) : $(>) ; }
2146 ##rule UNDEFINES { Undefines $(<) : $(>) ; }
2148 # Old INSTALL* didn't take dest directory.
2150 ##rule INSTALLBIN { InstallBin $(BINDIR) : $(<) ; }
2151 ##rule INSTALLLIB { InstallLib $(LIBDIR) : $(<) ; }
2152 ##rule INSTALLMAN { InstallMan $(MANDIR) : $(<) ; }
2154 # Compatibility with jam 2.2.
2156 rule addDirName { $(<) += [ FDirName $(>) ] ; }
2157 rule makeCommon { FStripCommon $(<) : $(>) ; }
2158 rule _makeCommon { FStripCommon $(<) : $(>) ; }
2159 rule makeDirName { $(<) = [ FDirName $(>) ] ; }
2160 rule makeGrist { $(<) = [ FGrist $(>) ] ; }
2161 rule makeGristedName { $(<) = [ FGristSourceFiles $(>) ] ; }
2162 rule makeRelPath { $(<[1]) = [ FRelPath $(<[2-]) : $(>) ] ; }
2163 rule makeString { $(<) = $(>:J) ; }
2164 rule makeSubDir { $(<) = [ FSubDir $(>) ] ; }
2165 rule makeSuffixed { $(<[1]) = [ FAppendSuffix $(>) : $(<[2]) ] ; }
2169 # Ketmar's additions
2172 rule CheckGCC42Plus {
2173   local t gccv ;
2175   t = [ Match "(gcc)" : "$(CC)" ] ;
2176   if $(t) != "gcc" { return "ona" ; }
2177   gccv = [ Command "gcc --version | line 1" ] ;
2179   t = [ Match "[\t\r\n ]+([0-9]+\\.)[0-9]+\\." : "$(gccv)" ] ;
2180   if $(t) != "4." { return "ona" ; }
2182   t = [ Match "[\t\r\n ]+[0-9]+\\.([0-9]+\\.)" : "$(gccv)" ] ;
2183   if $(t) = "0." { return "ona" ; }
2184   if $(t) = "1." { return "ona" ; }
2186   return "tan" ;
2190 rule SetCPUFlags {
2191   local t flg f skiping seting ;
2193   if $(OS) != "LINUX" {
2194     DETECTED_CPU = "i486" ;
2195     OPTIM_SPEED = -O3 -march=i486 -mtune=i486 ;
2196     return ;
2197   }
2199   t = [ CheckGCC42Plus ] ;
2200   if $(t) = "tan" {
2201     DETECTED_CPU = native ;
2202     OPTIM_SPEED = -O3 -march=native -mtune=native ;
2203     return ;
2204   }
2206   OPTIM_SPEED = ;
2207   # regexp, flags, empty
2208   flg =
2209     "([Ii]ntel.*[Cc]ore.*[Dd]uo)"
2210     "prescott"
2211     -O3 -march=prescott -mtune=prescott -mfpmath=sse
2212     ""
2213     "([Pp]entium.*III)"
2214     "pentium3"
2215     -O3 -march=pentium3 -mtune=pentium3 -mfpmath=sse
2216     ""
2217     "([Pp]entium.*II)"
2218     "pentium2"
2219     -O3 -march=pentium2 -mtune=pentium2
2220     ""
2221     "([Pp]entium)"
2222     "pentium"
2223     -O3 -march=pentium -mtune=pentium
2224     ""
2225   ;
2226   DETECTED_CPU = [ Command "uname -p" ] ;
2227   for f in $(flg) {
2228     if $(skiping) {
2229       if ! $(f) { skiping = ; }
2230     } else if $(seting) {
2231       if ! $(f) { return ; }
2232       if $(seting) = "first" {
2233         DETECTED_CPU = "$(f)" ;
2234         seting = tan ;
2235       } else {
2236         OPTIM_SPEED += "$(f)" ;
2237       }
2238     } else {
2239       t = [ Match "$(f)" : "$(DETECTED_CPU)" ] ;
2240       if $(t) { seting = first ; } else { skiping = tan ; }
2241     }
2242   }
2246 # VAR = [ RemoveOpt options-to-remove : options-list ] ;
2247 # remove options from list
2248 rule RemoveOpt {
2249   local oname = $(1) ;
2250   local str = $(2) ;
2251   local res = ;
2252   local f ;
2253   local oo ;
2254   #Echo "removing " $(oname) " from " $(str) ;
2255   for f in $(str) {
2256     if ! $(f) in $(oname) {
2257       res += $(f) ;
2258     }
2259   }
2260   return $(res) ;
2264 # VAR = [ RemoveOpt regexp-options-to-remove : options-list ] ;
2265 # remove options from list with egrep-like regexps
2266 rule RemoveOptWild {
2267   local oname = $(1) ;
2268   local str = $(2) ;
2269   local res = ;
2270   local f ;
2271   local t ;
2272   #Echo "removing " $(oname) " from " $(str) ;
2273   for f in $(str) {
2274     t = [ Match $(oname) : $(f) ] ;
2275     #Echo $(f) ": " $(t) ;
2276     if $(t[1]) = "" {
2277       #Echo "include: " $(f) ;
2278       res += $(f) ;
2279     }
2280   }
2281   return $(res) ;
2285 # profile "name" ;
2286 # set compile flags for profile; works only for gcc/g++
2287 # available profiles:
2288 #  none, default: don't change
2289 #  empty: remove optimisation flags
2290 #  speed: optimise for speed and pIII
2291 #  size: optimise for size
2292 #  debug: don't optimize, add debug info
2293 #  standard: -O2
2294 rule profile {
2295   local orm = "(^\\-march\\=)" "(^\\-mtune\\=)" "(^\\-mfpmath\\=)" "(^\\-O.$)" ;
2296   local ormff = "(^\\-f[^n][^o])" ;
2297   local t ;
2299   local isGCC = "ona" ;
2300   local isG++ = "ona" ;
2301   if ( "gcc" in $(CC) ) || ( $(JAM_TOOLSET) = MINGW ) { isGCC = "tan" ; }
2302   if ( "g++" in $(C++) ) || ( $(JAM_TOOLSET) = MINGW ) { isG++ = "tan" ; }
2304   if $(isGCC) = "tan" { OPTIM = [ RemoveOptWild $(orm) $(ormff) : $(OPTIM) ] ; }
2305   if $(isGCC) = "tan" { OPTIM = [ RemoveOptWild $(orm) $(ormff) : $(OPTIM) ] ; }
2306   if $(isG++) = "tan" { C++OPTIM = [ RemoveOptWild $(orm) $(ormff) : $(C++OPTIM) ] ; }
2307   if "gcc" in $(LINK) { LINKFLAGS = [ RemoveOpt "-g" "-s" : $(LINKFLAGS) ] ; }
2308   if $(isG++) = "tan" { C++LINKFLAGS = [ RemoveOpt "-g" "-s" : $(C++LINKFLAGS) ] ; }
2310   switch $(1) {
2311     case "none" :
2312       Echo "MSG: default profile" ;
2313       OPT_PROFILE = ;
2314     case "default" :
2315       Echo "MSG: default profile" ;
2316       OPT_PROFILE = "default" ;
2317     case "empty" :
2318       Echo "MSG: removing default optimization flags" ;
2319       LINKFLAGS += -s ;
2320       if $(isG++) = "tan" { C++LINKFLAGS += -s ; }
2321       SLACK_PKG_ARCH = "i486" ;
2322       OPT_PROFILE = "empty" ;
2323     case "speed" :
2324       SetCPUFlags ;
2325       Echo "MSG: optimizing for speed; CPU: $(DETECTED_CPU)" ;
2326       if $(isGCC) = "tan" { OPTIM += $(OPTIM_SPEED) ; }
2327       if $(isG++) = "tan" { C++OPTIM += $(OPTIM_SPEED) ; }
2328       if $(isGCC) = "tan" { LINKFLAGS += $(LINKFLAGS_SPEED) ; }
2329       if $(isG++) = "tan" { C++LINKFLAGS += $(LINKFLAGS_SPEED) ; }
2330       SLACK_PKG_ARCH = "i686" ;
2331       OPT_PROFILE = "speed" ;
2332     case "size" :
2333       Echo "MSG: optimizing for size" ;
2334       if $(isGCC) = "tan" { OPTIM += $(OPTIM_SIZE) ; }
2335       if $(isG++) = "tan" { C++OPTIM += $(OPTIM_SIZE) ; }
2336       if $(isGCC) = "tan" { LINKFLAGS += $(LINKFLAGS_SIZE) ; }
2337       if $(isG++) = "tan" { C++LINKFLAGS += $(LINKFLAGS_SIZE) ; }
2338       SLACK_PKG_ARCH = "i686" ;
2339       OPT_PROFILE = "size" ;
2340     case "debug" :
2341       Echo "MSG: debug build" ;
2342       if $(isGCC) = "tan" { OPTIM += $(OPTIM_DEBUG) ; }
2343       if $(isG++) = "tan" { C++OPTIM += $(OPTIM_DEBUG) ; }
2344       if $(isGCC) = "tan" { LINKFLAGS += $(LINKFLAGS_DEBUG) ; }
2345       if $(isG++) = "tan" { C++LINKFLAGS += $(LINKFLAGS_DEBUG) ; }
2346       SLACK_PKG_ARCH = "i486" ;
2347       OPT_PROFILE = "debug" ;
2348     case "standard" :
2349       Echo "MSG: standard build" ;
2350       if $(isGCC) = "tan" { OPTIM += -O2 ; }
2351       if $(isG++) = "tan" { C++OPTIM += -O2 ; }
2352       if $(isGCC) = "tan" { LINKFLAGS += -s ; }
2353       if $(isG++) = "tan" { C++LINKFLAGS += -s ; }
2354       SLACK_PKG_ARCH = "i486" ;
2355       OPT_PROFILE = "standard" ;
2356     case "*" :
2357       Exit "unknown profile; possible values are: default; empty; speed; size; debug; standard" ;
2358   }
2360 SLACK_PKG_ARCH ?= "i486" ;
2363 # ObjectNoAliasing filelist ;
2364 # turn off aliasing optimization for specified files
2365 # works only for gcc/g++
2366 rule ObjectNoAliasing {
2367   local isGCC = "ona" ;
2368   local isG++ = "ona" ;
2369   if ( "gcc" in $(CC) ) || ( $(JAM_TOOLSET) = MINGW ) { isGCC = "tan" ; }
2370   if ( "g++" in $(C++) ) || ( $(JAM_TOOLSET) = MINGW ) { isG++ = "tan" ; }
2372   if $(isGCC) = "tan" { CCFLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(OPTIM_NOALIAS) ; }
2373   if $(isG++) = "tan" { C++FLAGS on [ FGristFiles $(<:S=$(SUFOBJ)) ] += $(OPTIM_NOALIAS) ; }
2377 # call $(1) --cflags and $(1) --libs (many libs provides such configurators)
2378 # add necessary flags to compiler and linker vars
2379 # return "tan" (non-empty string) if library is present
2380 # if $(2) != "" -- don't add flags, just check
2381 rule lib-config {
2382   local cf ;
2383   local lf ;
2384   local hasit ;
2386   cf = [ Command "$(1) --cflags 2>/dev/null" : parse-output exit-code code-first ] ;
2387   #Echo "cf:" $(cf) ;
2388   if $(cf[1]) = "0" && $(cf[2]) {
2389     hasit = tan ;
2390     #Echo "flags:" $(cf[2-]) ;
2391     if ! $(2) {
2392       CCFLAGS += $(cf[2-]) ;
2393       C++FLAGS += $(cf[2-]) ;
2394     }
2395   }
2397   lf = [ Command "$(1) --libs 2>/dev/null" : parse-output exit-code code-first ] ;
2398   #Echo "lf:" $(lf) ;
2399   if $(lf[1]) = "0" && $(lf[2]) {
2400     hasit = "tan" ;
2401     #Echo "flags:" $(lf[2-]) ;
2402     if ! $(2) {
2403       LINKFLAGS += $(lf[2-]) ;
2404       C++LINKFLAGS += $(lf[2-]) ;
2405     }
2406   }
2408   return $(hasit) ;
2413 # Now include the user's Jamfile.
2415 include $(JAMFILE) ;