blob: a807af4f29a6fcec5ce18a8e31405191c75be572 [file] [log] [blame]
Philipp Wollermann19f34132015-06-12 08:39:25 +00001#!/bin/bash
2
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00003# Copyright 2015 The Bazel Authors. All rights reserved.
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +00004#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# General purpose method and values for bootstrapping bazel.
18
19set -o errexit
20
Laszlo Csomor5586fc12019-04-11 05:02:42 -070021# Check if all necessary tools are available.
22# List: https://github.com/bazelbuild/bazel/issues/7641#issuecomment-472344261
23for tool in basename cat chmod comm cp dirname find grep ln ls mkdir mktemp \
24 readlink rm sed sort tail touch tr uname unzip which; do
25 if ! hash "$tool" >/dev/null; then
26 echo >&2 "ERROR: cannot find \"$tool\"; check your PATH."
27 echo >&2 " You may need to run the following command or similar:"
28 echo >&2 " export PATH=\"/bin:/usr/bin:\$PATH\""
29 exit 1
30 fi
31done
32
33# Ensure Python is on the PATH on Windows, otherwise we would see
34# "LAUNCHER ERROR" messages from py_binary exe launchers.
35case "$(uname -s | tr "[:upper:]" "[:lower:]")" in
36msys*|mingw*|cygwin*)
37 # Ensure Python is on the PATH, otherwise the bootstrapping fails later.
38 if ! hash python.exe >/dev/null; then
39 echo >&2 "ERROR: cannot locate python.exe; check your PATH."
40 echo >&2 " You may need to run the following command, or something"
41 echo >&2 " similar, depending on where you installed Python:"
42 echo >&2 " export PATH=\"/c/Python27:\$PATH\""
43 exit 1
44 fi
45 # Ensure TMPDIR uses the user-specified TMPDIR or TMP or TEMP.
46 # This is necessary to avoid overly longs paths during bootstrapping, see for
47 # example https://github.com/bazelbuild/bazel/issues/4536
48 export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-}}}"
49esac
50
Klaus Aehlig276a8cd2016-07-11 12:06:07 +000051# If BAZEL_WRKDIR is set, default all variables to point into
52# that directory
53
54if [ -n "${BAZEL_WRKDIR}" ] ; then
55 mkdir -p "${BAZEL_WRKDIR}/tmp"
56 mkdir -p "${BAZEL_WRKDIR}/user_root"
57 : ${TMPDIR:=${BAZEL_WRKDIR}/tmp}
58 export TMPDIR
59 : ${BAZEL_DIR_STARTUP_OPTIONS:="--output_user_root=${BAZEL_WRKDIR}/user_root"}
60fi
61
62
dmarting511c35b2017-05-05 14:12:29 +020063# We define the fail function early so we can use it when detecting the JDK
64# See https://github.com/bazelbuild/bazel/issues/2949,
65function fail() {
66 local exitCode=$?
67 if [[ "$exitCode" = "0" ]]; then
68 exitCode=1
69 fi
70 echo >&2
Androbinef381e52017-12-14 07:24:27 -080071 echo "ERROR: $*" >&2
dmarting511c35b2017-05-05 14:12:29 +020072 exit $exitCode
73}
74
75
Klaus Aehlig276a8cd2016-07-11 12:06:07 +000076# Set standard variables
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +000077DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
Andrew Johnson1fccb312016-12-05 18:27:27 +000078WORKSPACE_DIR="$(dirname "$(dirname "${DIR}")")"
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +000079
Damien Martin-Guillerez9c5deb62015-09-15 07:38:26 +000080JAVA_VERSION=${JAVA_VERSION:-1.8}
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +000081BAZELRC=${BAZELRC:-"/dev/null"}
82PLATFORM="$(uname -s | tr 'A-Z' 'a-z')"
83
László Csomor3c0c2622017-02-13 15:46:28 +000084PATHSEP=":"
Lukacs T. Berkib70343f2017-01-23 11:57:42 +000085case "${PLATFORM}" in
86linux)
87 # JAVA_HOME must point to a Java installation.
88 JAVA_HOME="${JAVA_HOME:-$(readlink -f $(which javac) | sed 's_/bin/javac__')}"
89 ;;
90
91freebsd)
92 # JAVA_HOME must point to a Java installation.
93 JAVA_HOME="${JAVA_HOME:-/usr/local/openjdk8}"
94 ;;
95
96darwin)
97 if [[ -z "$JAVA_HOME" ]]; then
98 JAVA_HOME="$(/usr/libexec/java_home -v ${JAVA_VERSION}+ 2> /dev/null)" \
99 || fail "Could not find JAVA_HOME, please ensure a JDK (version ${JAVA_VERSION}+) is installed."
100 fi
101 ;;
102
Laszlo Csomord0d7ef02017-04-26 10:48:00 +0200103msys*|mingw*|cygwin*)
Lukacs T. Berkib70343f2017-01-23 11:57:42 +0000104 # Use a simplified platform string.
Laszlo Csomord0d7ef02017-04-26 10:48:00 +0200105 PLATFORM="windows"
Lukacs T. Berkib70343f2017-01-23 11:57:42 +0000106 PATHSEP=";"
107 # Find the latest available version of the SDK.
Laszlo Csomord0d7ef02017-04-26 10:48:00 +0200108 JAVA_HOME="${JAVA_HOME:-$(ls -d C:/Program\ Files/Java/jdk* | sort | tail -n 1)}"
László Csomor3c0c2622017-02-13 15:46:28 +0000109 # Replace backslashes with forward slashes.
110 JAVA_HOME="${JAVA_HOME//\\//}"
Lukacs T. Berkib70343f2017-01-23 11:57:42 +0000111esac
112
Dmitry Lomov9d40a602016-02-15 16:15:03 +0000113EXE_EXT=""
Laszlo Csomord0d7ef02017-04-26 10:48:00 +0200114if [ "${PLATFORM}" == "windows" ]; then
Laszlo Csomorf5525e82017-01-30 18:11:58 +0000115 # Extension for executables.
Dmitry Lomov9d40a602016-02-15 16:15:03 +0000116 EXE_EXT=".exe"
Dmitry Lomov9d40a602016-02-15 16:15:03 +0000117
Laszlo Csomord0d7ef02017-04-26 10:48:00 +0200118 # Fix TMPDIR on windows
Laszlo Csomorf5525e82017-01-30 18:11:58 +0000119 default_tmp=${TMP:-$(cygpath -mO)/Temp}
Laszlo Csomor57db5092016-09-05 07:37:44 +0000120 TMPDIR=$(cygpath -ml "${TMPDIR:-$default_tmp}")
Laszlo Csomorf5525e82017-01-30 18:11:58 +0000121fi
Dmitry Lomov19fd76f2016-06-24 11:52:50 +0000122
Julio Merino5909d9d2016-02-25 21:44:31 +0000123# Whether we display build messages or not. We set this conditionally because
124# the file including us or the user may already have defined VERBOSE to their
125# liking.
126: ${VERBOSE:=yes}
127
Julio Merino63e8d632016-02-25 18:17:53 +0000128# List of functions to invoke on exit.
129ATEXIT_HANDLERS=
130
131# Registers a function to be invoked on exit.
132#
133# The handlers will be invoked at exit time in the order they were registered.
134# See comments in run_atexit for more details.
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000135function atexit() {
Julio Merino63e8d632016-02-25 18:17:53 +0000136 local handler="${1}"; shift
137
138 [ -n "${ATEXIT_HANDLERS}" ] || trap 'run_atexit_handlers $?' EXIT
139 ATEXIT_HANDLERS="${ATEXIT_HANDLERS} ${handler}"
140}
141
142# Exit routine to run all registered atexit handlers.
143#
144# If the program exited with an error, this exit routine will also exit with the
145# same error. However, if the program exited successfully, this exit routine
146# will only exit successfully if the atexit handlers succeed.
147function run_atexit_handlers() {
148 local exit_code="$?"
149
150 local failed=no
151 for handler in ${ATEXIT_HANDLERS}; do
152 eval "${handler}" || failed=yes
153 done
154
155 trap - EXIT # Reset exit handler to prevent double execution.
156 if [ ${exit_code} -ne 0 ]; then
157 exit ${exit_code}
158 else
159 if [ "${failed}" = yes ]; then
160 echo "Program tried to exit successfully but atexit routines failed" 1>&2
161 exit 1
162 else
163 exit 0
164 fi
165 fi
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000166}
167
168function tempdir() {
169 local tmp=${TMPDIR:-/tmp}
Alexander Chungfc071422017-02-07 12:48:26 +0000170 mkdir -p "${tmp}"
171 local DIR="$(mktemp -d "${tmp%%/}/bazel_XXXXXXXX")"
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000172 mkdir -p "${DIR}"
Klaus Aehligf47fd832016-07-01 13:58:09 +0000173 local DIRBASE=$(basename "${DIR}")
László Csomoraa029902017-10-09 09:11:08 +0200174 eval "cleanup_tempdir_${DIRBASE}() { rm -rf '${DIR}' >&/dev/null || true ; }"
Klaus Aehligf47fd832016-07-01 13:58:09 +0000175 atexit cleanup_tempdir_${DIRBASE}
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000176 NEW_TMPDIR="${DIR}"
177}
178tempdir
179OUTPUT_DIR=${NEW_TMPDIR}
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000180phasefile=${OUTPUT_DIR}/phase
Lukacs Berki7da21b12016-08-04 12:18:07 +0000181function cleanup_phasefile() {
182 if [ -f "${phasefile}" ]; then
183 echo 1>&2;
184 cat "${phasefile}" 1>&2;
185 fi;
186}
187
Julio Merino63e8d632016-02-25 18:17:53 +0000188atexit cleanup_phasefile
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000189
Julio Merino5909d9d2016-02-25 21:44:31 +0000190# Excutes a command respecting the current verbosity settings.
191#
192# If VERBOSE is yes, the command itself and its output are printed.
193# If VERBOSE is no, the command's output is only displayed in case of failure.
194#
195# Exits the script if the command fails.
196function run() {
197 if [ "${VERBOSE}" = yes ]; then
198 echo "${@}"
199 "${@}" || exit $?
200 else
Lukacs Berki7da21b12016-08-04 12:18:07 +0000201 local errfile="${OUTPUT_DIR}/errors"
202
Julio Merino5909d9d2016-02-25 21:44:31 +0000203 echo "${@}" >"${errfile}"
Lukacs Berki7da21b12016-08-04 12:18:07 +0000204 if ! "${@}" >>"${errfile}" 2>&1; then
205 local exitcode=$?
206 cat "${errfile}" 1>&2
207 exit $exitcode
208 fi
Julio Merino5909d9d2016-02-25 21:44:31 +0000209 fi
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000210}
211
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000212function display() {
213 if [[ -z "${QUIETMODE}" ]]; then
214 echo -e "$@" >&2
215 fi
216}
217
218function log() {
219 echo -n "." >&2
220 echo "$1" >${phasefile}
221}
222
223function clear_log() {
224 echo >&2
225 rm -f ${phasefile}
226}
227
228LEAVES="\xF0\x9F\x8D\x83"
229INFO="\033[32mINFO\033[0m:"
Damien Martin-Guillerez338dc562015-06-23 17:15:12 +0000230WARNING="\033[31mWARN\033[0m:"
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000231
232first_step=1
233function new_step() {
234 rm -f ${phasefile}
235 local new_line=
236 if [ -n "${first_step}" ]; then
237 first_step=
238 else
239 new_line="\n"
240 fi
Dmitry Lomov8d58ec12017-10-24 14:43:07 +0200241 if [ -t 2 ]; then
242 display -n "$new_line$LEAVES $1"
243 else
244 display -n "$new_line$1"
245 fi
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000246}
247
248function git_sha1() {
Laszlo Csomord0d7ef02017-04-26 10:48:00 +0200249 if [ -x "$(which git 2>/dev/null)" ] && [ -d .git ]; then
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000250 git rev-parse --short HEAD 2>/dev/null || true
251 fi
252}
253
Damien Martin-Guillerez28e67b52016-03-14 11:01:31 +0000254function git_date() {
Laszlo Csomord0d7ef02017-04-26 10:48:00 +0200255 if [ -x "$(which git 2>/dev/null)" ] && [ -d .git ]; then
Damien Martin-Guillerez28e67b52016-03-14 11:01:31 +0000256 git log -1 --pretty=%ai | cut -d " " -f 1 || true
257 fi
258}
259
260# Get the latest release version and append the date of
261# the last commit if any.
262function get_last_version() {
Damien Martin-Guillerezb7e1b822016-03-17 20:52:36 +0000263 if [ -f "CHANGELOG.md" ]; then
264 local version="$(fgrep -m 1 '## Release' CHANGELOG.md \
265 | sed -E 's|.*Release (.*) \(.*\)|\1|')"
266 else
267 local version=""
268 fi
269
Damien Martin-Guillerez28e67b52016-03-14 11:01:31 +0000270 local date="$(git_date)"
271 if [ -z "${version-}" ]; then
272 version="unknown"
273 fi
274 if [ -n "${date-}" ]; then
275 date="$(date +%Y-%m-%d)"
276 fi
277 echo "${version}-${date}"
278}
279
Damien Martin-Guillerezd47a8ef2015-06-10 11:54:50 +0000280if [[ ${PLATFORM} == "darwin" ]]; then
281 function md5_file() {
282 echo $(cat $1 | md5) $1
283 }
284else
285 function md5_file() {
286 md5sum $1
287 }
288fi
Damien Martin-Guillerez338dc562015-06-23 17:15:12 +0000289
290# Gets the java version from JAVA_HOME
291# Sets JAVAC and JAVAC_VERSION with respectively the path to javac and
292# the version of javac.
293function get_java_version() {
294 test -z "$JAVA_HOME" && fail "JDK not found, please set \$JAVA_HOME."
295 JAVAC="${JAVA_HOME}/bin/javac"
296 [[ -x "${JAVAC}" ]] \
297 || fail "JAVA_HOME ($JAVA_HOME) is not a path to a working JDK."
298
299 JAVAC_VERSION=$("${JAVAC}" -version 2>&1)
Bernhard M. Wiedemann5d3f4f12017-11-08 19:46:14 +0100300 if [[ "$JAVAC_VERSION" =~ javac\ ((1\.)?([789]|[1-9][0-9])).*$ ]]; then
301 JAVAC_VERSION=1.${BASH_REMATCH[3]}
Damien Martin-Guillerez338dc562015-06-23 17:15:12 +0000302 else
John Cater6a87a7e2016-08-23 18:49:56 +0000303 fail \
304 "Cannot determine JDK version, please set \$JAVA_HOME.\n" \
305 "\$JAVAC_VERSION is \"${JAVAC_VERSION}\""
Damien Martin-Guillerez338dc562015-06-23 17:15:12 +0000306 fi
307}
Damien Martin-Guillerezdbf5cad2015-09-04 12:46:23 +0000308
309# Return the target that a bind point to, using Bazel query.
310function get_bind_target() {
Klaus Aehlig276a8cd2016-07-11 12:06:07 +0000311 $BAZEL --bazelrc=${BAZELRC} --nomaster_bazelrc ${BAZEL_DIR_STARTUP_OPTIONS} \
Damien Martin-Guillerezdbf5cad2015-09-04 12:46:23 +0000312 query "deps($1, 1) - $1"
313}
John Cater32c5add2018-03-19 08:51:46 -0700314
315# Create a link for a directory on the filesystem
316function link_dir() {
317 local source=$1
318 local dest=$2
319
320 if [[ "${PLATFORM}" == "windows" ]]; then
philwof24768b2019-07-16 07:12:54 -0700321 local -r s="$(cygpath -w "$source")"
322 local -r d="$(cygpath -w "$dest")"
323 powershell -command "New-Item -ItemType Junction -Path '$d' -Value '$s'"
John Cater32c5add2018-03-19 08:51:46 -0700324 else
325 ln -s "${source}" "${dest}"
326 fi
327}
Laszlo Csomor3eec3fe2018-09-03 06:40:28 -0700328
329function link_file() {
330 local source=$1
331 local dest=$2
332
333 if [[ "${PLATFORM}" == "windows" ]]; then
334 # Attempt creating a symlink to the file. This is supported without
335 # elevation (Administrator privileges) on Windows 10 version 1709 when
336 # Developer Mode is enabled.
philwof24768b2019-07-16 07:12:54 -0700337 local -r s="$(cygpath -w "$source")"
338 local -r d="$(cygpath -w "$dest")"
339 if ! powershell -command "New-Item -ItemType SymbolicLink -Path '$d' -Value '$s'"; then
Laszlo Csomor3eec3fe2018-09-03 06:40:28 -0700340 # If the previous call failed to create a symlink, just copy the file.
341 cp "$source" "$dest"
342 fi
343 else
344 ln -s "${source}" "${dest}"
345 fi
346}
347
348# Link direct children (subdirectories and files) of a directory.
349# Usage:
350# link_children "$PWD" "tools" "${BAZEL_TOOLS_REPO}"
351# This creates:
352# ${BAZEL_TOOLS_REPO}/tools/android -> $PWD/tools/android
353# ${BAZEL_TOOLS_REPO}/tools/bash -> $PWD/tools/bash
354# ... and so on for all files and directories directly under "tools".
355function link_children() {
356 local -r source_dir=${1%/}
357 local -r source_subdir=${2%/}
358 local -r dest_dir=${3%/}
359
360 for e in $(find "${source_dir}/${source_subdir}" -mindepth 1 -maxdepth 1 -type d); do
361 local dest_path="${dest_dir}/${e#$source_dir/}"
362 if [[ ! -d "$dest_path" ]]; then
363 link_dir "$e" "$dest_path"
364 fi
365 done
366 for e in $(find "${source_dir}/${source_subdir}" -mindepth 1 -maxdepth 1 -type f); do
367 local dest_path="${dest_dir}/${e#$source_dir/}"
368 if [[ ! -f "$dest_path" ]]; then
369 link_file "$e" "$dest_path"
370 fi
371 done
372}