Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ buildifier: 8.2.1
matrix:
platform:
- ubuntu2004
- ubuntu2004_arm64
- macos
- macos_arm64
- windows
legacy_bazel:
- 7.*
Expand Down Expand Up @@ -62,3 +64,51 @@ tasks:
- "//tests/..."
test_targets:
- "//tests/..."
test_module_bzlmod_shell_runfiles:
name: "Test module (Bzlmod + Shell Runfiles)"
working_directory: "tests/bcr"
bazel: ${{ modern_bazel }}
platform: ${{ platform }}
build_flags:
- "--enable_bzlmod"
- "--@rules_shell//shell/settings:experimental_use_shell_runfiles=True"
build_targets:
- "//..."
test_flags:
- "--enable_bzlmod"
- "--@rules_shell//shell/settings:experimental_use_shell_runfiles=True"
test_targets:
- "//..."
test_posix_shell_runfiles:
# Explicit dash coverage for the POSIX shell runfiles library. Local
# repro: bazel test --config=posix_shell //tests/runfiles/...
name: "POSIX Shell Runfiles (dash, ${{modern_bazel}})"
bazel: ${{ modern_bazel }}
platform: ubuntu2004
shell_commands:
- "/bin/dash -c 'echo dash ready'"
build_flags:
- "--config=posix_shell"
build_targets:
- "//tests/runfiles:runfiles_sh_test"
test_flags:
- "--config=posix_shell"
test_targets:
- "//tests/runfiles:runfiles_sh_test"
test_module_workspace_shell_runfiles:
name: "Test module (${{legacy_bazel}}, WORKSPACE + Shell Runfiles)"
working_directory: "tests/bcr"
bazel: ${{ legacy_bazel }}
platform: ${{ platform }}
build_flags:
- "--noenable_bzlmod"
- "--enable_workspace"
- "--@rules_shell//shell/settings:experimental_use_shell_runfiles=True"
build_targets:
- "//..."
test_flags:
- "--noenable_bzlmod"
- "--enable_workspace"
- "--@rules_shell//shell/settings:experimental_use_shell_runfiles=True"
test_targets:
- "//..."
6 changes: 6 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
common --check_direct_dependencies=off
common --keep_going

# --config=posix_shell forces the sh_toolchain to resolve to /bin/dash via
# BAZEL_SH. Used by the `test_posix_shell_runfiles` presubmit task and
# available locally: `bazel test --config=posix_shell //tests/runfiles/...`.
# Only takes effect on hosts where /bin/dash exists (i.e. Debian/Ubuntu).
common:posix_shell --repo_env=BAZEL_SH=/bin/dash
3 changes: 2 additions & 1 deletion .bcr/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ bcr_test_module:
- debian10
- ubuntu2004
- macos
- macos_arm64
- windows
bazel: [6.x, 7.x, 8.x]
bazel: [7.x, 8.x, 9.x]
tasks:
run_test_module:
name: Run test module
Expand Down
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use_repo(sh_configure, "local_config_shell")

register_toolchains("@local_config_shell//:all")

bazel_dep(name = "rules_shellcheck", version = "0.6.2", dev_dependency = True)
bazel_dep(name = "rules_shellcheck", version = "0.6.4", dev_dependency = True)
bazel_dep(name = "rules_testing", version = "0.9.0", dev_dependency = True)
bazel_dep(name = "stardoc", version = "0.8.1", dev_dependency = True)
bazel_dep(name = "with_cfg.bzl", version = "0.14.1", dev_dependency = True)
1 change: 1 addition & 0 deletions shell/private/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ bzl_library(
"sh_test.bzl",
],
visibility = ["//shell:__pkg__"],
deps = ["@bazel_skylib//rules:common_settings"],
)
15 changes: 14 additions & 1 deletion shell/private/sh_executable.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@

"""Common code for sh_binary and sh_test rules."""

load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load(":providers.bzl", "ShBinaryInfo", "ShInfo")

visibility(["//shell"])

_SH_TOOLCHAIN_TYPE = Label("//shell:toolchain_type")

_BASH_RUNFILES_INIT_PATH = "bazel_tools/tools/bash/runfiles/runfiles.bash"
_SHELL_RUNFILES_INIT_PATH = "shell/runfiles/runfiles.sh"

def _to_rlocation_path(ctx, file):
if file.short_path.startswith("../"):
return file.short_path[3:]
Expand Down Expand Up @@ -49,12 +53,16 @@ def _sh_executable_impl(ctx):
else:
shell = ctx.toolchains[_SH_TOOLCHAIN_TYPE].path
shebang = "#!{}".format(shell)
if ctx.attr._use_shell_runfiles[BuildSettingInfo].value:
init_path = _SHELL_RUNFILES_INIT_PATH
else:
init_path = _BASH_RUNFILES_INIT_PATH
ctx.actions.write(
entrypoint,
content = """{shebang}

# --- begin runfiles.bash initialization v3 ---
set -uo pipefail; set +e; f=bazel_tools/tools/bash/runfiles/runfiles.bash
set -uo pipefail; set +e; f={init_path}
# shellcheck disable=SC1090
source "${{RUNFILES_DIR:-/dev/null}}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${{RUNFILES_MANIFEST_FILE:-/dev/null}}" | cut -f2- -d' ')" 2>/dev/null || \
Expand All @@ -69,6 +77,7 @@ runfiles_export_envvars
exec "$(rlocation "{src}")" "$@"
""".format(
shebang = shebang,
init_path = init_path,
src = _to_rlocation_path(ctx, src),
),
is_executable = True,
Expand Down Expand Up @@ -259,6 +268,10 @@ The file containing the shell script.
"_runfiles_dep": attr.label(
default = Label("//shell/runfiles"),
),
"_use_shell_runfiles": attr.label(
default = Label("//shell/settings:experimental_use_shell_runfiles"),
providers = [BuildSettingInfo],
),
"_windows_constraint": attr.label(
default = "@platforms//os:windows",
),
Expand Down
72 changes: 70 additions & 2 deletions shell/runfiles/BUILD
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
load("//shell:sh_library.bzl", "sh_library")
load("//shell/private:root_symlinks.bzl", "ROOT_SYMLINKS_SUPPORTED", "root_symlinks")

config_setting(
name = "use_shell_runfiles",
flag_values = {"//shell/settings:experimental_use_shell_runfiles": "true"},
)

alias(
name = "runfiles",
actual = ":runfiles_impl" if ROOT_SYMLINKS_SUPPORTED else "@bazel_tools//tools/bash/runfiles",
actual = select({
":use_shell_runfiles": ":runfiles_sh_impl",
"//conditions:default": ":runfiles_impl" if ROOT_SYMLINKS_SUPPORTED else "@bazel_tools//tools/bash/runfiles",
}),
visibility = ["//visibility:public"],
)

sh_library(
name = "runfiles_impl",
data = [":runfiles_at_legacy_location"],
tags = ["manual"],
visibility = ["//visibility:public"],
deps = [":runfiles_bash"],
)

sh_library(
name = "runfiles_bash",
srcs = ["runfiles.bash"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

root_symlinks(
Expand All @@ -21,7 +38,58 @@ root_symlinks(
tags = ["manual"],
)

sh_library(
name = "runfiles_sh_impl",
data = [
":runfiles_sh_at_documented_location",
":runfiles_sh_at_legacy_location",
],
tags = ["manual"],
visibility = ["//visibility:public"],
deps = [":runfiles_sh"],
)

sh_library(
name = "runfiles_sh",
srcs = ["runfiles.sh"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

# Place runfiles.sh at the root path used by the documented init snippet
# (`f=shell/runfiles/runfiles.sh`). Without this, the file would only appear
# under its repo-prefixed location (e.g. `_main/shell/runfiles/runfiles.sh`
# or `rules_shell+/shell/runfiles/runfiles.sh`) and copy-pasting the snippet
# would fail with `ERROR: cannot find shell/runfiles/runfiles.sh`.
root_symlinks(
name = "runfiles_sh_at_documented_location",
root_symlinks = {
"runfiles.sh": "shell/runfiles/runfiles.sh",
},
tags = ["manual"],
)

# Native `sh_test` (used when Bazel exposes it — legacy 7/8 modes and some
# launcher paths) hardcodes `f=bazel_tools/tools/bash/runfiles/runfiles.bash`
# in its generated launcher and cannot be redirected from Starlark. When the
# `experimental_use_shell_runfiles` flag swaps the `:runfiles` alias to this
# target, that path must still resolve to something sourceable — otherwise
# every native sh_test in the build dies with
# `ERROR: cannot find bazel_tools/tools/bash/runfiles/runfiles.bash`.
# Bash and sh impls never appear in the same runfiles tree (the alias uses a
# mutually-exclusive select), so the shared path is safe.
root_symlinks(
name = "runfiles_sh_at_legacy_location",
root_symlinks = {
"runfiles.sh": "bazel_tools/tools/bash/runfiles/runfiles.bash",
},
tags = ["manual"],
)

exports_files(
["runfiles.bash"],
[
"runfiles.bash",
"runfiles.sh",
],
visibility = ["//tests/runfiles:__pkg__"],
)
Loading