1#!/bin/sh
2
3#~ Copyright 2002-2019 Rene Rivera.
4#~ Distributed under the Boost Software License, Version 1.0.
5#~ (See accompanying file LICENSE_1_0.txt or copy at
6#~ http://www.boost.org/LICENSE_1_0.txt)
7
8# Reset the toolset.
9B2_TOOLSET=
10B2_OS=
11
12# Run a command, and echo before doing so. Also checks the exit status and quits
13# if there was an error.
14echo_run ()
15{
16    echo "> $@"
17    $@
18    r=$?
19    if test $r -ne 0 ; then
20        exit $r
21    fi
22}
23
24# Print an error message, and exit with a status of 1.
25error_exit ()
26{
27    echo "
28${@}
29
30You can specify the toolset as the argument, i.e.:
31    ./build.sh gcc
32
33Toolsets supported by this script are:
34    acc, clang, como, gcc, intel-darwin, intel-linux, kcc, kylix, mipspro,
35    pathscale, pgi, qcc, sun, sunpro, tru64cxx, vacpp
36
37For any toolset you can override the path to the compiler with the CXX
38environment variable. You can also use additional flags for the compiler
39with the CXXFLAGS environment variable.
40
41A special toolset; cxx, is available which is used as a fallback when a more
42specific toolset is not found and the cxx command is detected. The 'cxx'
43toolset will use the CXX, CXXFLAGS, and LIBS environment variables, if present.
44
45Similarly, the cross-cxx toolset is available for cross-compiling by using the
46BUILD_CXX, BUILD_CXXFLAGS, and BUILD_LDFLAGS environment variables to compile
47binaries that will be executed on the build system. This allows CXX etc. to be
48set for cross-compilers to be propagated to subprocesses.
49" 1>&2
50    exit 1
51}
52
53# Check that a command is in the PATH.
54test_path ()
55{
56    if `command -v command 1>/dev/null 2>/dev/null`; then
57        command -v $1 1>/dev/null 2>/dev/null
58    else
59        hash $1 1>/dev/null 2>/dev/null
60    fi
61}
62
63# Check that the OS name, as returned by "uname", is as given.
64test_uname ()
65{
66    if test_path uname; then
67        test `uname` = $*
68    fi
69}
70
71# Check that the given command runs.
72test_exec ()
73{
74    "$*" 1>/dev/null 2>/dev/null
75}
76
77# Check that the compiler can do C++11.
78test_cxx11 ()
79{
80    if ! test $NO_CXX11_CHECK ; then
81        case $1 in
82            gcc) ( ${CXX:=g++} -x c++ -std=c++11 check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
83            intel-darwin) ( ${CXX:=icc} -xc++ check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
84            intel-linux) ( ${CXX:=icc} -xc++ check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
85            vacpp) ( ${CXX:=xlC_r} check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
86            xlcpp) ( ${CXX:=xlC_r} check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
87            como) ( ${CXX:=como} check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
88            kcc) ( ${CXX:=KCC} check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
89            kylix) ( ${CXX:=bc++} -tC -q check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
90            mipspro) ( ${CXX:=CC} -FE:template_in_elf_section -ptused check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
91            pathscale) ( ${CXX:=pathCC} check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
92            pgi) ( ${CXX:=pgc++} -std=c++11 check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
93            sun*) ( ${CXX:=CC} -std=c++11 check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
94            clang*) ( ${CXX:=clang++} -x c++ -std=c++11 check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
95            tru64cxx) ( ${CXX:=cc} check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
96            acc) ( ${CXX:=aCC} -AA check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
97            qcc) ( ${CXX:=QCC} check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
98            cxx) ( ${CXX:=cxx} check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
99            cross-cxx) ( ${CXX:=cxx} check_cxx11.cpp && rm -f a.out ) 1>/dev/null 2>/dev/null ;;
100            *) test "0" = "1" ;;
101        esac
102    else
103        test $NO_CXX11_CHECK
104    fi
105}
106
107# Try and guess the toolset to bootstrap the build with...
108guess_toolset ()
109{
110    if test_uname Darwin && test_cxx11 clang ; then B2_TOOLSET=clang
111    elif test_uname IRIX && test_cxx11 mipspro ; then B2_TOOLSET=mipspro
112    elif test_uname IRIX64 && test_cxx11 mipspro ; then B2_TOOLSET=mipspro
113    elif test_uname OSF1 && test_cxx11 tru64cxx ; then B2_TOOLSET=tru64cxx
114    elif test_uname QNX && test_path QCC && test_cxx11 qcc ; then B2_TOOLSET=qcc
115    elif test_uname Linux && test_path xlC_r ; then
116       if /usr/bin/lscpu | grep Byte | grep Little > /dev/null 2>&1 ; then
117          # Little endian linux
118          B2_TOOLSET=xlcpp
119       else
120          #Big endian linux
121          B2_TOOLSET=vacpp
122       fi
123    elif test_uname AIX && test_path xlC_r && test_cxx11 vacpp ; then B2_TOOLSET=vacpp
124    elif test_uname FreeBSD && test_path freebsd-version && test_path clang++ && test_cxx11 clang ; then B2_TOOLSET=clang
125    elif test_path g++ && test_cxx11 gcc ; then B2_TOOLSET=gcc
126    elif test_path clang++ && test_cxx11 clang ; then B2_TOOLSET=clang
127    elif test_path icc && test_cxx11 intel-linux ; then B2_TOOLSET=intel-linux
128    elif test -r /opt/intel/cc/9.0/bin/iccvars.sh && test_cxx11 intel-linux ; then
129        B2_TOOLSET=intel-linux
130        B2_TOOLSET_ROOT=/opt/intel/cc/9.0
131    elif test -r /opt/intel_cc_80/bin/iccvars.sh && test_cxx11 intel-linux ; then
132        B2_TOOLSET=intel-linux
133        B2_TOOLSET_ROOT=/opt/intel_cc_80
134    elif test -r /opt/intel/compiler70/ia32/bin/iccvars.sh && test_cxx11 intel-linux ; then
135        B2_TOOLSET=intel-linux
136        B2_TOOLSET_ROOT=/opt/intel/compiler70/ia32/
137    elif test -r /opt/intel/compiler60/ia32/bin/iccvars.sh && test_cxx11 intel-linux ; then
138        B2_TOOLSET=intel-linux
139        B2_TOOLSET_ROOT=/opt/intel/compiler60/ia32/
140    elif test -r /opt/intel/compiler50/ia32/bin/iccvars.sh && test_cxx11 intel-linux ; then
141        B2_TOOLSET=intel-linux
142        B2_TOOLSET_ROOT=/opt/intel/compiler50/ia32/
143    elif test_path pgc++ && test_cxx11 pgi ; then B2_TOOLSET=pgi
144    elif test_path pathCC && test_cxx11 pathscale ; then B2_TOOLSET=pathscale
145    elif test_path como && test_cxx11 como ; then B2_TOOLSET=como
146    elif test_path KCC && test_cxx11 kcc ; then B2_TOOLSET=kcc
147    elif test_path bc++ && test_cxx11 kylix ; then B2_TOOLSET=kylix
148    elif test_path aCC && test_cxx11 acc ; then B2_TOOLSET=acc
149    elif test_uname HP-UX ; then B2_TOOLSET=acc
150    elif test -r /opt/SUNWspro/bin/cc && test_cxx11 sunpro ; then
151        B2_TOOLSET=sunpro
152        B2_TOOLSET_ROOT=/opt/SUNWspro/
153    # Test for some common compile command as the default fallback.
154    elif test_path $CXX ; then B2_TOOLSET=cxx
155    elif test_path cxx ; then
156        B2_TOOLSET=cxx
157        CXX=cxx
158    elif test_path cpp ; then
159        B2_TOOLSET=cxx
160        CXX=cpp
161    elif test_path CC ; then
162        B2_TOOLSET=cxx
163        CXX=CC
164    fi
165    if test "$B2_TOOLSET" = "" ; then
166        error_exit "Could not find a suitable toolset."
167    fi
168}
169
170check_debug_build ()
171{
172    while test $# -gt 0
173    do
174        case "$1" in
175            --debug) return 0 ;;
176        esac
177        shift
178    done
179    return 1
180}
181
182# The one option we support in the invocation
183# is the name of the toolset to force building
184# with.
185case "$1" in
186    --guess-toolset) NO_CXX11_CHECK=1 ; guess_toolset ; echo "$B2_TOOLSET" ; exit 1 ;;
187    -*) guess_toolset ;;
188    ?*) B2_TOOLSET=$1 ; shift ;;
189    *) guess_toolset ;;
190esac
191
192# We need a C++11 compiler. Check here and given some feedback about it.
193if ! test_cxx11 $B2_TOOLSET ; then
194    error_exit "
195A C++11 capable compiler is required for building the B2 engine.
196Toolset '$B2_TOOLSET' does not appear to support C++11.
197
198** Note, the C++11 capable compiler is _only_ required for building the B2
199** engine. The B2 build system allows for using any C++ level and any other
200** supported language and resource in your projects.
201"
202fi
203
204case $B2_TOOLSET in
205
206    gcc)
207        CXX=${CXX:=g++}
208        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
209        # Check whether it's MinGW GCC, which has Windows headers and none of POSIX ones.
210        machine=$(${CXX} -dumpmachine 2>/dev/null)
211        if test $? -ne 0 ; then
212            echo "B2_TOOLSET is gcc, but the 'gcc' command cannot be executed."
213            echo "Make sure 'gcc' is in PATH, or use a different toolset."
214            exit 1
215        fi
216        case $machine in
217        *mingw*)
218        # MinGW insists that its bin directory be in PATH.
219        if test -r ${B2_TOOLSET_ROOT}bin/gcc ; then
220            export PATH=${B2_TOOLSET_ROOT}bin:$PATH
221        fi
222        B2_CXX="${CXX} -x c++ -std=c++11"
223        B2_CXXFLAGS_RELEASE="-O2 -s"
224        B2_CXXFLAGS_DEBUG="-O0 -g"
225        B2_OS="NT"
226        ;;
227
228        *cygwin*)
229        B2_CXX="${CXX} -x c++ -std=gnu++11"
230        B2_CXXFLAGS_RELEASE="-O2 -s"
231        B2_CXXFLAGS_DEBUG="-O0 -g"
232        ;;
233
234        *)
235        B2_CXX="${CXX} -x c++ -std=c++11"
236        B2_CXXFLAGS_RELEASE="-O2 -s"
237        B2_CXXFLAGS_DEBUG="-O0 -g"
238        esac
239    ;;
240
241    intel-darwin)
242        CXX=${CXX:=icc}
243        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
244        B2_CXX="${CXX} -xc++"
245        B2_CXXFLAGS_RELEASE="-O3 -s"
246        B2_CXXFLAGS_DEBUG="-O0 -g -p"
247    ;;
248
249    intel-linux)
250        CXX=${CXX:=icc}
251        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
252        test_path ${CXX} >/dev/null 2>&1
253        if test $? ; then
254            echo "Found ${CXX} in environment"
255            B2_TOOLSET_ROOT=`echo ${CXX}| sed -e 's/bin.*\/icc//'`
256            # probably the most widespread
257            ARCH=intel64
258        else
259            echo "No intel compiler in current path"
260            echo "Look in a few old place for legacy reason"
261            if test -r /opt/intel/cc/9.0/bin/iccvars.sh ; then
262                B2_TOOLSET_ROOT=/opt/intel/cc/9.0/
263            elif test -r /opt/intel_cc_80/bin/iccvars.sh ; then
264                B2_TOOLSET_ROOT=/opt/intel_cc_80/
265            elif test -r /opt/intel/compiler70/ia32/bin/iccvars.sh ; then
266                B2_TOOLSET_ROOT=/opt/intel/compiler70/ia32/
267            elif test -r /opt/intel/compiler60/ia32/bin/iccvars.sh ; then
268                B2_TOOLSET_ROOT=/opt/intel/compiler60/ia32/
269            elif test -r /opt/intel/compiler50/ia32/bin/iccvars.sh ; then
270                B2_TOOLSET_ROOT=/opt/intel/compiler50/ia32/
271            fi
272        fi
273        if test -r ${B2_TOOLSET_ROOT}bin/iccvars.sh ; then
274            # iccvars does not change LD_RUN_PATH. We adjust LD_RUN_PATH here in
275            # order not to have to rely on ld.so.conf knowing the icc library
276            # directory. We do this before running iccvars.sh in order to allow a
277            # user to add modifications to LD_RUN_PATH in iccvars.sh.
278            if test -z "${LD_RUN_PATH}"; then
279                LD_RUN_PATH="${B2_TOOLSET_ROOT}lib"
280            else
281                LD_RUN_PATH="${B2_TOOLSET_ROOT}lib:${LD_RUN_PATH}"
282            fi
283            export LD_RUN_PATH
284            . ${B2_TOOLSET_ROOT}bin/iccvars.sh $ARCH
285        fi
286        B2_CXX="${CXX} -xc++"
287        B2_CXXFLAGS_RELEASE="-O3 -s"
288        B2_CXXFLAGS_DEBUG="-O0 -g -p"
289    ;;
290
291    vacpp)
292        CXX=${CXX:=xlC_r}
293        CXX_VERSION_OPT=${CXX_VERSION_OPT:=-qversion}
294        B2_CXX="${CXX}"
295        B2_CXXFLAGS_RELEASE="-O3 -s -qstrict -qinline"
296        B2_CXXFLAGS_DEBUG="-g -qNOOPTimize -qnoinline -pg"
297    ;;
298
299    xlcpp)
300        CXX=${CXX:=xlC_r}
301        CXX_VERSION_OPT=${CXX_VERSION_OPT:=-qversion}
302        B2_CXX="${CXX}"
303        B2_CXXFLAGS_RELEASE="-s -O3 -qstrict -qinline"
304        B2_CXXFLAGS_DEBUG="-g -qNOOPTimize -qnoinline -pg"
305    ;;
306
307    como)
308        CXX=${CXX:=como}
309        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
310        B2_CXX="${CXX}"
311        B2_CXXFLAGS_RELEASE="-O3 --inlining"
312        B2_CXXFLAGS_DEBUG="-O0 -g --no_inlining --long_long"
313    ;;
314
315    kcc)
316        CXX=${CXX:=KCC}
317        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
318        B2_CXX="KCC"
319        B2_CXXFLAGS_RELEASE="+K2 -s"
320        B2_CXXFLAGS_DEBUG="+K0 -g"
321    ;;
322
323    kylix)
324        CXX=${CXX:=bc++}
325        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
326        B2_CXX="bc++ -tC -q"
327        B2_CXXFLAGS_RELEASE="-O2 -vi -w-inl -s"
328        B2_CXXFLAGS_DEBUG="-Od -v -vi-"
329    ;;
330
331    mipspro)
332        CXX=${CXX:=CC}
333        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
334        B2_CXX="${CXX} -FE:template_in_elf_section -ptused"
335        B2_CXXFLAGS_RELEASE="-Ofast -g0 \"-INLINE:none\" -s"
336        B2_CXXFLAGS_DEBUG="-O0 -INLINE -g"
337    ;;
338
339    pathscale)
340        CXX=${CXX:=pathCC}
341        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
342        B2_CXX="${CXX}"
343        B2_CXXFLAGS_RELEASE="-O3 -inline -s"
344        B2_CXXFLAGS_DEBUG="-O0 -noinline -ggdb"
345    ;;
346
347    pgi)
348        CXX=${CXX:=pgc++}
349        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
350        B2_CXX="${CXX} -std=c++11"
351        B2_CXXFLAGS_RELEASE="-fast -s"
352        B2_CXXFLAGS_DEBUG="-O0 -gopt"
353    ;;
354
355    sun*)
356        CXX=${CXX:=CC}
357        CXX_VERSION_OPT=${CXX_VERSION_OPT:=-V}
358        if test -z "${B2_TOOLSET_ROOT}" -a -r /opt/SUNWspro/bin/CC ; then
359            B2_TOOLSET_ROOT=/opt/SUNWspro/
360        fi
361        if test -r "${B2_TOOLSET_ROOT}/bin/CC" ; then
362            PATH=${B2_TOOLSET_ROOT}bin:${PATH}
363            export PATH
364        fi
365        B2_CXX="${CXX} -std=c++11"
366        B2_CXXFLAGS_RELEASE="-xO4 -s"
367        B2_CXXFLAGS_DEBUG="-g"
368    ;;
369
370    clang*)
371        CXX=${CXX:=clang++}
372        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
373        B2_CXX="${CXX} -x c++ -std=c++11"
374        B2_TOOLSET=clang
375        B2_CXXFLAGS_RELEASE="-O3 -s"
376        B2_CXXFLAGS_DEBUG="-O0 -fno-inline -g"
377    ;;
378
379    tru64cxx)
380        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
381        B2_CXX="cc"
382        B2_CXXFLAGS_RELEASE="-O5 -inline speed -s"
383        B2_CXXFLAGS_DEBUG="-O0 -pg -g"
384    ;;
385
386    acc)
387        CXX=${CXX:=aCC}
388        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
389        B2_CXX="${CXX} -AA"
390        B2_CXXFLAGS_RELEASE="-O3 -s"
391        B2_CXXFLAGS_DEBUG="+d -g"
392    ;;
393
394    qcc)
395        CXX=${CXX:=QCC}
396        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
397        B2_CXX="${CXX}"
398        B2_CXXFLAGS_RELEASE="-O3 -Wc,-finline-functions"
399        B2_CXXFLAGS_DEBUG="O0 -Wc,-fno-inline -gstabs+"
400    ;;
401
402    cxx)
403        CXX=${CXX:=cxx}
404        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
405        B2_CXX="${CXX}"
406    ;;
407
408    cross-cxx)
409        CXX=${BUILD_CXX:=cxx}
410        CXXFLAGS=${BUILD_CXXFLAGS}
411        CXX_VERSION_OPT=${CXX_VERSION_OPT:=--version}
412        B2_CXX="${CXX}"
413    ;;
414
415    *)
416        error_exit "Unknown toolset: $B2_TOOLSET"
417    ;;
418esac
419
420echo "
421###
422###
423### Using '$B2_TOOLSET' toolset.
424###
425###
426"
427echo_run ${CXX} ${CXX_VERSION_OPT}
428echo "
429###
430###
431"
432B2_SOURCES="\
433 builtins.cpp \
434 class.cpp \
435 command.cpp \
436 compile.cpp \
437 constants.cpp \
438 cwd.cpp \
439 debug.cpp \
440 debugger.cpp \
441 execcmd.cpp \
442 filesys.cpp \
443 frames.cpp \
444 function.cpp \
445 glob.cpp\
446 hash.cpp \
447 hcache.cpp \
448 hdrmacro.cpp \
449 headers.cpp \
450 jam.cpp \
451 jamgram.cpp \
452 lists.cpp \
453 make.cpp \
454 make1.cpp \
455 md5.cpp \
456 mem.cpp \
457 modules.cpp \
458 native.cpp \
459 object.cpp \
460 option.cpp \
461 output.cpp \
462 parse.cpp \
463 pathsys.cpp \
464 regexp.cpp \
465 rules.cpp \
466 scan.cpp \
467 search.cpp \
468 jam_strings.cpp \
469 startup.cpp \
470 subst.cpp \
471 sysinfo.cpp \
472 timestamp.cpp \
473 variable.cpp \
474 w32_getreg.cpp \
475 modules/order.cpp \
476 modules/path.cpp \
477 modules/property-set.cpp \
478 modules/regex.cpp \
479 modules/sequence.cpp \
480 modules/set.cpp \
481 "
482case $B2_OS in
483    NT)
484    B2_SOURCES="${B2_SOURCES} execnt.cpp filent.cpp pathnt.cpp"
485    ;;
486
487    *)
488    B2_SOURCES="${B2_SOURCES} execunix.cpp fileunix.cpp pathunix.cpp"
489    ;;
490esac
491
492if check_debug_build "$@" ; then B2_CXXFLAGS="${B2_CXXFLAGS_DEBUG}"
493else B2_CXXFLAGS="${B2_CXXFLAGS_RELEASE} -DNDEBUG"
494fi
495echo_run ${B2_CXX} ${CXXFLAGS} ${B2_CXXFLAGS} ${B2_SOURCES} -o b2
496echo_run cp b2 bjam
497