refactor: make it a new public api

This commit is contained in:
Alex Eagle 2022-09-20 08:05:18 -07:00
parent 25d2a3027f
commit ef3bb75be6
9 changed files with 155 additions and 67 deletions

View File

@ -47,6 +47,10 @@ Installation instructions are included on each release:
- [run_binary](docs/run_binary.md) Like skylib's run_binary but adds directory output support.
- [stamping](docs/stamping.md) Support version stamping in custom rules.
## Running programs
- [wrap_binary](docs/wrap_binary.md) Compatibility shims which wrap binaries to adapt to the Bazel execution environment.
## Generating documentation
- [docs](docs/docs.md) Rules for generating docs and stamping tests to ensure they are up to date.

View File

@ -73,6 +73,11 @@ stardoc_with_diff_test(
bzl_library_target = "//lib:run_binary",
)
stardoc_with_diff_test(
name = "wrap_binary",
bzl_library_target = "//lib:wrap_binary",
)
stardoc_with_diff_test(
name = "transitions",
bzl_library_target = "//lib:transitions",

21
docs/paths.md generated
View File

@ -2,27 +2,6 @@
Public API
<a id="chdir_binary"></a>
## chdir_binary
<pre>
chdir_binary(<a href="#chdir_binary-name">name</a>, <a href="#chdir_binary-binary">binary</a>, <a href="#chdir_binary-chdir">chdir</a>, <a href="#chdir_binary-kwargs">kwargs</a>)
</pre>
Wrap a *_binary to be executed under a given directory.
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="chdir_binary-name"></a>name | Name of the rule. | none |
| <a id="chdir_binary-binary"></a>binary | Label of an executable target to wrap. | none |
| <a id="chdir_binary-chdir"></a>chdir | Argument for the <code>cd</code> command, the default is commonly used with <code>bazel run</code> to run the program in the root of the Bazel workspace, in the source tree. | <code>"$BUILD_WORKSPACE_DIRECTORY"</code> |
| <a id="chdir_binary-kwargs"></a>kwargs | Additional named arguments for the resulting sh_binary rule. | none |
<a id="relative_file"></a>
## relative_file

40
docs/wrap_binary.md generated Normal file
View File

@ -0,0 +1,40 @@
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
Wraps binary rules to make them more compatible with Bazel.
Currently supports only Bash as the wrapper language, not cmd.exe.
Future additions might include:
- wrap a binary such that it sees a tty on stdin
- manipulate arguments or environment variables
- redirect stdout/stderr, e.g. to silence buildspam on success
- intercept exit code, e.g. to make an "expect_fail"
- change user, e.g. to deal with containerized build running as root, but tool requires non-root
- intercept signals, e.g. to make a tool behave as a Bazel persistent worker
<a id="chdir_binary"></a>
## chdir_binary
<pre>
chdir_binary(<a href="#chdir_binary-name">name</a>, <a href="#chdir_binary-binary">binary</a>, <a href="#chdir_binary-chdir">chdir</a>, <a href="#chdir_binary-kwargs">kwargs</a>)
</pre>
Wrap a *_binary to be executed under a given working directory.
Note: under `bazel run`, this is similar to the `--run_under "cd $PWD &&"` trick, but is hidden
from the user so they don't need to know about that flag.
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="chdir_binary-name"></a>name | Name of the rule. | none |
| <a id="chdir_binary-binary"></a>binary | Label of an executable target to wrap. | none |
| <a id="chdir_binary-chdir"></a>chdir | Argument for the <code>cd</code> command, the default is commonly used with <code>bazel run</code> to run the program in the root of the Bazel workspace, in the source tree. | <code>"$BUILD_WORKSPACE_DIRECTORY"</code> |
| <a id="chdir_binary-kwargs"></a>kwargs | Additional named arguments for the resulting sh_binary rule. | none |

View File

@ -48,10 +48,7 @@ bzl_library(
bzl_library(
name = "paths",
srcs = ["paths.bzl"],
deps = [
"//lib/private:paths",
"@bazel_skylib//rules:write_file",
],
deps = ["//lib/private:paths"],
)
bzl_library(
@ -126,6 +123,16 @@ bzl_library(
deps = ["//lib/private:run_binary"],
)
bzl_library(
name = "wrap_binary",
srcs = ["wrap_binary.bzl"],
deps = [
":paths",
"//lib/private:run_binary",
"@bazel_skylib//rules:write_file",
],
)
bzl_library(
name = "repo_utils",
srcs = ["repo_utils.bzl"],

View File

@ -1,6 +1,5 @@
"Public API"
load("@bazel_skylib//rules:write_file.bzl", "write_file")
load("//lib/private:paths.bzl", "paths")
relative_file = paths.relative_file
@ -23,44 +22,3 @@ source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v2 ---
"""
def chdir_binary(name, binary, chdir = "$BUILD_WORKSPACE_DIRECTORY", **kwargs):
"""Wrap a *_binary to be executed under a given directory.
Args:
name: Name of the rule.
binary: Label of an executable target to wrap.
chdir: Argument for the `cd` command, the default is commonly used with `bazel run`
to run the program in the root of the Bazel workspace, in the source tree.
**kwargs: Additional named arguments for the resulting sh_binary rule.
"""
script = "_{}_chdir.sh".format(name)
# It's 2022 and java_binary still cannot be told to cd to the source directory under bazel run.
write_file(
name = "_{}_wrap".format(name),
out = script,
content = [
"#!/usr/bin/env bash",
BASH_RLOCATION_FUNCTION,
# Remove external/ prefix that is included in $(rootpath) but not supported by $(rlocation)
"bin=$(rlocation ${1#external/})",
# Consume the first argument
"shift",
# Fix the working directory
"cd " + chdir,
# Replace the current process
"exec $bin $@",
],
is_executable = True,
)
native.sh_binary(
name = name,
srcs = [script],
args = ["$(rootpath {})".format(binary)] + kwargs.pop("args", []),
data = [binary],
deps = ["@bazel_tools//tools/bash/runfiles"],
**kwargs
)

View File

@ -0,0 +1,25 @@
load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("@aspect_bazel_lib//lib:wrap_binary.bzl", "chdir_binary")
sh_binary(
name = "fixture",
srcs = ["needs-working-dir.sh"],
)
chdir_binary(
name = "wrap",
binary = "fixture",
chdir = package_name(),
)
run_binary(
name = "assert",
outs = ["thing"],
tool = "wrap",
)
build_test(
name = "test",
targets = ["assert"],
)

View File

@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -o errexit -o nounset -o pipefail
if [ "$(dirname $(pwd))" != "wrap_binary" ]; then
echo >&2 "this program must be run with the working directory inside the package, but was $(pwd)"
exit 1
fi

62
lib/wrap_binary.bzl Normal file
View File

@ -0,0 +1,62 @@
"""Wraps binary rules to make them more compatible with Bazel.
Currently supports only Bash as the wrapper language, not cmd.exe.
Future additions might include:
- wrap a binary such that it sees a tty on stdin
- manipulate arguments or environment variables
- redirect stdout/stderr, e.g. to silence buildspam on success
- intercept exit code, e.g. to make an "expect_fail"
- change user, e.g. to deal with containerized build running as root, but tool requires non-root
- intercept signals, e.g. to make a tool behave as a Bazel persistent worker
"""
load(":paths.bzl", "BASH_RLOCATION_FUNCTION")
load(":utils.bzl", "to_label")
load("@bazel_skylib//rules:write_file.bzl", "write_file")
def chdir_binary(name, binary, chdir = "$BUILD_WORKSPACE_DIRECTORY", **kwargs):
"""Wrap a *_binary to be executed under a given working directory.
Note: under `bazel run`, this is similar to the `--run_under "cd $PWD &&"` trick, but is hidden
from the user so they don't need to know about that flag.
Args:
name: Name of the rule.
binary: Label of an executable target to wrap.
chdir: Argument for the `cd` command.
By default, supports using the binary under `bazel run` by running program in the
root of the Bazel workspace, in the source tree.
**kwargs: Additional named arguments for the resulting sh_binary rule.
"""
script = "_{}_chdir.sh".format(name)
binary = to_label(binary)
# It's 2022 and java_binary still cannot be told to cd to the source directory under bazel run.
write_file(
name = "_{}_wrap".format(name),
out = script,
content = [
"#!/usr/bin/env bash",
BASH_RLOCATION_FUNCTION,
# Remove external/ prefix that is included in $(rootpath) but not supported by $(rlocation)
"bin=$(rlocation ${1#external/})",
# Consume the first argument
"shift",
# Fix the working directory
"cd " + chdir,
# Replace the current process
"exec $bin $@",
],
is_executable = True,
)
native.sh_binary(
name = name,
srcs = [script],
args = ["$(rootpath {})".format(binary)] + kwargs.pop("args", []),
data = [binary],
deps = ["@bazel_tools//tools/bash/runfiles"],
**kwargs
)