1#~ Copyright 2002-2007 Rene Rivera.
2#~ Distributed under the Boost Software License, Version 1.0.
3#~ (See accompanying file LICENSE_1_0.txt or copy at
4#~ http://www.boost.org/LICENSE_1_0.txt)
5
6# Clean env vars of any "extra" empty values.
7for local v in ARGV CC CFLAGS LIBS
8{
9    local values ;
10    for local x in $($(v))
11    {
12        if $(x) != ""
13        {
14            values += $(x) ;
15        }
16    }
17    $(v) = $(values) ;
18}
19
20# Platform related specifics.
21if $(OS) = NT { rule .path { return "$(<:J=\\)" ; } ./ = "/" ; }
22else { rule .path { return "$(<:J=/)" ; } }
23
24. = "." ;
25./ ?= "" ;
26
27# Info about what we are building.
28_VERSION_ = 3 1 19 ;
29NAME = boost-jam ;
30VERSION = $(_VERSION_:J=$(.)) ;
31RELEASE = 1 ;
32LICENSE = LICENSE_1_0 ;
33
34# Generate development debug binaries?
35if --debug in $(ARGV)
36{
37    debug = true ;
38}
39
40if --profile in $(ARGV)
41{
42    profile = true ;
43}
44
45# Attempt to generate and/or build the grammar?
46if --grammar in $(ARGV)
47{
48    grammar = true ;
49}
50
51# Do we need to add a default build type argument?
52if ! ( --release in $(ARGV) ) &&
53   ! ( --debug in $(ARGV) ) &&
54   ! ( --profile in $(ARGV) )
55{
56    ARGV += --release ;
57}
58
59# Enable, and configure, Python hooks.
60with-python = ;
61python-location = [ MATCH --with-python=(.*) : $(ARGV) ] ;
62if $(python-location)
63{
64    with-python = true ;
65}
66if $(with-python)
67{
68    if $(OS) = NT
69    {
70        --python-include = [ .path $(python-location) include ] ;
71        --python-lib = ;
72        for local v in 27 26 25 24 23 22
73        {
74            --python-lib ?=
75                [ GLOB [ .path $(python-location) libs ] : "python$(v).lib" ]
76                [ GLOB $(python-location) [ .path $(python-location) libs ]
77                    $(Path) $(PATH) $(path) : "python$(v).dll" ]
78                ;
79            if ! $(--python-lib[2])
80            {
81                --python-lib = ;
82            }
83        }
84        --python-lib = $(--python-lib[1]) ;
85    }
86    else if $(OS) = MACOSX
87    {
88        --python-include = [ .path $(python-location) Headers ] ;
89        --python-lib = $(python-location) Python ;
90    }
91    else
92    {
93        --python-include = ;
94        --python-lib = ;
95        for local v in 2.7 2.6 2.5 2.4 2.3 2.2
96        {
97            local inc = [ GLOB [ .path $(python-location) include ] : python$(v) ] ;
98            local lib = [ GLOB [ .path $(python-location) lib ] : libpython$(v)* ] ;
99            if $(inc) && $(lib)
100            {
101                --python-include ?= $(inc) ;
102                --python-lib ?= $(lib[1]:D) python$(v) ;
103            }
104        }
105    }
106}
107
108# Boehm GC?
109if --gc in $(ARGV)
110{
111    --boehm-gc = true ;
112}
113if $(--boehm-gc)
114{
115    --extra-include += [ .path [ PWD ] "boehm_gc" "include" ] ;
116}
117
118# Duma?
119if --duma in $(ARGV)
120{
121    --duma = true ;
122}
123if $(--duma)
124{
125    --extra-include += [ .path [ PWD ] "duma" ] ;
126}
127
128# An explicit root for the toolset? (trim spaces)
129toolset-root = [ MATCH --toolset-root=(.*) : $(ARGV) ] ;
130{
131    local t = [ MATCH "[ ]*(.*)" : $(toolset-root:J=" ") ] ;
132    toolset-root = ;
133    while $(t)
134    {
135        t = [ MATCH "([^ ]+)([ ]*)(.*)" : $(t) ] ;
136        toolset-root += $(t[1]) ;
137        if $(t[3]) { toolset-root += $(t[2]) ; }
138        t = $(t[3]) ;
139    }
140    toolset-root = $(toolset-root:J="") ;
141}
142
143# Configure the implemented toolsets. These are minimal commands and options to
144# compile the full Jam. When adding new toolsets make sure to add them to the
145# "known" list also.
146
147rule toolset ( name command .type ? : opt.out + : opt.define * : flags * : linklibs * )
148{
149    .type ?= "" ;
150    tool.$(name)$(.type).cc ?= $(command) ;
151    tool.$(name)$(.type).opt.out ?= $(opt.out) ;
152    tool.$(name)$(.type).opt.define ?= $(opt.define) ;
153    tool.$(name)$(.type).flags ?= $(flags) ;
154    tool.$(name)$(.type).linklibs ?= $(linklibs) ;
155    if ! $(name) in $(toolsets) { toolsets += $(name) ; }
156}
157
158rule if-os ( os + : yes-opt * : no-opt * )
159    { if $(os) in $(OS) { return $(yes-opt) ; } else { return $(no-opt) ; } }
160
161rule opt ( type : yes-opt * : no-opt * )
162    { if $(type) in $(ARGV) { return $(yes-opt) ; } else { return $(no-opt) ; } }
163
164## HP-UX aCC compiler
165toolset acc cc : "-o " : -D
166    : -Ae
167    [ opt --release : -s -O3 ]
168    [ opt --debug : -g -pg ]
169    -I$(--python-include) -I$(--extra-include)
170    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
171## Borland C++ 5.5.x
172toolset borland bcc32 : -e -n : /D
173    : -WC -w- -q "-I$(toolset-root)Include" "-L$(toolset-root)Lib"
174    [ opt --release : -O2 -vi -w-inl ]
175    [ opt --debug : -v -Od -vi- ]
176    -I$(--python-include) -I$(--extra-include)
177    : $(--python-lib[1]) ;
178## Generic Unix cc
179if ! $(CC) { CC = cc ; }
180toolset cc $(CC) : "-o " : -D
181    : $(CFLAGS)
182    [ opt --release : -s -O ]
183    [ opt --debug : -g ]
184    -I$(--python-include) -I$(--extra-include)
185    : $(LIBS) -L$(--python-lib[1]) -l$(--python-lib[2]) ;
186## Comeau C/C++ 4.x
187toolset como como : "-o " : -D
188    : --c
189    [ opt --release : --inlining ]
190    [ opt --debug : --no_inlining ]
191    -I$(--python-include) -I$(--extra-include)
192    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
193## Clang Linux 2.8+
194toolset clang clang :  "-o " : -D
195    : -Wno-unused -Wno-format
196    [ opt --release : -Os ]
197    [ opt --debug : -g -O0 -fno-inline ]
198    [ opt --profile : -finline-functions -g ]
199    -I$(--python-include) -I$(--extra-include)
200    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
201## MacOSX Darwin, using GCC 2.9.x, 3.x
202toolset darwin cc :  "-o " : -D
203    :
204    [ opt --release : -Wl,-x -O3 -finline-functions ]
205    [ opt --debug : -g -O0 -fno-inline -pg ]
206    [ opt --profile : -Wl,-x -O3 -finline-functions -g -pg ]
207    -I$(--python-include) -I$(--extra-include)
208    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
209## GCC 2.x, 3.x, 4.x
210toolset gcc gcc : "-o " : -D
211    : -pedantic -fno-strict-aliasing
212    [ opt --release : [ opt --symbols : -g : -s ] -O3 ]
213    [ opt --debug : -g -O0 -fno-inline ]
214    [ opt --profile : -O3 -g -pg ]
215    -I$(--python-include) -I$(--extra-include) -Wno-long-long
216    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
217## GCC 2.x, 3.x on CYGWIN but without cygwin1.dll
218toolset gcc-nocygwin gcc : "-o " : -D
219    : -s -O3 -mno-cygwin
220    [ opt --release : -finline-functions ]
221    [ opt --debug : -s -O3 -fno-inline -pg ]
222    -I$(--python-include) -I$(--extra-include)
223    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
224## Intel C/C++ for Darwin
225toolset intel-darwin icc : "-o " : -D
226    :
227    [ opt --release : -O3 ]
228    [ opt --debug : -g -O0 -p ]
229    -I$(--python-include) -I$(--extra-include)
230    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
231## Intel C/C++ for Linux
232toolset intel-linux icc : "-o " : -D
233    :
234    [ opt --release : -Xlinker -s -O3 ]
235    [ opt --debug : -g -O0 -p ]
236    -I$(--python-include) -I$(--extra-include)
237    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
238## Intel C/C++ for Win32
239toolset intel-win32 icl : /Fe : -D
240    : /nologo
241    [ opt --release : /MT /O2 /Ob2 /Gy /GF /GA /GB ]
242    [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 ]
243    -I$(--python-include) -I$(--extra-include)
244    : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
245## KCC ?
246toolset kcc KCC : "-o " : -D
247    :
248    [ opt --release : -s +K2 ]
249    [ opt --debug : -g +K0 ]
250    -I$(--python-include) -I$(--extra-include)
251    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
252## Borland Kylix
253toolset kylix bc++ : -o : -D
254    : -tC -q
255    [ opt --release : -O2 -vi -w-inl ]
256    [ opt --debug : -v -Od -vi- ]
257    -I$(--python-include) -I$(--extra-include)
258    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
259## Metrowerks CodeWarrior 8.x
260{
261    # Even though CW can compile all files at once, it crashes if it tries in
262    # the bjam case.
263    local mwcc ; if $(OS) != NT { mwcc = mwc$(OSPLAT:L) ; }
264    mwcc ?= mwcc ;
265    toolset metrowerks $(mwcc) : "-o " : -D
266        : -c -lang c -subsystem console -cwd include
267        [ opt --release : -runtime ss -opt full -inline all ]
268        [ opt --debug : -runtime ssd -opt none -inline off ]
269        -I$(--python-include) -I$(--extra-include) ;
270    toolset metrowerks $(mwcc) .link : "-o " :
271        : -subsystem console -lkernel32.lib -ladvapi32.lib -luser32.lib
272        [ opt --release : -runtime ss ]
273        [ opt --debug : -runtime ssd ]
274        : $(--python-lib[1]) ;
275}
276## MINGW GCC
277toolset mingw gcc : "-o " : -D
278    :
279    [ opt --release : -s -O3 -finline-functions ]
280    [ opt --debug : -g -O0 -fno-inline -pg ]
281    -I$(--python-include) -I$(--extra-include)
282    : $(--python-lib[2]) ;
283## MIPS Pro
284toolset mipspro cc : "-o " : -D
285    :
286    [ opt --release : -s -O3 -g0 -INLINE:none ]
287    [ opt --debug : -g -O0 -INLINE ]
288    -I$(--python-include) -I$(--extra-include)
289    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
290## Microsoft Visual Studio C++ 6.x
291toolset msvc cl : /Fe /Fe /Fd /Fo : -D
292    : /nologo
293    [ opt --release : /ML /O2 /Ob2 /Gy /GF /GA /GB ]
294    [ opt --debug : /MLd /DEBUG /Z7 /Od /Ob0 ]
295    -I$(--python-include) -I$(--extra-include)
296    : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
297## QNX 6.x GCC 3.x/2.95.3
298toolset qcc qcc : "-o " : -D
299    : -Wc,-pedantic -Wc,-fno-strict-aliasing
300    [ opt --release : [ opt --symbols : -g ] -O3 -Wc,-finline-functions ]
301    [ opt --debug : -g -O0 -Wc,-fno-inline ]
302    -I$(--python-include) -I$(--extra-include)
303    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
304## Qlogic Pathscale 2.4
305toolset pathscale pathcc : "-o " : -D
306    :
307    [ opt --release : -s -Ofast -O3 ]
308    [ opt --debug : -g ]
309    -I$(--python-include) -I$(--extra-include)
310    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
311## Portland Group Pgi 6.2
312toolset pgi pgcc : "-o " : -D
313    :
314    [ opt --release : -s -O3 ]
315    [ opt --debug : -g ]
316    -I$(--python-include) -I$(--extra-include)
317    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
318## Sun Workshop 6 C++
319toolset sun cc : "-o " : -D
320    :
321    [ opt --release : -s -xO3 ]
322    [ opt --debug : -g ]
323    -I$(--python-include) -I$(--extra-include)
324    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
325## Sun Workshop 6 C++ (old alias)
326toolset sunpro cc : "-o " : -D
327    :
328    [ opt --release : -s -xO3 ]
329    [ opt --debug : -g ]
330    -I$(--python-include) -I$(--extra-include)
331    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
332## Compaq Alpha CXX
333toolset tru64cxx cc : "-o " : -D
334    :
335    [ opt --release : -s -O5 -inline speed ]
336    [ opt --debug : -g -O0 -pg ]
337    -I$(--python-include) -I$(--extra-include)
338    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
339## IBM VisualAge C++ or IBM XL C/C++ for Aix or IBM XL C/C++ for Linux (Big endian)
340toolset vacpp xlc : "-o " : -D
341    :
342    [ opt --release : -s -O3 -qstrict -qinline ]
343    [ opt --debug : -g -qNOOPTimize -qnoinline -pg ]
344    -I$(--python-include) -I$(--extra-include)
345    : -L$(--python-lib[1]) -l$(--python-lib[2]) [ if-os AIX : -bmaxdata:0x40000000 ] ;
346
347## IBM XL C/C++ for Linux (little endian)
348toolset xlcpp xlC :  "-o " : -D
349    : -Wno-unused -Wno-format
350    [ opt --release : -s  ]
351    [ opt --debug : -g -qNOOPTimize -qnoinline -pg ]
352    -I$(--python-include) -I$(--extra-include)
353    : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
354
355## Microsoft Visual C++ .NET 7.x
356toolset vc7 cl : /Fe /Fe /Fd /Fo : -D
357    : /nologo
358    [ opt --release : /ML /O2 /Ob2 /Gy /GF /GA /GB ]
359    [ opt --debug : /MLd /DEBUG /Z7 /Od /Ob0 ]
360    -I$(--python-include) -I$(--extra-include)
361    : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
362## Microsoft Visual C++ 2005
363toolset vc8 cl : /Fe /Fe /Fd /Fo : -D
364    : /nologo
365    [ opt --release : /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
366    [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
367    -I$(--python-include) -I$(--extra-include)
368    : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
369## Microsoft Visual C++ 2008
370toolset vc9 cl : /Fe /Fe /Fd /Fo : -D
371    : /nologo
372    [ opt --release : /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
373    [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
374    -I$(--python-include) -I$(--extra-include)
375    : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
376## Microsoft Visual C++ 2010
377toolset vc10 cl : /Fe /Fe /Fd /Fo : -D
378    : /nologo
379    [ opt --release : /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
380    [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
381    -I$(--python-include) -I$(--extra-include)
382    : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
383## Microsoft Visual C++ 2012
384toolset vc11 cl : /Fe /Fe /Fd /Fo : -D
385    : /nologo
386    [ opt --release : /GL /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
387    [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
388    -I$(--python-include) -I$(--extra-include)
389    : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
390## Microsoft Visual C++ 2013
391toolset vc12 cl : /Fe /Fe /Fd /Fo : -D
392    : /nologo
393    [ opt --release : /GL /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
394    [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
395    -I$(--python-include) -I$(--extra-include)
396    : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
397toolset vc14 cl : /Fe /Fe /Fd /Fo : -D
398    : /nologo
399    [ opt --release : /GL /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
400    [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
401    -I$(--python-include) -I$(--extra-include)
402    : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
403
404# First set the build commands and options according to the
405# preset toolset.
406toolset = [ MATCH --toolset=(.*) : $(ARGV) ] ;
407if ! $(toolset)
408{
409    # For some reason, the following test does not catch empty toolset.
410    ECHO "###" ;
411    ECHO "###" No toolset specified. Please use --toolset option. ;
412    ECHO "###" ;
413    ECHO "###" Known toolsets are: $(toolsets:J=", ") ;
414    EXIT "###" ;
415}
416if ! $(toolset) in $(toolsets)
417{
418    ECHO "###" ;
419    ECHO "###" Unknown toolset: $(toolset) ;
420    ECHO "###" ;
421    ECHO "###" Known toolsets are: $(toolsets:J=", ") ;
422    EXIT "###" ;
423}
424--cc = $(tool.$(toolset).cc) ;
425if $(tool.$(toolset).opt.out[2])
426{
427    if $(tool.$(toolset).opt.out[1]) = $(tool.$(toolset).opt.out[2])
428    {
429        --out = $(tool.$(toolset).opt.out[1]) ;
430        --dir = $(tool.$(toolset).opt.out[3-]) ;
431    }
432    else
433    {
434        --bin = $(tool.$(toolset).opt.out[1]) ;
435        --dir = $(tool.$(toolset).opt.out[2-]) ;
436    }
437}
438else
439{
440    --out = $(tool.$(toolset).opt.out) ;
441}
442--def = $(tool.$(toolset).opt.define) ;
443--flags = $(tool.$(toolset).flags) ;
444--defs = $(tool.$(toolset).defines) ;
445--libs = $(tool.$(toolset).linklibs) ;
446if $(tool.$(toolset).link.cc)
447{
448    --link = $(tool.$(toolset).link.cc) ;
449    if $(tool.$(toolset).link.opt.out[2])
450    {
451        if $(tool.$(toolset).link.opt.out[1]) = $(tool.$(toolset).link.opt.out[2])
452        {
453            --link-out = $(tool.$(toolset).link.opt.out[1]) ;
454            --link-dir = $(tool.$(toolset).link.opt.out[3-]) ;
455        }
456        else
457        {
458            --link-bin = $(tool.$(toolset).link.opt.out[1]) ;
459            --link-dir = $(tool.$(toolset).link.opt.out[2-]) ;
460        }
461    }
462    else
463    {
464        --link-out = $(tool.$(toolset).link.opt.out) ;
465    }
466    --link-def = $(tool.$(toolset).link.opt.define) ;
467    --link-flags = $(tool.$(toolset).link.flags) ;
468    --link-defs = $(tool.$(toolset).link.defines) ;
469    --link-libs = $(tool.$(toolset).link.linklibs) ;
470}
471
472# Put executables in platform-specific subdirectory.
473locate-target = $(LOCATE_TARGET) ;
474if $(OSPLAT)
475{
476    locate-target ?= bin$(.)$(OS:L)$(OSPLAT:L) ;
477    platform = $(OS:L)$(OSPLAT:L) ;
478}
479else
480{
481    locate-target ?= bin$(.)$(OS:L) ;
482    platform = $(OS:L) ;
483}
484if $(debug)
485{
486    locate-target = [ .path $(locate-target)$(.)debug ] ;
487}
488if $(profile)
489{
490    locate-target = [ .path $(locate-target)$(.)profile ] ;
491}
492else
493{
494    locate-target = [ .path $(locate-target) ] ;
495}
496
497if --show-locate-target in $(ARGV)
498{
499    ECHO $(locate-target) ;
500}
501
502# We have some different files for UNIX, and NT.
503jam.source =
504    command.c compile.c constants.c debug.c execcmd.c frames.c function.c glob.c
505    hash.c hcache.c headers.c hdrmacro.c jam.c jambase.c jamgram.c lists.c
506    make.c make1.c mem.c object.c option.c output.c parse.c pathsys.c regexp.c
507    rules.c scan.c search.c subst.c w32_getreg.c timestamp.c variable.c
508    modules.c strings.c filesys.c builtins.c class.c cwd.c native.c md5.c
509    [ .path modules set.c ] [ .path modules path.c ] [ .path modules regex.c ]
510    [ .path modules property-set.c ] [ .path modules sequence.c ] [ .path modules order.c ] ;
511if $(OS) = NT
512{
513    jam.source += execnt.c filent.c pathnt.c ;
514}
515else
516{
517    jam.source += execunix.c fileunix.c pathunix.c ;
518}
519
520# Debug assertions, or not.
521if ! $(debug) || --noassert in $(ARGV)
522{
523    --defs += NDEBUG ;
524}
525
526# Enable some optional features.
527--defs += OPT_HEADER_CACHE_EXT ;
528--defs += OPT_GRAPH_DEBUG_EXT ;
529--defs += OPT_SEMAPHORE ;
530--defs += OPT_AT_FILES ;
531--defs += OPT_DEBUG_PROFILE ;
532
533# Bug fixes
534--defs += OPT_FIX_TARGET_VARIABLES_EXT ;
535#~ --defs += OPT_NO_EXTERNAL_VARIABLE_SPLIT ;
536
537# Improvements
538--defs += OPT_IMPROVED_PATIENCE_EXT ;
539
540# Use Boehm GC memory allocator?
541if $(--boehm-gc)
542{
543    --defs += OPT_BOEHM_GC ;
544    if $(debug)
545    {
546        --defs += GC_DEBUG ;
547    }
548}
549
550if $(--duma)
551{
552    --defs += OPT_DUMA ;
553}
554
555if ( $(OS) = NT ) && ! NT in $(--defs)
556{
557    --defs += NT ;
558}
559--defs += YYSTACKSIZE=5000 ;
560
561if $(with-python)
562{
563    --defs += HAVE_PYTHON ;
564}
565
566if $(debug)
567{
568    --defs += BJAM_NEWSTR_NO_ALLOCATE ;
569}
570
571
572# The basic symbolic targets...
573NOTFILE all clean dist ;
574ALWAYS clean ;
575
576# Utility rules and actions...
577rule .clean
578{
579    [DELETE] clean : $(<) ;
580}
581if $(OS) = NT { actions piecemeal together existing [DELETE] {
582    del /F /Q "$(>)"
583} }
584if $(UNIX) = true { actions piecemeal together existing [DELETE] {
585    rm -f "$(>)"
586} }
587if $(OS) = NT {
588    --chmod+w = "attrib -r " ;
589}
590if $(UNIX) = true {
591    --chmod+w = "chmod +w " ;
592}
593
594rule .mkdir
595{
596    NOUPDATE $(<) ;
597    if $(<:P) { DEPENDS $(<) : $(<:P) ; .mkdir $(<:P) ; }
598    if ! $(md<$(<)>) { [MKDIR] $(<) ; md<$(<)> = - ; }
599}
600if $(OS) = NT { actions [MKDIR] {
601    md "$(<)"
602} }
603if $(UNIX) = true { actions [MKDIR] {
604    mkdir "$(<)"
605} }
606
607rule .exe
608{
609    local exe = $(<) ;
610    if $(OS) = NT || ( $(UNIX) = true && $(OS) = CYGWIN ) { exe = $(exe:S=.exe) ; }
611    LOCATE on $(exe) = $(locate-target) ;
612    DEPENDS all : $(exe) ;
613    .mkdir $(locate-target) ;
614    if $(--link)
615    {
616        local objs ;
617        for local s in $(>)
618        {
619            # Translate any subdir elements into a simple file name.
620            local o = [ MATCH "([^/]+)[/]?(.+)" : $(s) ] ;
621            o = $(o:J=_) ;
622            o = $(o:S=.o) ;
623            objs += $(o) ;
624            LOCATE on $(o) = $(locate-target) ;
625            DEPENDS $(exe) : $(o) ;
626            DEPENDS $(o) : $(s) ;
627            DEPENDS $(o) : $(locate-target) ;
628            [COMPILE] $(o) : $(s) ;
629            .clean $(o) ;
630        }
631        DEPENDS $(exe) : $(objs) ;
632        DEPENDS $(exe) : $(locate-target) ;
633        [COMPILE.LINK] $(exe) : $(objs) ;
634        .clean $(exe) ;
635    }
636    else
637    {
638        DEPENDS $(exe) : $(>) ;
639        DEPENDS $(exe) : $(locate-target) ;
640        [COMPILE] $(exe) : $(>) ;
641        .clean $(exe) ;
642    }
643    return $(exe) ;
644}
645if ! $(--def[2]) { actions [COMPILE] {
646    "$(--cc)" "$(--bin)$(<:D=)" "$(--dir)$(<:D)$(./)" $(--out)$(<) "$(--def)$(--defs)" "$(--flags)" "$(>)" "$(--libs)"
647} }
648else { actions [COMPILE] {
649    "$(--cc)" "$(--bin)$(<:D=)" "$(--dir)$(<:D)$(./)" $(--out)$(<) "$(--def[1])$(--defs:J=$(--def[2]))$(--def[3])" "$(--flags)"  "$(>)" "$(--libs)"
650} }
651
652actions [COMPILE.LINK] {
653    "$(--link)" "$(--link-bin)$(<:D=)" "$(--link-dir)$(<:D)$(./)" "$(--link-out)$(<)" "$(--link-def)$(--link-defs)" "$(--link-flags)"  "$(>)" "$(--link-libs)"
654}
655
656rule .link
657{
658    DEPENDS all : $(<) ;
659    DEPENDS $(<) : $(>) ;
660    [LINK] $(<) : $(>) ;
661    .clean $(<) ;
662}
663if $(OS) = NT { actions [LINK] {
664    copy "$(>)" "$(<)"
665} }
666if $(UNIX) = true { actions [LINK] {
667    ln -fs "$(>)" "$(<)"
668} }
669
670rule .copy
671{
672    DEPENDS all : $(<) ;
673    DEPENDS $(<) : $(>) ;
674    [COPY] $(<) : $(>) ;
675    .clean $(<) ;
676}
677
678# Will be redefined later.
679actions [COPY]
680{
681}
682
683
684rule .move
685{
686    DEPENDS $(<) : $(>) ;
687    [MOVE] $(<) : $(>) ;
688}
689if $(OS) = NT { actions [MOVE] {
690    del /f "$(<)"
691    rename "$(>)" "$(<)"
692} }
693if $(UNIX) = true { actions [MOVE] {
694    mv -f "$(>)" "$(<)"
695} }
696
697# Generate the grammar tokens table, and the real yacc grammar.
698rule .yyacc
699{
700    local exe = [ .exe yyacc : yyacc.c ] ;
701    NOUPDATE $(exe) ;
702    DEPENDS $(<) : $(exe) $(>) ;
703    LEAVES $(<) ;
704    yyacc.exe on $(<) = $(exe:R=$(locate-target)) ;
705    [YYACC] $(<) : $(>) ;
706}
707actions [YYACC] {
708    $(--chmod+w)$(<[1])
709    $(--chmod+w)$(<[2])
710    "$(yyacc.exe)" "$(<)" "$(>)"
711}
712if $(grammar)
713{
714    .yyacc jamgram.y jamgramtab.h : jamgram.yy ;
715}
716else if $(debug)
717{
718    .exe yyacc : yyacc.c ;
719}
720
721# How to build the grammar.
722if $(OS) = NT
723{
724    SUFEXE = .exe ;
725    # try some other likely spellings...
726    PATH ?= $(Path) ;
727    PATH ?= $(path) ;
728}
729SUFEXE ?= "" ;
730
731yacc ?= [ GLOB $(PATH) : yacc$(SUFEXE) ] ;
732yacc ?= [ GLOB $(PATH) : bison$(SUFEXE) ] ;
733yacc ?= [ GLOB "$(ProgramFiles:J= )\\GnuWin32\\bin"
734    "C:\\Program Files\\GnuWin32\\bin" : bison$(SUFEXE) ] ;
735yacc = $(yacc[1]) ;
736switch $(yacc:D=:S=)
737{
738    case bison : yacc += -d --yacc ;
739    case yacc  : yacc += -d ;
740}
741if $(debug) && $(yacc)
742{
743    yacc += -t -v ;
744}
745yacc += $(YACCFLAGS) ;
746
747rule .yacc
748{
749    DEPENDS $(<) : $(>) ;
750    LEAVES $(<) ;
751    [YACC] $(<) : $(>) ;
752}
753if $(OS) = NT { actions [YACC] {
754    "$(yacc)" "$(>)"
755    if not errorlevel 1 (
756        del /f "$(<[1])"
757        rename y.tab$(<[1]:S) "$(<[1])"
758        del /f $(<[2])
759        rename y.tab$(<[2]:S) "$(<[2])"
760    ) else set _error_ =
761} }
762if $(UNIX) = true { actions [YACC] {
763    if ` "$(yacc)" "$(>)" ` ; then
764        mv -f y.tab$(<[1]:S) "$(<[1])"
765        mv -f y.tab$(<[2]:S) "$(<[2])"
766    else
767        exit 1
768    fi
769} }
770if $(grammar) && ! $(yacc)
771{
772    EXIT Could not find the 'yacc' tool, and therefore can not build the
773        grammar. ;
774}
775if $(grammar) && $(yacc)
776{
777    .yacc jamgram.c jamgram.h : jamgram.y ;
778}
779
780# How to build the compiled in jambase.
781rule .mkjambase
782{
783    local exe = [ .exe mkjambase : mkjambase.c ] ;
784    DEPENDS $(<) : $(exe) $(>) ;
785    LEAVES $(<) ;
786    mkjambase.exe on $(<) = $(exe:R=$(locate-target)) ;
787    [MKJAMBASE] $(<) : $(>) ;
788}
789actions [MKJAMBASE] {
790    $(--chmod+w)$(<)
791    $(mkjambase.exe) "$(<)" "$(>)"
792}
793if $(debug)
794{
795    .mkjambase jambase.c : Jambase ;
796}
797
798# How to build Jam.
799rule .jam
800{
801    $(>).exe = [ .exe $(>) : $(jam.source) ] ;
802    DEPENDS all : $($(>).exe) ;
803
804    # Make a copy under the old name.
805    $(<).exe = $(<:S=$($(>).exe:S)) ;
806    LOCATE on $($(<).exe) = $(locate-target) ;
807    .copy $($(<).exe) : $($(>).exe) ;
808    DEPENDS all : $($(<).exe) ;
809}
810.jam bjam : b2 ;
811
812
813# Scan sources for header dependencies.
814#
815# In order to keep things simple, we made a slight compromise here - we only
816# detect changes in headers included relative to the current folder as opposed
817# to those included from somewhere on the include path.
818rule .scan ( targets + )
819{
820    HDRRULE on $(targets) = .hdr.scan ;
821    HDRSCAN on $(targets) = "^[ \t]*#[ \t]*include[ \t]*\"([^\"]*)\".*$" ;
822}
823rule .hdr.scan ( target : includes * : binding )
824{
825    local target-path = [ NORMALIZE_PATH $(binding:D) ] ;
826    # Extra grist provides target name uniqueness when referencing same name
827    # header files from different folders.
828    local include-targets = <$(target-path)>$(includes) ;
829    NOCARE $(include-targets) ;
830    INCLUDES $(target) : $(include-targets) ;
831    SEARCH on $(include-targets) = $(target-path) ;
832    ISFILE $(include-targets) ;
833    .scan $(include-targets) ;
834}
835.scan $(jam.source) ;
836
837
838# Distribution making from here on out. Assumes that the docs are already built
839# as HTML at ../doc/html. Otherwise they will not be included in the built
840# distribution archive.
841dist.license =
842    [ GLOB . : $(LICENSE).txt ]
843    ;
844dist.license = $(dist.license:D=)
845    [ GLOB [ .path .. .. .. ] : $(LICENSE).txt ]
846    [ GLOB [ .path .. boost ] : $(LICENSE).txt ] ;
847dist.docs =
848    [ GLOB . : *.png *.css *.html ]
849    ;
850dist.docs = $(dist.docs:D=)
851    [ GLOB [ .path images ] : *.png ]
852    [ GLOB [ .path jam ] : *.html ]
853    ;
854dist.source =
855    [ GLOB . : *.c *.h ]
856    ;
857dist.source = $(dist.source:D=)
858    $(dist.license[1])
859    $(dist.docs)
860    build.jam build.bat build.sh
861    Jambase
862    jamgram.y jamgram.yy
863    [ .path modules set.c ]
864    [ .path modules path.c ]
865    [ .path modules regex.c ]
866    [ .path modules property-set.c ]
867    [ .path modules sequence.c ]
868    [ .path modules order.c ]
869    [ GLOB [ .path boehm_gc ] : * ]
870    [ GLOB [ .path boehm_gc include ] : * ]
871    [ GLOB [ .path boehm_gc include private ] : * ]
872    [ GLOB [ .path boehm_gc cord ] : * ]
873    [ GLOB [ .path boehm_gc Mac_files ] : * ]
874    [ GLOB [ .path boehm_gc tests ] : * ]
875    [ GLOB [ .path boehm_gc doc ] : * ]
876    ;
877dist.bin =
878    bjam
879    ;
880dist.bin =
881    $(dist.license[1])
882    $(dist.bin:S=$(bjam.exe:S))
883    ;
884
885if $(OS) = NT
886{
887    zip ?= [ GLOB "$(ProgramFiles:J= )\\7-ZIP" "C:\\Program Files\\7-ZIP" : "7z.exe" ] ;
888    zip ?= [ GLOB "$(ProgramFiles:J= )\\7-ZIP" "C:\\Program Files\\7-ZIP" : "7zn.exe" ] ;
889    zip ?= [ GLOB $(PATH) : zip.exe ] ;
890    zip ?= zip ;
891    zip = $(zip[1]) ;
892    switch $(zip:D=:S=)
893    {
894        case 7z* : zip += a -r -tzip -mx=9 ;
895        case zip : zip += -9r ;
896    }
897    actions piecemeal [PACK] {
898        "$(zip)" "$(<)" "$(>)"
899    }
900    actions piecemeal [ZIP] {
901        "$(zip)" "$(<)" "$(>)"
902    }
903    actions piecemeal [COPY] {
904        copy /Y "$(>)" "$(<)" >NUL:
905    }
906}
907if $(UNIX) = true
908{
909    tar ?= [ GLOB $(PATH) : star bsdtar tar ] ;
910    tar = $(tar[1]) ;
911    switch $(tar:D=:S=)
912    {
913        case star : tar += -c artype=pax -D -d -to-stdout ;
914        case * : tar += -c -f - ;
915    }
916    actions [PACK] {
917        "$(tar)" "$(>)" | gzip -c9 > "$(<)"
918    }
919    #~ actions [PACK] {
920    #~     tar cf "$(<:S=.tar)" "$(>)"
921    #~ }
922    actions [ZIP] {
923    gzip -c9 "$(>)" > "$(<)"
924    }
925    actions [COPY] {
926        cp -Rpf "$(>)" "$(<)"
927    }
928}
929
930# The single binary, compressed.
931rule .binary
932{
933    local zip ;
934    if $(OS) = NT { zip = $($(<).exe:S=.zip) ; }
935    if $(UNIX) = true { zip = $($(<).exe:S=.tgz) ; }
936    zip = $(zip:S=)-$(VERSION)-$(RELEASE)-$(platform)$(zip:S) ;
937    DEPENDS $(zip) : $($(<).exe) ;
938    DEPENDS dist : $(zip) ;
939    #~ LOCATE on $(zip) = $(locate-target) ;
940    if $(OS) = NT { [ZIP] $(zip) : $($(<).exe) ; }
941    if $(UNIX) = true { [PACK] $(zip) : $($(<).exe) ; }
942    .clean $(zip) ;
943}
944
945# Package some file.
946rule .package ( dst-dir : src-files + )
947{
948    local dst-files ;
949    local src-files-actual ;
950    for local src-path in $(src-files)
951    {
952        if ! [ GLOB $(src-path:P) : $(src-path:B) ] || [ CHECK_IF_FILE $(src-path) ]
953        {
954            local src-subdir = $(src-path:D) ;
955            local src-file = $(src-path) ;
956            while $(src-subdir:D) { src-subdir = $(src-subdir:D) ; }
957            if $(src-subdir) = ".."
958            {
959                src-file = $(src-file:D=) ;
960            }
961            dst-files += $(src-file:R=$(dst-dir)) ;
962            src-files-actual += $(src-path) ;
963        }
964    }
965
966    local pack ;
967    if $(OS) = NT { pack = $(dst-dir).zip ; }
968    if $(UNIX) = true { pack = $(dst-dir).tgz ; }
969
970    DEPENDS dist : $(pack) ;
971    DEPENDS $(pack) : $(dst-files) ;
972
973    local dst-files-queue = $(dst-files) ;
974    for local src-path in $(src-files-actual)
975    {
976        local dst-file = $(dst-files-queue[1]) ;
977        dst-files-queue = $(dst-files-queue[2-]) ;
978        DEPENDS $(dst-file) : $(src-path) $(dst-file:D) ;
979        .mkdir $(dst-file:D) ;
980
981        [COPY] $(dst-file) : $(src-path) ;
982        .clean $(dst-file) ;
983    }
984
985    [PACK] $(pack) : $(dst-files) ;
986    .clean $(pack) ;
987}
988
989# RPM distro file.
990rpm-tool = [ GLOB $(PATH) : "rpmbuild" ] ;
991rpm-tool ?= [ GLOB $(PATH) : "rpm" ] ;
992rpm-tool = $(rpm-tool[1]) ;
993rule .rpm ( name : source )
994{
995    local rpm-arch ;
996    switch $(OSPLAT)
997    {
998        case X86       : rpm-arch ?= i386 ;
999        case PPC       : rpm-arch ?= ppc ;
1000        case AXP       : rpm-arch ?= alpha ;
1001        # no guaranty for these:
1002        case IA64      : rpm-arch ?= ia64 ;
1003        case ARM       : rpm-arch ?= arm ;
1004        case SPARC     : rpm-arch ?= sparc ;
1005        case *         : rpm-arch ?= other ;
1006    }
1007    local target = $(name)-rpm ;
1008    NOTFILE $(target) ;
1009    DEPENDS dist : $(target) ;
1010    DEPENDS $(target) : $(name).$(rpm-arch).rpm $(name).src.rpm ;
1011    DEPENDS $(name).$(rpm-arch).rpm : $(source) ;
1012    DEPENDS $(name).src.rpm : $(name).$(rpm-arch).rpm ;
1013    docs on $(target) = $(dist.docs:J=" ") ;
1014    arch on $(target) = $(rpm-arch) ;
1015    if $(rpm-arch) = ppc { target-opt on $(target) = --target= ; }
1016    else { target-opt on $(target) = "--target " ; }
1017    [RPM] $(target) : $(source) ;
1018    .clean $(name).$(rpm-arch).rpm $(name).src.rpm ;
1019}
1020actions [RPM] {
1021    set -e
1022    export BOOST_JAM_TOOLSET="$(toolset)"
1023    $(rpm-tool) -ta $(target-opt)$(arch) $(>) | tee rpm.out
1024    cp `grep -e '^Wrote:' rpm.out | sed 's/^Wrote: //'` .
1025    rm -f rpm.out
1026}
1027
1028# The distribution targets. Do not bother with them unless this is a
1029# distribution build.
1030if dist in $(ARGV)
1031{
1032    #~ .binary bjam ;
1033    .package $(NAME)-$(VERSION) : $(dist.source) ;
1034    .package $(NAME)-$(VERSION)-$(RELEASE)-$(platform) : $(dist.bin) ;
1035    if $(rpm-tool)
1036    {
1037        #~ .rpm $(NAME)-$(VERSION)-$(RELEASE) : $(NAME)-$(VERSION).tgz ;
1038    }
1039}
1040