| #!/bin/bash | |
| # Copyright 2026 The Fuchsia Authors. All rights reserved. | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| # A wrapper script to run a Bazel binary with its pre-extracted | |
| # install_base and its embedded JRE. It avoids extracting 164 MiB of | |
| # data to the output_user_root the first time it is invoked, and | |
| # unexpected conflicts with the installed JDK. | |
| # | |
| # Note that this script assumes there is a 'bazel-real' binary and an | |
| # 'install_base' directory next to it. This is normally generated by | |
| # the Fuchsia 'generate_bazel_install.py' script, or the corresponding | |
| # LUCI recipe. | |
| # | |
| # IMPORTANT: The timestamps under install_base/ must be 10 years in the | |
| # future, or Bazel will refuse to run. This is used as a way to check that | |
| # the files have not been tampered with. | |
| set -eo pipefail | |
| # `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 | |
| } | |
| readonly BAZEL_WRAPPER_DIR="$(dirname "$(get_realpath "${BASH_SOURCE[0]}")")" | |
| readonly BAZEL_INSTALL_DIR="${BAZEL_WRAPPER_DIR}" | |
| readonly BAZEL_INSTALL_BASE="${BAZEL_INSTALL_DIR}"/install_base | |
| # Bazel will refuse to run if the timestamps for BAZEL_INSTALL_BASE are | |
| # not at least 10 years in the future. Our CIPD archive does not preserve | |
| # input timestamps, even if they were set correctly by install.sh, so | |
| # reset any files whose mtime is not already in the future. | |
| # | |
| # Don't touch files whose mtime is already in the future: `touch` still | |
| # updates their ctime, and Bazel includes ctime in its FileStateValue for | |
| # `@bazel_tools` (`install_base/embedded_tools`), so doing so invalidates | |
| # `@bazel_tools` and forces Bzlmod module resolution and full package | |
| # reloading on every Bazel invocation. | |
| # | |
| # The mtime check must be per-file rather than based on a single stamp | |
| # file or directory, since a CIPD update can replace arbitrary files deep | |
| # in the tree (see https://fxbug.dev/129051). | |
| # | |
| # STALE_BEFORE must stay just below FUTURE_TIMESTAMP (update them together) | |
| # so that bumping FUTURE_TIMESTAMP also retouches files that were set to | |
| # the previous value. | |
| case "$OSTYPE" in | |
| linux*) | |
| # A future timestamp in a format supported by GNU touch, which does | |
| # not support the same format as BSD touch. | |
| FUTURE_TIMESTAMP="2042-07-29 00:00:00" | |
| STALE_BEFORE="2042-07-28" | |
| find "${BAZEL_INSTALL_BASE}" ! -newermt "${STALE_BEFORE}" \ | |
| -exec touch -d "${FUTURE_TIMESTAMP}" {} + | |
| ;; | |
| darwin*|*bsd) | |
| # A future timestamp that is supported by MacOS filesystems. | |
| # See https://apple.fandom.com/wiki/2040_date_limit | |
| FUTURE_TIMESTAMP=204002050000 | |
| STALE_BEFORE="2040-02-04" | |
| find "${BAZEL_INSTALL_BASE}" ! -newermt "${STALE_BEFORE}" \ | |
| -exec touch -t "${FUTURE_TIMESTAMP}" {} + | |
| ;; | |
| *) | |
| echo >&2 "ERROR: Unsupported system: $OSTYPE" | |
| ;; | |
| esac | |
| exec "${BAZEL_INSTALL_DIR}/bazel-real" \ | |
| --install_base="${BAZEL_INSTALL_DIR}/install_base" \ | |
| --server_javabase="${BAZEL_INSTALL_DIR}/install_base/embedded_tools/jdk" \ | |
| "$@" |