1#!/usr/bin/env bash
2
3set -eu
4
5# $Id$
6
7get_cores()
8{
9    case $OS in
10        "Linux")
11            echo "$(grep -c ^processor /proc/cpuinfo)" ;;
12        "SunOS")
13            echo "$(psrinfo | wc -l | tr -d ' ')" ;;
14        "Darwin" | "FreeBSD")
15            echo "$(sysctl -n hw.ncpu)" ;;
16        *)
17            echo "CPU information not available: unsupported OS: '$OS'" >/dev/stderr
18            echo 1
19            ;;
20    esac
21}
22
23usage()
24{
25    cat << EOF
26Usage: build.sh [OPTIONS]
27Options:
28    --stage <initial stage>
29    --last-stage <last stage>
30    -s|--scratch    build everything from scratch
31    -c|--configure  reconfigure the build system (implies -s)
32    -b|--bootstap   rebuild the build system (implies -c)
33    -o|--opt        configure build with debug disabled (implies -c)
34    -d|--debug      configure build with debug enabled (implies -c)
35    --dl            set debug level for Scons build (1, implies -c)
36    -r|--release    release number
37    -m32/-m64       build 32/64-bit binaries for x86
38    -p|--package    build RPM packages at the end (DEB not supported).
39    --with-spread   configure build with spread backend (implies -c to gcs)
40    --source        build source packages
41    --sb            skip actual build, use the existing binaries
42    --cmake         build using CMake build system (yes)
43    --co            CMake options
44    --scons         build using Scons build system (no)
45    --so            Sconscript option
46    -j|--jobs       how many parallel jobs to use for Scons (1)
47    "\nSet DISABLE_GCOMM/DISABLE_VSBES to 'yes' to disable respective modules"
48EOF
49}
50
51OS=$(uname)
52# disable building vsbes by default
53DISABLE_VSBES=${DISABLE_VSBES:-"yes"}
54DISABLE_GCOMM=${DISABLE_GCOMM:-"no"}
55PACKAGE=${PACKAGE:-"no"}
56SKIP_BUILD=${SKIP_BUILD:-"no"}
57RELEASE=${RELEASE:-""}
58SOURCE=${SOURCE:-"no"}
59DEBUG=${DEBUG:-"no"}
60DEBUG_LEVEL=${DEBUG_LEVEL:-"0"}
61CMAKE=${CMAKE:-"yes"}
62CMAKE_OPTS=${CMAKE_OPTS:-""}
63SCONS=${SCONS:-"no"}
64SCONS_OPTS=${SCONS_OPTS:-""}
65export JOBS=${JOBS:-"$(get_cores)"}
66SCRATCH=${SCRATCH:-"no"}
67OPT="yes"
68NO_STRIP=${NO_STRIP:-"no"}
69WITH_SPREAD="no"
70RUN_TESTS=${RUN_TESTS:-1}
71if [ "$OS" == "FreeBSD" ]; then
72  chown=/usr/sbin/chown
73  true=/usr/bin/true
74  epm=/usr/local/bin/epm
75else
76  chown=/bin/chown
77  true=/bin/true
78  epm=/usr/bin/epm
79fi
80
81EXTRA_SYSROOT=${EXTRA_SYSROOT:-""}
82
83if [ "$OS" == "Darwin" ]; then
84  if which -s port && test -x /opt/local/bin/port; then
85    EXTRA_SYSROOT=/opt/local
86  elif which -s brew && test -x /usr/local/bin/brew; then
87    EXTRA_SYSROOT=/usr/local
88  elif which -s fink && test -x /sw/bin/fink; then
89    EXTRA_SYSROOT=/sw
90  fi
91elif [ "$OS" == "FreeBSD" ]; then
92  EXTRA_SYSROOT=/usr/local
93fi
94
95if [ "$OS" == "FreeBSD" ]; then
96    CC=${CC:-"clang"}
97    CXX=${CXX:-"clang++"}
98else
99    CC=${CC:-"gcc"}
100    CXX=${CXX:-"g++"}
101fi
102
103if ccache -V > /dev/null 2>&1
104then
105    echo "$CC"  | grep "ccache" > /dev/null || CC="ccache $CC"
106    echo "$CXX" | grep "ccache" > /dev/null || CXX="ccache $CXX"
107fi
108export CC CXX LD_LIBRARY_PATH
109
110CFLAGS=${CFLAGS:-"-O2"}
111CXXFLAGS=${CXXFLAGS:-"$CFLAGS"}
112CPPFLAGS=${CPPFLAGS:-}
113
114initial_stage="galerautils"
115last_stage="galera"
116gainroot=""
117TARGET=${TARGET:-""} # default target
118
119while test $# -gt 0
120do
121    case $1 in
122        --stage)
123            initial_stage=$2
124            shift
125            ;;
126        --last-stage)
127            last_stage=$2
128            shift
129            ;;
130        --gainroot)
131            gainroot=$2
132            shift
133            ;;
134        -b|--bootstrap)
135            BOOTSTRAP="yes" # Bootstrap the build system
136            ;;
137        -c|--configure)
138            CONFIGURE="yes" # Reconfigure the build system
139            ;;
140        -s|--scratch)
141            SCRATCH="yes"   # Build from scratch (run make clean)
142            ;;
143        -o|--opt)
144            OPT="yes"       # Compile without debug
145            ;;
146        -d|--debug)
147            DEBUG="yes"     # Compile with debug
148            NO_STRIP="yes"
149            ;;
150        -r|--release)
151            RELEASE="$2"
152            shift
153            ;;
154        -m32)
155            CFLAGS="$CFLAGS -m32"
156            CXXFLAGS="$CXXFLAGS -m32"
157            SCRATCH="yes"
158            TARGET="i686"
159            ;;
160        -m64)
161            CFLAGS="$CFLAGS -m64"
162            CXXFLAGS="$CXXFLAGS -m64"
163            SCRATCH="yes"
164            TARGET="x86_64"
165            ;;
166        -p|--package)
167            PACKAGE="yes"   # build binary packages
168            ;;
169        --with*-spread)
170            WITH_SPREAD="$1"
171            ;;
172        --help)
173            usage
174            exit 0
175            ;;
176        --source)
177            SOURCE="yes"
178            ;;
179        --sb)
180            SKIP_BUILD="yes"
181            ;;
182        --cmake)
183            CMAKE="yes"
184            SCONS="no"
185            ;;
186        --co)
187            CMAKE_OPTS="$CMAKE_OPTS $2"
188            shift
189            ;;
190        --scons)
191            SCONS="yes"
192            CMAKE="no"
193            ;;
194        --so)
195            SCONS_OPTS="$SCONS_OPTS $2"
196            shift
197            ;;
198        -j|--jobs)
199            JOBS=$2
200            shift
201            ;;
202        --dl)
203            DEBUG_LEVEL=$2
204            shift
205            ;;
206        *)
207            if test ! -z "$1"; then
208               echo "Unrecognized option: $1"
209            fi
210            usage
211            exit 1
212            ;;
213    esac
214    shift
215done
216
217# check whether sudo accepts -E to preserve environment
218if [ "$PACKAGE" == "yes" ]
219then
220    if which dpkg >/dev/null 2>&1
221    then
222        echo "Error: Package build not supported on Debian, use dpkg-buildpackage"
223        exit 1
224    fi
225    echo "testing sudo"
226    if sudo -E $true >/dev/null 2>&1
227    then
228        echo "sudo accepts -E"
229        SUDO="sudo -E"
230    else
231        echo "sudo does not accept param -E"
232        if [ $(id -ur) != 0 ]
233        then
234            echo "error, must build as root"
235            exit 1
236        else
237            echo "I'm root, can continue"
238            SUDO=""
239        fi
240    fi
241fi
242
243if [ "$OPT"   == "yes" ]; then CONFIGURE="yes";
244   conf_flags="--disable-debug --disable-dbug";
245fi
246if [ "$DEBUG" == "yes" ]; then CONFIGURE="yes"; fi
247if [ -n "$WITH_SPREAD" ]; then CONFIGURE="yes"; fi
248
249if [ "$CONFIGURE" == "yes" ] && [ "$SCONS" != "yes" ]; then SCRATCH="yes"; fi
250
251# Be quite verbose
252#set -x
253
254# Build process base directory
255build_base=${GALERA_SRC:-$(cd $(dirname $0)/..; pwd -P)}
256
257get_arch()
258{
259    if ! [ -z "$TARGET" ]
260    then
261       if [ "$TARGET" == "i686" ]
262       then
263           echo "i386"
264       else
265           echo "amd64"
266       fi
267    elif [ "$OS" == "Darwin" ]; then
268        if file $build_base/gcs/src/gcs.o | grep "i386" >/dev/null 2>&1
269        then
270            echo "i386"
271        else
272            echo "amd64"
273        fi
274    else
275        if file $build_base/gcs/src/gcs.o | grep "80386" >/dev/null 2>&1
276        then
277            echo "i386"
278        else
279            echo "amd64"
280        fi
281    fi
282}
283
284build_packages()
285{
286    local PKG_DIR=$build_base/scripts/packages
287    pushd $PKG_DIR
288
289    local ARCH=$(get_arch)
290    local WHOAMI=$(whoami)
291
292    export BUILD_BASE=$build_base
293    export GALERA_VER=$RELEASE
294
295    if [ $DEBIAN -eq 0 ] && [ "$ARCH" == "amd64" ]
296    then
297        ARCH="x86_64"
298        export x86_64=$ARCH # for epm
299    fi
300    export $ARCH
301
302    local STRIP_OPT=""
303    [ "$NO_STRIP" == "yes" ] && STRIP_OPT="-g"
304
305    $SUDO rm -rf $ARCH
306
307    set +e
308    if [ "$OS" == "FreeBSD" ]; then
309        if test "$NO_STRIP" != "yes"; then
310            strip $build_base/{garb/garbd,libgalera_smm.so}
311        fi
312        ./freebsd.sh $GALERA_VER
313    else # build RPM
314        ./rpm.sh $GALERA_VER
315    fi
316    local RET=$?
317
318    set -e
319
320    popd
321    if [ "$OS" == "FreeBSD" ]; then
322        mv -f $PKG_DIR/*.tbz ./
323    else
324        mv -f $PKG_DIR/*.rpm ./
325    fi
326    return $RET
327}
328
329build_source()
330{
331    local module="$1"
332    shift
333    local build_dir="$build_base/$module"
334    pushd $build_dir
335
336    if [ ! -x "configure" ]; then ./bootstrap.sh; fi
337    if [ ! -s "Makefile"  ]; then ./configure;    fi
338
339    local src_base_name="lib${module}-"
340    rm -rf "${src_base_name}"*.tar.gz
341    make dist || (echo $?; echo "make dist failed"; echo)
342    local ret=$(ls "${src_base_name}"*.tar.gz)
343    popd
344
345    echo $build_dir/$ret
346}
347
348build_sources()
349{
350    local module
351    local srcs=""
352
353    for module in "galerautils" "gcomm" "gcs" "galera"
354    do
355        src=$(build_source $module | tail -n 1)
356        srcs="$srcs $src"
357    done
358
359    local ret="galera-source-r$RELEASE.tar"
360    tar --transform 's/.*\///' -cf $ret $srcs \
361    "source/README" "source/COPYING" "source/build.sh"
362
363    # return absolute path for scripts
364    echo $PWD/$ret
365}
366
367pushd "$build_base"
368#GALERA_REV="$(svnversion | sed s/\:/,/g)"
369#if [ "$GALERA_REV" == "exported" ]
370#then
371    GALERA_REV=$(git log --pretty=oneline | wc -l) || \
372    GALERA_REV=$(bzr revno --tree -q)              || \
373    GALERA_REV=$(svn info >&/dev/null && svnversion | sed s/\:/,/g) || \
374    GALERA_REV="XXXX"
375    # trim spaces (sed is not working on Solaris, so using bash built-in)
376    GALERA_REV=${GALERA_REV//[[:space:]]/}
377#fi
378
379if [ -z "$RELEASE" ]
380then
381    source GALERA_VERSION
382    RELEASE="$GALERA_VERSION_WSREP_API.$GALERA_VERSION_MAJOR.$GALERA_VERSION_MINOR"
383fi
384
385if [ "$CMAKE" == "yes" ] # Build using CMake
386then
387    cmake_args="$CMAKE_OPTS -DGALERA_REVISION=$GALERA_REV"
388    [ -n "$TARGET"        ] && \
389        echo "WARN: TARGET=$TARGET ignored by CMake build"
390    [ -n "$RELEASE"       ] && \
391        echo "WARN: RELEASE=$RELEASE ignored by CMake build"
392    [ "$DEBUG" == "yes"   ] && cmake_args="$cmake_args -DCMAKE_BUILD_TYPE=Debug"
393    [ -n "$EXTRA_SYSROOT" ] && \
394        echo "EXTRA_SYSROOT=$EXTRA_SYSROOT ignored by CMake build"
395
396    if [ "$SCRATCH" == "yes" ]
397    then
398        (cd $build_base && make clean) || :
399        rm -f $build_base/CMakeCache.txt
400        cmake $cmake_args $build_base
401    fi
402
403    if [ "$SKIP_BUILD" != "yes" ]
404    then
405        make -j $JOBS VERBOSE=1
406    fi
407
408    if [ $RUN_TESTS ]
409    then
410        make test ARGS=-V
411    fi
412elif [ "$SCONS" == "yes" ] # Build using Scons
413then
414    # Scons variant dir, defaults to GALERA_SRC
415    export SCONS_VD=$build_base
416    scons_args="-C $build_base revno=$GALERA_REV tests=$RUN_TESTS strict_build_flags=1"
417
418    [ -n "$TARGET"        ] && scons_args="$scons_args arch=$TARGET"
419    [ -n "$RELEASE"       ] && scons_args="$scons_args version=$RELEASE"
420    [ "$DEBUG" == "yes"   ] && scons_args="$scons_args debug=$DEBUG_LEVEL"
421    [ -n "$EXTRA_SYSROOT" ] && scons_args="$scons_args extra_sysroot=$EXTRA_SYSROOT"
422
423    if [ "$SCRATCH" == "yes" ]
424    then
425        scons -Q -c --conf=force $scons_args $SCONS_OPTS
426    fi
427
428    if [ "$SKIP_BUILD" != "yes" ]
429    then
430        scons $scons_args -j $JOBS $SCONS_OPTS
431    fi
432
433elif test "$SKIP_BUILD" == "no"; then # Build using autotools
434    echo "Error: autotools not supported anymore! Nothing was built."
435    exit 1
436fi # SKIP_BUILD / SCONS
437
438if test "$PACKAGE" == "yes"
439then
440    build_packages
441fi
442
443if test "$SOURCE" == "yes"
444then
445    build_sources
446fi
447
448popd # $build_base
449