| #!/bin/bash | 
 |  | 
 | # Copyright 2015 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. | 
 |  | 
 | # General purpose method and values for bootstrapping bazel. | 
 |  | 
 | set -o errexit | 
 |  | 
 | # Check if all necessary tools are available. | 
 | # List: https://github.com/bazelbuild/bazel/issues/7641#issuecomment-472344261 | 
 | for tool in basename cat chmod comm cp dirname find grep ln ls mkdir mktemp \ | 
 |             readlink rm sed sort tail touch tr uname unzip which; do | 
 |   if ! hash "$tool" >/dev/null; then | 
 |     echo >&2 "ERROR: cannot find \"$tool\"; check your PATH." | 
 |     echo >&2 "       You may need to run the following command or similar:" | 
 |     echo >&2 "         export PATH=\"/bin:/usr/bin:\$PATH\"" | 
 |     exit 1 | 
 |   fi | 
 | done | 
 |  | 
 | # Ensure Python is on the PATH on Windows, otherwise we would see | 
 | # "LAUNCHER ERROR" messages from py_binary exe launchers. | 
 | case "$(uname -s | tr "[:upper:]" "[:lower:]")" in | 
 | msys*|mingw*|cygwin*) | 
 |   # Ensure Python is on the PATH, otherwise the bootstrapping fails later. | 
 |   if ! hash python.exe >/dev/null; then | 
 |     echo >&2 "ERROR: cannot locate python.exe; check your PATH." | 
 |     echo >&2 "       You may need to run the following command, or something" | 
 |     echo >&2 "       similar, depending on where you installed Python:" | 
 |     echo >&2 "         export PATH=\"/c/Python27:\$PATH\"" | 
 |     exit 1 | 
 |   fi | 
 |   # Ensure TMPDIR uses the user-specified TMPDIR or TMP or TEMP. | 
 |   # This is necessary to avoid overly longs paths during bootstrapping, see for | 
 |   # example https://github.com/bazelbuild/bazel/issues/4536 | 
 |   export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-}}}" | 
 | esac | 
 |  | 
 | # If BAZEL_WRKDIR is set, default all variables to point into | 
 | # that directory | 
 |  | 
 | if [ -n "${BAZEL_WRKDIR}" ] ; then | 
 |  mkdir -p "${BAZEL_WRKDIR}/tmp" | 
 |  mkdir -p "${BAZEL_WRKDIR}/user_root" | 
 |  : ${TMPDIR:=${BAZEL_WRKDIR}/tmp} | 
 |  export TMPDIR | 
 |  : ${BAZEL_DIR_STARTUP_OPTIONS:="--output_user_root=${BAZEL_WRKDIR}/user_root"} | 
 | fi | 
 |  | 
 |  | 
 | # We define the fail function early so we can use it when detecting the JDK | 
 | # See https://github.com/bazelbuild/bazel/issues/2949, | 
 | function fail() { | 
 |   local exitCode=$? | 
 |   if [[ "$exitCode" = "0" ]]; then | 
 |     exitCode=1 | 
 |   fi | 
 |   echo >&2 | 
 |   echo "ERROR: $*" >&2 | 
 |   exit $exitCode | 
 | } | 
 |  | 
 |  | 
 | # Set standard variables | 
 | DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) | 
 | WORKSPACE_DIR="$(dirname "$(dirname "${DIR}")")" | 
 |  | 
 | JAVA_VERSION=${JAVA_VERSION:-11} | 
 | BAZELRC=${BAZELRC:-"/dev/null"} | 
 | PLATFORM="$(uname -s | tr 'A-Z' 'a-z')" | 
 |  | 
 | PATHSEP=":" | 
 | case "${PLATFORM}" in | 
 | linux) | 
 |   # JAVA_HOME must point to a Java installation. | 
 |   JAVA_HOME="${JAVA_HOME:-$(readlink -f $(which javac) | sed 's_/bin/javac__')}" | 
 |   ;; | 
 |  | 
 | freebsd) | 
 |   # JAVA_HOME must point to a Java installation. | 
 |   JAVA_HOME="${JAVA_HOME:-/usr/local/openjdk11}" | 
 |   ;; | 
 |  | 
 | openbsd) | 
 |   # JAVA_HOME must point to a Java installation. | 
 |   JAVA_HOME="${JAVA_HOME:-/usr/local/jdk-11}" | 
 |   ;; | 
 |  | 
 | darwin) | 
 |   if [[ -z "$JAVA_HOME" ]]; then | 
 |     JAVA_HOME="$(/usr/libexec/java_home -v ${JAVA_VERSION}+ 2> /dev/null)" \ | 
 |       || fail "Could not find JAVA_HOME, please ensure a JDK (version ${JAVA_VERSION}+) is installed." | 
 |   fi | 
 |   ;; | 
 |  | 
 | msys*|mingw*|cygwin*) | 
 |   # Use a simplified platform string. | 
 |   PLATFORM="windows" | 
 |   PATHSEP=";" | 
 |   # Find the latest available version of the SDK. | 
 |   JAVA_HOME="${JAVA_HOME:-$(ls -d C:/Program\ Files/Java/jdk* | sort | tail -n 1)}" | 
 |   # Replace backslashes with forward slashes. | 
 |   JAVA_HOME="${JAVA_HOME//\\//}" | 
 | esac | 
 |  | 
 | EXE_EXT="" | 
 | if [ "${PLATFORM}" == "windows" ]; then | 
 |   # Extension for executables. | 
 |   EXE_EXT=".exe" | 
 |  | 
 |   # Fix TMPDIR on windows | 
 |   default_tmp=${TMP:-$(cygpath -mO)/Temp} | 
 |   TMPDIR=$(cygpath -ml "${TMPDIR:-$default_tmp}") | 
 | fi | 
 |  | 
 | # Whether we display build messages or not.  We set this conditionally because | 
 | # the file including us or the user may already have defined VERBOSE to their | 
 | # liking. | 
 | : ${VERBOSE:=yes} | 
 |  | 
 | # List of functions to invoke on exit. | 
 | ATEXIT_HANDLERS= | 
 |  | 
 | # Registers a function to be invoked on exit. | 
 | # | 
 | # The handlers will be invoked at exit time in the order they were registered. | 
 | # See comments in run_atexit for more details. | 
 | function atexit() { | 
 |   local handler="${1}"; shift | 
 |  | 
 |   [ -n "${ATEXIT_HANDLERS}" ] || trap 'run_atexit_handlers $?' EXIT | 
 |   ATEXIT_HANDLERS="${ATEXIT_HANDLERS} ${handler}" | 
 | } | 
 |  | 
 | # Exit routine to run all registered atexit handlers. | 
 | # | 
 | # If the program exited with an error, this exit routine will also exit with the | 
 | # same error.  However, if the program exited successfully, this exit routine | 
 | # will only exit successfully if the atexit handlers succeed. | 
 | function run_atexit_handlers() { | 
 |   local exit_code="$?" | 
 |  | 
 |   local failed=no | 
 |   for handler in ${ATEXIT_HANDLERS}; do | 
 |     eval "${handler}" || failed=yes | 
 |   done | 
 |  | 
 |   trap - EXIT  # Reset exit handler to prevent double execution. | 
 |   if [ ${exit_code} -ne 0 ]; then | 
 |     exit ${exit_code} | 
 |   else | 
 |     if [ "${failed}" = yes ]; then | 
 |       echo "Program tried to exit successfully but atexit routines failed" 1>&2 | 
 |       exit 1 | 
 |     else | 
 |       exit 0 | 
 |     fi | 
 |   fi | 
 | } | 
 |  | 
 | function tempdir() { | 
 |   local tmp=${TMPDIR:-/tmp} | 
 |   mkdir -p "${tmp}" | 
 |   local DIR="$(mktemp -d "${tmp%%/}/bazel_XXXXXXXX")" | 
 |   mkdir -p "${DIR}" | 
 |   local DIRBASE=$(basename "${DIR}") | 
 |   eval "cleanup_tempdir_${DIRBASE}() { rm -rf '${DIR}' >&/dev/null || true ; }" | 
 |   atexit cleanup_tempdir_${DIRBASE} | 
 |   NEW_TMPDIR="${DIR}" | 
 | } | 
 | tempdir | 
 | OUTPUT_DIR=${NEW_TMPDIR} | 
 | phasefile=${OUTPUT_DIR}/phase | 
 | function cleanup_phasefile() { | 
 |   if [ -f "${phasefile}" ]; then | 
 |     echo 1>&2; | 
 |     cat "${phasefile}" 1>&2; | 
 |   fi; | 
 | } | 
 |  | 
 | atexit cleanup_phasefile | 
 |  | 
 | # Executes a command respecting the current verbosity settings. | 
 | # | 
 | # If VERBOSE is yes, the command itself and its output are printed. | 
 | # If VERBOSE is no, the command's output is only displayed in case of failure. | 
 | # | 
 | # Exits the script if the command fails. | 
 | function run() { | 
 |   if [ "${VERBOSE}" = yes ]; then | 
 |     echo "${@}" | 
 |     "${@}" || exit $? | 
 |   else | 
 |     local errfile="${OUTPUT_DIR}/errors" | 
 |  | 
 |     echo "${@}" >"${errfile}" | 
 |     if ! "${@}" >>"${errfile}" 2>&1; then | 
 |       local exitcode=$? | 
 |       cat "${errfile}" 1>&2 | 
 |       exit $exitcode | 
 |     fi | 
 |   fi | 
 | } | 
 |  | 
 | function display() { | 
 |   if [[ -z "${QUIETMODE}" ]]; then | 
 |     echo -e "$@" >&2 | 
 |   fi | 
 | } | 
 |  | 
 | function log() { | 
 |   echo -n "." >&2 | 
 |   echo "$1" >${phasefile} | 
 | } | 
 |  | 
 | function clear_log() { | 
 |   echo >&2 | 
 |   rm -f ${phasefile} | 
 | } | 
 |  | 
 | LEAVES="\xF0\x9F\x8D\x83" | 
 | INFO="\033[32mINFO\033[0m:" | 
 | WARNING="\033[31mWARN\033[0m:" | 
 |  | 
 | first_step=1 | 
 | function new_step() { | 
 |   rm -f ${phasefile} | 
 |   local new_line= | 
 |   if [ -n "${first_step}" ]; then | 
 |     first_step= | 
 |   else | 
 |     new_line="\n" | 
 |   fi | 
 |   if [ -t 2 ]; then | 
 |     display -n "$new_line$LEAVES  $1" | 
 |   else | 
 |     display -n "$new_line$1" | 
 |   fi | 
 | } | 
 |  | 
 | function git_sha1() { | 
 |   if [ -x "$(which git 2>/dev/null)" ] && [ -d .git ]; then | 
 |     git rev-parse --short HEAD 2>/dev/null || true | 
 |   fi | 
 | } | 
 |  | 
 | function git_date() { | 
 |   if [ -x "$(which git 2>/dev/null)" ] && [ -d .git ]; then | 
 |     git log -1 --pretty=%ai | cut -d " " -f 1 || true | 
 |   fi | 
 | } | 
 |  | 
 | # Get the latest release version and append the date of | 
 | # the last commit if any. | 
 | function get_last_version() { | 
 |   if [ -f "CHANGELOG.md" ]; then | 
 |     local version="$(fgrep -m 1 '## Release' CHANGELOG.md \ | 
 |                        | sed -E 's|.*Release (.*) \(.*\)|\1|')" | 
 |   else | 
 |     local version="" | 
 |   fi | 
 |  | 
 |   local date="$(git_date)" | 
 |   if [ -z "${version-}" ]; then | 
 |     version="unknown" | 
 |   fi | 
 |   if [ -n "${date-}" ]; then | 
 |     date="$(date +%Y-%m-%d)" | 
 |   fi | 
 |   echo "${version}-${date}" | 
 | } | 
 |  | 
 | if [[ ${PLATFORM} == "darwin" ]]; then | 
 |   function md5_file() { | 
 |     echo $(cat $1 | md5) $1 | 
 |   } | 
 | else | 
 |   function md5_file() { | 
 |     md5sum $1 | 
 |   } | 
 | fi | 
 |  | 
 | # Gets the java version from JAVA_HOME | 
 | # Sets JAVAC and JAVAC_VERSION with respectively the path to javac and | 
 | # the version of javac. | 
 | function get_java_version() { | 
 |   test -z "$JAVA_HOME" && fail "JDK not found, please set \$JAVA_HOME." | 
 |   JAVAC="${JAVA_HOME}/bin/javac" | 
 |   [[ -x "${JAVAC}" ]] \ | 
 |     || fail "JAVA_HOME ($JAVA_HOME) is not a path to a working JDK." | 
 |  | 
 |   JAVAC_VERSION=$("${JAVAC}" -version 2>&1) | 
 |   if [[ "$JAVAC_VERSION" =~ javac\ ((1\.)?([789]|[1-9][0-9])).*$ ]]; then | 
 |     JAVAC_VERSION=1.${BASH_REMATCH[3]} | 
 |   else | 
 |     fail \ | 
 |       "Cannot determine JDK version, please set \$JAVA_HOME.\n" \ | 
 |       "\$JAVAC_VERSION is \"${JAVAC_VERSION}\"" | 
 |   fi | 
 | } | 
 |  | 
 | # Return the target that a bind point to, using Bazel query. | 
 | function get_bind_target() { | 
 |   $BAZEL --bazelrc=${BAZELRC} ${BAZEL_DIR_STARTUP_OPTIONS} \ | 
 |     query "deps($1, 1) - $1" | 
 | } | 
 |  | 
 | # Create a link for a directory on the filesystem | 
 | function link_dir() { | 
 |   local source=$1 | 
 |   local dest=$2 | 
 |  | 
 |   if [[ "${PLATFORM}" == "windows" ]]; then | 
 |     local -r s="$(cygpath -w "$source")" | 
 |     local -r d="$(cygpath -w "$dest")" | 
 |     powershell -command "New-Item -ItemType Junction -Path '$d' -Value '$s'" | 
 |   else | 
 |     ln -s "${source}" "${dest}" | 
 |   fi | 
 | } | 
 |  | 
 | function link_file() { | 
 |   local source=$1 | 
 |   local dest=$2 | 
 |  | 
 |   if [[ "${PLATFORM}" == "windows" ]]; then | 
 |     # Attempt creating a symlink to the file. This is supported without | 
 |     # elevation (Administrator privileges) on Windows 10 version 1709 when | 
 |     # Developer Mode is enabled. | 
 |     local -r s="$(cygpath -w "$source")" | 
 |     local -r d="$(cygpath -w "$dest")" | 
 |     if ! powershell -command "New-Item -ItemType SymbolicLink -Path '$d' -Value '$s'"; then | 
 |       # If the previous call failed to create a symlink, just copy the file. | 
 |       cp "$source" "$dest" | 
 |     fi | 
 |   else | 
 |     ln -s "${source}" "${dest}" | 
 |   fi | 
 | } | 
 |  | 
 | # Link direct children (subdirectories and files) of a directory. | 
 | # Usage: | 
 | #   link_children "$PWD" "tools" "${BAZEL_TOOLS_REPO}" | 
 | # This creates: | 
 | #   ${BAZEL_TOOLS_REPO}/tools/android -> $PWD/tools/android | 
 | #   ${BAZEL_TOOLS_REPO}/tools/bash -> $PWD/tools/bash | 
 | #   ... and so on for all files and directories directly under "tools". | 
 | function link_children() { | 
 |   local -r source_dir=${1%/} | 
 |   local -r source_subdir=${2%/} | 
 |   local -r dest_dir=${3%/} | 
 |  | 
 |   for e in $(find "${source_dir}/${source_subdir}" -mindepth 1 -maxdepth 1 -type d); do | 
 |     local dest_path="${dest_dir}/${e#$source_dir/}" | 
 |     if [[ ! -d "$dest_path" ]]; then | 
 |       link_dir "$e" "$dest_path" | 
 |     fi | 
 |   done | 
 |   for e in $(find "${source_dir}/${source_subdir}" -mindepth 1 -maxdepth 1 -type f); do | 
 |     local dest_path="${dest_dir}/${e#$source_dir/}" | 
 |     if [[ ! -f "$dest_path" ]]; then | 
 |       link_file "$e" "$dest_path" | 
 |     fi | 
 |   done | 
 | } |