RUNFILES detection in executable scripts is hard
- Dominant language
- Java
- Stars
- 25.8k
- Forks
- 4.6k
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 72
Description
In order for executable rules to be able to properly refer to files that are included as `data` deps, those executables need to know what the `RUNFILES` directory is.
There are many contexts from which an executable can be invoked, so it's common for the templates of such executable rules to contain boilerplate code that tries to deduce `RUNFILES` with code that looks similar to the following:
```bash
if [[ -n "$TEST_SRCDIR" && -d "$TEST_SRCDIR" ]]; then
# use $TEST_SRCDIR if set.
export RUNFILES="$TEST_SRCDIR"
elif [[ -z "$RUNFILES" ]]; then
# canonicalize the entrypoint.
pushd "$(dirname "$0")" > /dev/null
abs_entrypoint="$(pwd -P)/$(basename "$0")"
popd > /dev/null
if [[ -e "${abs_entrypoint}.runfiles" ]]; then
# runfiles dir found alongside entrypoint.
export RUNFILES="${abs_entrypoint}.runfiles"
elif [[ "$abs_entrypoint" == *".runfiles/"* ]]; then
# runfiles dir found in entrypoint path.
export RUNFILES="${abs_entrypoint%.runfiles/*}.runfiles"
else
# runfiles dir not found: fall back on current directory.
export RUNFILES="$PWD"
fi
fi
```
Blocks of code like this end up sprinkled throughout a project's Bazel codebase, which is (a) not very maintainable, and (b) fragile. And note that the code above only attempts to work on Mac and Linux - with Windows support, it'd look even worse.
Is there any way Bazel could guarantee that `$RUNFILES` will always be set when executable targets are invoked from the following contexts:
* `bazel run`
* `bazel test`
* Being invoked via a `genrule`
If those guarantees were made, then developers would only have to worry about deducing `RUNFILES` when the script was invoked directly at the command-line, in which case `RUNFILES` is basically `.runfiles/`
Contributor guide
Assessment
This issue has not been assessed yet.