Skip to content

Commit

Permalink
Bash, runfiles lib v2: shorter init code
Browse files Browse the repository at this point in the history
This CL rolls forward commit 229fe56, which was
rolled back by commit 4f9110e.

Reason for roll-forward:
- Skydoc project on Bazel CI was broke because it
  used "set -e" instead of "set -euo pipefail",
  but the new runfiles library forced
  "set -euo pipefail" on it

Differences between original and roll-forward:
- remove "set -euo pipefail" from runfiles.bash,
  and move it to init code (like in v1 init), so
  users can employ a less strict mode
- added comments to runfiles.bash explaining
  version compatibility
- added test to ensure v1 init code can load v2
  library

Original description:

The Bash Runfiles Library is now at its version 2.

The new version has a shorter copy-pasted init
code ("stanza") than v1.

The init code does the bare minimum to load the
runfiles library. Everything else is done in the
library itself (e.g. export RUNFILES_* envvars).

The rlocation() function is unchanged.

To demonstrate correctness, I updated:
- two mock binaries
- two actual tests

RELNOTES[NEW]: Bash, runfiles: the copy-pasted init code of the Bash runfiles library is now shorter, see `tools/bash/runfiles/runfiles.bash`. To use the new init code, you need Bazel 0.27 or newer. The old (longer) init code still works.

Closes #8461.

PiperOrigin-RevId: 250258548
  • Loading branch information
laszlocsomor authored and copybara-github committed May 28, 2019
1 parent a65b047 commit 934045f
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 116 deletions.
31 changes: 10 additions & 21 deletions src/test/py/bazel/testdata/runfiles_test/bar/bar.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.

set -euo pipefail
# --- begin runfiles.bash initialization ---
if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$0.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.runfiles/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
export RUNFILES_DIR="$0.runfiles"
fi
fi
if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
"$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)"
else
echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash"
exit 1
fi
# --- end runfiles.bash initialization ---
# --- begin runfiles.bash initialization v2 ---
# Copy-pasted from the Bazel Bash runfiles library v2.
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v2 ---

echo "Hello Bash Bar!"
echo "rloc=$(rlocation "foo_ws/bar/bar-sh-data.txt")"
39 changes: 14 additions & 25 deletions src/test/py/bazel/testdata/runfiles_test/foo/foo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.

set -euo pipefail
# --- begin runfiles.bash initialization ---
if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$0.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.runfiles/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
export RUNFILES_DIR="$0.runfiles"
fi
fi
if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
"$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)"
else
echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash"
exit 1
fi
# --- end runfiles.bash initialization ---
# --- begin runfiles.bash initialization v2 ---
# Copy-pasted from the Bazel Bash runfiles library v2.
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v2 ---

if ! type rlocation >&/dev/null; then
echo >&2 "ERROR: rlocation is undefined"
Expand All @@ -42,16 +31,16 @@ fi

case "$(uname -s | tr [:upper:] [:lower:])" in
msys*|mingw*|cygwin*)
function is_windows() { true ; }
is_windows=true
;;
*)
function is_windows() { false ; }
is_windows=false
;;
esac

function child_binary_name() {
local lang=$1
if is_windows; then
if "$is_windows"; then
echo "foo_ws/bar/bar-${lang}.exe"
else
echo "foo_ws/bar/bar-${lang}"
Expand All @@ -65,7 +54,7 @@ function main() {
# Run a subprocess, propagate the runfiles envvar to it. The subprocess will
# use this process's runfiles manifest or runfiles directory.
runfiles_export_envvars
if is_windows; then
if "$is_windows"; then
export SYSTEMROOT="${SYSTEMROOT:-}"
fi
for lang in py java sh cc; do
Expand Down
31 changes: 10 additions & 21 deletions src/test/shell/bazel/help_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,16 @@
#
# Test the help command.

set -euo pipefail
# --- begin runfiles.bash initialization ---
if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$0.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.runfiles/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
export RUNFILES_DIR="$0.runfiles"
fi
fi
if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
"$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)"
else
echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash"
exit 1
fi
# --- end runfiles.bash initialization ---
# --- begin runfiles.bash initialization v2 ---
# Copy-pasted from the Bazel Bash runfiles library v2.
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v2 ---

source "$(rlocation "io_bazel/src/test/shell/integration_test_setup.sh")" \
|| { echo "integration_test_setup.sh not found!" >&2; exit 1; }
Expand Down
7 changes: 7 additions & 0 deletions src/test/shell/integration/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,13 @@ sh_test(
deps = ["@bazel_tools//tools/bash/runfiles"],
)

sh_test(
name = "bash_runfiles_v1_test",
srcs = ["bash_runfiles_v1_test.sh"],
data = ["BUILD"],
deps = ["@bazel_tools//tools/bash/runfiles"],
)

########################################################################
# Test suites.

Expand Down
32 changes: 10 additions & 22 deletions src/test/shell/integration/aquery_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# --- begin runfiles.bash initialization ---
# Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash).
set -euo pipefail
if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$0.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.runfiles/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
export RUNFILES_DIR="$0.runfiles"
fi
fi
if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
"$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)"
else
echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash"
exit 1
fi
# --- end runfiles.bash initialization ---
# --- begin runfiles.bash initialization v2 ---
# Copy-pasted from the Bazel Bash runfiles library v2.
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v2 ---

source "$(rlocation "io_bazel/src/test/shell/integration_test_setup.sh")" \
|| { echo "integration_test_setup.sh not found!" >&2; exit 1; }
Expand Down
44 changes: 44 additions & 0 deletions src/test/shell/integration/bash_runfiles_v1_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/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.

# Test Bazel Bash runfiles library v1 init code loading the v2 library.

# --- begin runfiles.bash initialization ---
# Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash).
set -euo pipefail
if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$0.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.runfiles/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
export RUNFILES_DIR="$0.runfiles"
fi
fi
if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
"$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)"
else
echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash"
exit 1
fi
# --- end runfiles.bash initialization ---

path="$(rlocation "io_bazel/src/test/shell/integration/BUILD")"
[[ -n "$path" ]] || fail "Could not load data file"
[[ -f "$path" ]] || fail "Path does not exist"
69 changes: 42 additions & 27 deletions tools/bash/runfiles/runfiles.bash
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# Runfiles lookup library for Bazel-built Bash binaries and tests.
# Runfiles lookup library for Bazel-built Bash binaries and tests, version 2.
#
# VERSION HISTORY:
# - version 2: Shorter init code.
# Features:
# - "set -euo pipefail" only at end of init code.
# "set -e" breaks the source <path1> || source <path2> || ... scheme on
# macOS, because it terminates if path1 does not exist.
# - Not exporting any environment variables in init code.
# This is now done in runfiles.bash itself.
# Compatibility:
# - The v1 init code can load the v2 library, i.e. if you have older source
# code (still using v1 init) then you can build it with newer Bazel (which
# contains the v2 library).
# - The reverse is not true: the v2 init code CANNOT load the v1 library,
# i.e. if your project (or any of its external dependencies) use v2 init
# code, then you need a newer Bazel version (which contains the v2
# library).
# - version 1: Original Bash runfiles library.
#
# ENVIRONMENT:
# - Use the example code provided below. It initializes the environment
# variables required by this script.
# - If RUNFILES_LIB_DEBUG=1 is set, the script will print diagnostic messages to
# stderr.
#
Expand All @@ -35,34 +51,33 @@
# up the library's runtime location, thus we have a chicken-and-egg problem.
# Insert the following code snippet to the top of your main script:
#
# # --- begin runfiles.bash initialization ---
# # Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash).
# set -euo pipefail
# if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
# if [[ -f "$0.runfiles_manifest" ]]; then
# export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
# elif [[ -f "$0.runfiles/MANIFEST" ]]; then
# export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
# elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
# export RUNFILES_DIR="$0.runfiles"
# fi
# fi
# if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
# source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
# elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
# source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
# "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)"
# else
# echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash"
# exit 1
# fi
# # --- end runfiles.bash initialization ---
# # --- begin runfiles.bash initialization v2 ---
# # Copy-pasted from the Bazel Bash runfiles library v2.
# set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
# source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
# source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
# source "$0.runfiles/$f" 2>/dev/null || \
# source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
# source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
# { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# # --- end runfiles.bash initialization v2 ---
#
#
# 3. Use rlocation to look up runfile paths:
# 3. Use rlocation to look up runfile paths.
#
# cat "$(rlocation my_workspace/path/to/my/data.txt)"
#

if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$0.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.runfiles/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
export RUNFILES_DIR="$0.runfiles"
fi
fi

case "$(uname -s | tr [:upper:] [:lower:])" in
msys*|mingw*|cygwin*)
# matches an absolute Windows path
Expand All @@ -84,7 +99,7 @@ function rlocation() {
echo >&2 "INFO[runfiles.bash]: rlocation($1): absolute path, return"
fi
# If the path is absolute, print it as-is.
echo $1
echo "$1"
elif [[ "$1" == ../* || "$1" == */.. || "$1" == ./* || "$1" == */./* || "$1" == "*/." || "$1" == *//* ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "ERROR[runfiles.bash]: rlocation($1): path is not normalized"
Expand Down

0 comments on commit 934045f

Please sign in to comment.