File: bazel.sh

package info (click to toggle)
bazel-bootstrap 4.2.3%2Bds-11
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 85,704 kB
  • sloc: java: 721,717; sh: 55,859; cpp: 35,360; python: 12,139; xml: 295; objc: 269; makefile: 113; ansic: 106; ruby: 3
file content (220 lines) | stat: -rwxr-xr-x 8,678 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/bin/bash

# Copyright 2019 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -eu

# This is a script which can be installed as your "bazel" binary instead of the
# real Bazel binary. When called, it tries to determine and run the correct
# Bazel version for a given project and forwards all arguments to it.
#
# You can specify which Bazel version to use using these methods:
# 1. Set $USE_BAZEL_VERSION to a version number
#    (e.g. export USE_BAZEL_VERSION=1.0.0).
# 2. Add a .bazelversion file that contains a version number next to your
#    WORKSPACE file.
# 3. Otherwise, the latest Bazel version will be used.
#
# This wrapper only recognizes Bazel versions installed next to itself, thus
# if you install this wrapper as /usr/bin/bazel, you'll have to install binaries
# for individual Bazel binaries as e.g. /usr/bin/bazel-1.0.0.
#
# In addition, if an executable called "tools/bazel" is found in the current
# workspace, this script will not directly execute Bazel, but instead store
# the path to the real Bazel executable in the environment variable BAZEL_REAL
# and then execute the "tools/bazel" wrapper script.
#
# In contrast to Bazelisk, this script does not download anything from the
# internet and instead relies on the local system to provide Bazel binaries.

function color() {
      # Usage: color "31;5" "string"
      # Some valid values for color:
      # - 5 blink, 1 strong, 4 underlined
      # - fg: 31 red,  32 green, 33 yellow, 34 blue, 35 purple, 36 cyan, 37 white
      # - bg: 40 black, 41 red, 44 blue, 45 purple
      printf '\033[%sm%s\033[0m\n' "$@"
}

# `readlink -f` that works on OSX too.
function get_realpath() {
    if [ "$(uname -s)" == "Darwin" ]; then
        local queue="$1"
        if [[ "${queue}" != /* ]] ; then
            # Make sure we start with an absolute path.
            queue="${PWD}/${queue}"
        fi
        local current=""
        while [ -n "${queue}" ]; do
            # Removing a trailing /.
            queue="${queue#/}"
            # Pull the first path segment off of queue.
            local segment="${queue%%/*}"
            # If this is the last segment.
            if [[ "${queue}" != */* ]] ; then
                segment="${queue}"
                queue=""
            else
                # Remove that first segment.
                queue="${queue#*/}"
            fi
            local link="${current}/${segment}"
            if [ -h "${link}" ] ; then
                link="$(readlink "${link}")"
                queue="${link}/${queue}"
                if [[ "${link}" == /* ]] ; then
                    current=""
                fi
            else
                current="${link}"
            fi
        done

        echo "${current}"
    else
        readlink -f "$1"
    fi
}

function get_workspace_root() {
  workspace_dir="${PWD}"
  while [[ "${workspace_dir}" != / ]]; do
    if [[ -e "${workspace_dir}/WORKSPACE" ]]; then
      readonly workspace_dir
      return
    fi
    workspace_dir="$(dirname "${workspace_dir}")"
  done
  readonly workspace_dir=""
}

get_workspace_root

readonly wrapper_dir="$(dirname "$(get_realpath "${BASH_SOURCE[0]}")")"
readonly os_arch_suffix="$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m)"

function get_bazel_version() {
  bazel_version=""

  if [[ -n ${USE_BAZEL_VERSION:-} ]]; then
    reason="specified in \$USE_BAZEL_VERSION"
    bazel_version="${USE_BAZEL_VERSION}"
  elif [[ -e "${workspace_dir}/.bazelversion" ]]; then
    reason="specified in ${workspace_dir}/.bazelversion"
    # The "read" can fail if the .bazelversion file does not contain a final
    # newline character. It will still correctly assign the read data to the
    # variable. Of course it can also fail due to real I/O errors. Because we do
    # validation of the read data later, we can just ignore the error here.
    # Alternatives like 'bazel_version=$(head -1 ...)' are not better either,
    # because bash does not care about the exit code of processes used in
    # command substitution.
    read -r bazel_version < "${workspace_dir}/.bazelversion" || true
  fi

  # If we read an empty string or the magic word "latest" from .bazelversion or
  # $USE_BAZEL_VERSION, then we should use the latest available stable version.
  # This mimics the behavior of Bazelisk.
  if [[ -z $bazel_version || $bazel_version == "latest" ]]; then
    if [[ -x "${wrapper_dir}/bazel-real" ]]; then
      reason="${reason:-"automatically selected bazel-real"}"
      bazel_version="real"
    else
      # Find the latest Bazel version installed on the system.
      reason="${reason:-"automatically selected latest available version"}"
      bazel_version="$(basename "$(find -H "${wrapper_dir}" -maxdepth 1 -name 'bazel-[0-9]*-${os_arch_suffix}' -type f | sort -V | tail -n 1)")"
      if [[ -z $bazel_version ]]; then
        bazel_version="$(basename "$(find -H "${wrapper_dir}" -maxdepth 1 -name 'bazel-[0-9]*' -type f | sort -V | tail -n 1)")"
      fi
      # Remove the "bazel-" prefix from the file name.
      bazel_version="${bazel_version#"bazel-"}"
    fi
  fi

  readonly reason
  readonly bazel_version
}

get_bazel_version

BAZEL_REAL="${wrapper_dir}/bazel-${bazel_version}-${os_arch_suffix}"

# Try without the architecture suffix.
if [[ ! -x ${BAZEL_REAL} ]]; then
  BAZEL_REAL="${wrapper_dir}/bazel-${bazel_version}"
fi

# Last try: Maybe `bazel-real` is actually the requested correct version?
readonly bazel_real_path="${wrapper_dir}/bazel-real"
if [[ ! -x ${BAZEL_REAL} && -x ${bazel_real_path} ]]; then
  # Note that "bazel --version" is very fast and doesn't start the Bazel server,
  # as opposed to "bazel version".
  readonly bazel_real_version="$("${bazel_real_path}" --version | grep '^bazel ' | cut -d' ' -f2)"
  if [[ $bazel_real_version == $bazel_version ]]; then
    BAZEL_REAL="${bazel_real_path}"
  fi
fi

# If the repository contains a checked-in executable called tools/bazel, we
# assume that they know what they're doing and have their own way of versioning
# Bazel. Thus, we don't have to print our helpful messages or error out in case
# we couldn't find a binary.
readonly wrapper="${workspace_dir}/tools/bazel"
if [[ -x "$wrapper" && -f "$wrapper" ]]; then
  export BAZEL_REAL
  exec -a "$0" "${wrapper}" "$@"
fi

if [[ -z $bazel_version ]]; then
  color "31" "ERROR: No installed Bazel version found, cannot continue."
  (echo ""
  echo "Bazel binaries have to be installed in ${wrapper_dir}, but none were found.") 2>&1
  exit 1
fi

if [[ ! -x $BAZEL_REAL ]]; then
  color "31" "ERROR: The project you're trying to build requires Bazel ${bazel_version} (${reason}), but it wasn't found in ${wrapper_dir}."

  long_binary_name="bazel-${bazel_version}-${os_arch_suffix}"

  if [[ -x $(command -v apt-get) && $wrapper_dir == "/usr/bin" ]]; then
    (echo ""
    echo "You can install the required Bazel version via apt:"
    echo "  sudo apt update && sudo apt install bazel-${bazel_version}"
    echo ""
    echo "If this doesn't work, check Bazel's installation instructions for help:"
    echo "  https://docs.bazel.build/versions/master/install-ubuntu.html") 2>&1
  else
    (echo ""
    echo "Bazel binaries for all official releases can be downloaded from here:"
    echo "  https://github.com/bazelbuild/bazel/releases") 2>&1

    if [[ -x $(command -v curl) && -w $wrapper_dir ]]; then
      (echo ""
      echo "You can download the required version directly using this command:"
      echo "  (cd \"${wrapper_dir}\" && curl -fLO https://releases.bazel.build/${bazel_version}/release/${long_binary_name} && chmod +x ${long_binary_name})") 2>&1
    elif [[ -x $(command -v wget) && -w $wrapper_dir ]]; then
      (echo ""
      echo "You can download the required version directly using this command:"
      echo "  (cd \"${wrapper_dir}\" && wget https://releases.bazel.build/${bazel_version}/release/${long_binary_name} && chmod +x ${long_binary_name})") 2>&1
    else
      (echo ""
      echo "Please put the downloaded Bazel binary into this location:"
      echo "  ${wrapper_dir}/${long_binary_name}") 2>&1
    fi
  fi
  exit 1
fi

exec -a "$0" "${BAZEL_REAL}" "$@"