1#!/bin/bash
2
3# This script serves two purposes.  First, it can bootstrap the standalone
4# Blueprint to generate the minibp binary.  To do this simply run the script
5# with no arguments from the desired build directory.
6#
7# It can also be invoked from another script to bootstrap a custom Blueprint-
8# based build system.  To do this, the invoking script must first set some or
9# all of the following environment variables, which are documented below where
10# their default values are set:
11#
12#   BOOTSTRAP
13#   WRAPPER
14#   SRCDIR
15#   BUILDDIR
16#   BOOTSTRAP_MANIFEST
17#   GOROOT
18#   GOOS
19#   GOARCH
20#   GOCHAR
21#
22# The invoking script should then run this script, passing along all of its
23# command line arguments.
24
25set -e
26
27EXTRA_ARGS=""
28
29# BOOTSTRAP should be set to the path of the bootstrap script.  It can be
30# either an absolute path or one relative to the build directory (which of
31# these is used should probably match what's used for SRCDIR).
32if [ -z "$BOOTSTRAP" ]; then
33    BOOTSTRAP="${BASH_SOURCE[0]}"
34
35    # WRAPPER should only be set if you want a ninja wrapper script to be
36    # installed into the builddir. It is set to blueprint's blueprint.bash
37    # only if BOOTSTRAP and WRAPPER are unset.
38    [ -z "$WRAPPER" ] && WRAPPER="`dirname "${BOOTSTRAP}"`/blueprint.bash"
39fi
40
41# SRCDIR should be set to the path of the root source directory.  It can be
42# either an absolute path or a path relative to the build directory.  Whether
43# its an absolute or relative path determines whether the build directory can
44# be moved relative to or along with the source directory without re-running
45# the bootstrap script.
46[ -z "$SRCDIR" ] && SRCDIR=`dirname "${BOOTSTRAP}"`
47
48# BUILDDIR should be set to the path to store build results. By default, this
49# is the current directory, but it may be set to an absolute or relative path.
50[ -z "$BUILDDIR" ] && BUILDDIR=.
51
52# TOPNAME should be set to the name of the top-level Blueprints file
53[ -z "$TOPNAME" ] && TOPNAME="Blueprints"
54
55# BOOTSTRAP_MANIFEST is the path to the bootstrap Ninja file that is part of
56# the source tree.  It is used to bootstrap a build output directory from when
57# the script is run manually by a user.
58[ -z "$BOOTSTRAP_MANIFEST" ] && BOOTSTRAP_MANIFEST="${SRCDIR}/build.ninja.in"
59
60# These variables should be set by auto-detecting or knowing a priori the host
61# Go toolchain properties.
62[ -z "$GOROOT" ] && GOROOT=`go env GOROOT`
63[ -z "$GOOS" ]   && GOOS=`go env GOHOSTOS`
64[ -z "$GOARCH" ] && GOARCH=`go env GOHOSTARCH`
65[ -z "$GOCHAR" ] && GOCHAR=`go env GOCHAR`
66
67# If RUN_TESTS is set, behave like -t was passed in as an option.
68[ ! -z "$RUN_TESTS" ] && EXTRA_ARGS="$EXTRA_ARGS -t"
69
70GOTOOLDIR="$GOROOT/pkg/tool/${GOOS}_$GOARCH"
71GOCOMPILE="$GOTOOLDIR/${GOCHAR}g"
72GOLINK="$GOTOOLDIR/${GOCHAR}l"
73
74if [ ! -f $GOCOMPILE ]; then
75  GOCOMPILE="$GOTOOLDIR/compile"
76fi
77if [ ! -f $GOLINK ]; then
78  GOLINK="$GOTOOLDIR/link"
79fi
80if [[ ! -f $GOCOMPILE || ! -f $GOLINK ]]; then
81  echo "Cannot find go tools under $GOROOT"
82  exit 1
83fi
84
85usage() {
86    echo "Usage of ${BOOTSTRAP}:"
87    echo "  -h: print a help message and exit"
88    echo "  -r: regenerate ${BOOTSTRAP_MANIFEST}"
89    echo "  -t: include tests when regenerating manifest"
90}
91
92# Parse the command line flags.
93IN="$BOOTSTRAP_MANIFEST"
94REGEN_BOOTSTRAP_MANIFEST=false
95while getopts ":b:hi:rt" opt; do
96    case $opt in
97        b) BUILDDIR="$OPTARG";;
98        h)
99            usage
100            exit 1
101            ;;
102        i) IN="$OPTARG";;
103        r) REGEN_BOOTSTRAP_MANIFEST=true;;
104        t) EXTRA_ARGS="$EXTRA_ARGS -t";;
105        \?)
106            echo "Invalid option: -$OPTARG" >&2
107            usage
108            exit 1
109            ;;
110        :)
111            echo "Option -$OPTARG requires an argument." >&2
112            exit 1
113            ;;
114    esac
115done
116
117if [ $REGEN_BOOTSTRAP_MANIFEST = true ]; then
118    # This assumes that the script is being run from a build output directory
119    # that has been built in the past.
120    if [ -x $BUILDDIR/.bootstrap/bin/minibp ]; then
121        echo "Regenerating $BOOTSTRAP_MANIFEST"
122        $BUILDDIR/.bootstrap/bin/minibp $EXTRA_ARGS -o $BOOTSTRAP_MANIFEST $SRCDIR/$TOPNAME
123    else
124        echo "Executable minibp not found at $BUILDDIR/.bootstrap/bin/minibp" >&2
125        exit 1
126    fi
127fi
128
129mkdir -p $BUILDDIR
130
131sed -e "s|@@SrcDir@@|$SRCDIR|g"                        \
132    -e "s|@@BuildDir@@|$BUILDDIR|g"                    \
133    -e "s|@@GoRoot@@|$GOROOT|g"                        \
134    -e "s|@@GoCompile@@|$GOCOMPILE|g"                  \
135    -e "s|@@GoLink@@|$GOLINK|g"                        \
136    -e "s|@@Bootstrap@@|$BOOTSTRAP|g"                  \
137    -e "s|@@BootstrapManifest@@|$BOOTSTRAP_MANIFEST|g" \
138    $IN > $BUILDDIR/build.ninja
139
140echo "BOOTSTRAP=\"${BOOTSTRAP}\"" > $BUILDDIR/.blueprint.bootstrap
141echo "BOOTSTRAP_MANIFEST=\"${BOOTSTRAP_MANIFEST}\"" >> $BUILDDIR/.blueprint.bootstrap
142
143if [ ! -z "$WRAPPER" ]; then
144    cp $WRAPPER $BUILDDIR/
145fi
146