Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add env and env_inherit to native_binary and native_test (using @bazel_features) #484

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5e06f39
Add `env` and `env_inherit` to `native_binary` and `native_test`
redsun82 Dec 20, 2023
f59ff4a
Add test for `env` and `env_inherit`
redsun82 Dec 21, 2023
4dc1f9a
Make env and env_inherit parameters of native_binary depend on bazel …
redsun82 Dec 21, 2023
10ea0af
Update docs
redsun82 Dec 21, 2023
70e6b77
Update patch indexes
redsun82 Dec 21, 2023
6e83bfe
Fix windows compilation of `assertenv.cc`
redsun82 Dec 21, 2023
d53f286
Autoformat
redsun82 Dec 21, 2023
336176f
Autoformat correctly
redsun82 Dec 21, 2023
b2b6677
Tweak `env_test` for Windows
redsun82 Dec 21, 2023
df44fa9
Lint
redsun82 Dec 21, 2023
5a73fbe
Mention bazel version in native_binary docs
redsun82 Dec 21, 2023
2453f16
Fix formatting
redsun82 Dec 21, 2023
20acd19
Generalize again test to windows
redsun82 Dec 21, 2023
9ce0e55
Use `bazel_features`
redsun82 Jan 11, 2024
f1bd4e0
Add missing directory and fix docs
redsun82 Jan 11, 2024
165e7ef
Fix formatting
redsun82 Jan 11, 2024
c23d409
Merge branch 'main' into env-native-binary-using-features
redsun82 Jun 13, 2024
f05da82
Update `bazel_features`
redsun82 Jun 13, 2024
02c2708
Update `MODULE.bazle-remove-override.patch`
redsun82 Jun 13, 2024
f86cde0
Add location expansion to `env`
redsun82 Jun 13, 2024
798c1a7
Update docs
redsun82 Jun 13, 2024
a7c1415
Fix `--noenable_bzlmod` checks
redsun82 Jun 13, 2024
b9cc025
Remove unneeded backward compatibility code
redsun82 Jun 26, 2024
b8adf7f
Fix formatting
redsun82 Jun 26, 2024
1ca13a4
Remove unneeded code
redsun82 Jun 26, 2024
bcbc4fd
Merge branch 'main' into env-native-binary-using-features
Aug 26, 2024
8f76bb6
Clean up test code
Aug 26, 2024
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
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ register_toolchains(
"//toolchains/unittest:bash_toolchain",
)

bazel_dep(name = "platforms", version = "0.0.4")
bazel_dep(name = "platforms", version = "0.0.9")
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there was a warning about a dependency pulling this version in

bazel_dep(name = "rules_license", version = "0.0.7")

### INTERNAL ONLY - lines after this are not included in the release packaging.
Expand Down
7 changes: 5 additions & 2 deletions docs/native_binary_doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ don't depend on Bash and work with --shell_executable="".
## native_binary

<pre>
native_binary(<a href="#native_binary-name">name</a>, <a href="#native_binary-src">src</a>, <a href="#native_binary-data">data</a>, <a href="#native_binary-out">out</a>)
native_binary(<a href="#native_binary-name">name</a>, <a href="#native_binary-src">src</a>, <a href="#native_binary-data">data</a>, <a href="#native_binary-out">out</a>, <a href="#native_binary-env">env</a>)
</pre>

Wraps a pre-built binary or script with a binary rule.
Expand All @@ -29,14 +29,15 @@ in genrule.tools for example. You can also augment the binary with runfiles.
| <a id="native_binary-src"></a>src | path of the pre-built executable | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="native_binary-data"></a>data | data dependencies. See https://bazel.build/reference/be/common-definitions#typical.data | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="native_binary-out"></a>out | An output name for the copy of the binary. Defaults to name.exe. (We add .exe to the name by default because it's required on Windows and tolerated on other platforms.) | String | optional | `""` |
| <a id="native_binary-env"></a>env | additional environment variables to set when the target is executed by `bazel`. Values are subject to location expansion for labels in `src` and `data`. | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | `{}` |


<a id="native_test"></a>

## native_test

<pre>
native_test(<a href="#native_test-name">name</a>, <a href="#native_test-src">src</a>, <a href="#native_test-data">data</a>, <a href="#native_test-out">out</a>)
native_test(<a href="#native_test-name">name</a>, <a href="#native_test-src">src</a>, <a href="#native_test-data">data</a>, <a href="#native_test-out">out</a>, <a href="#native_test-env">env</a>, <a href="#native_test-env_inherit">env_inherit</a>)
</pre>

Wraps a pre-built binary or script with a test rule.
Expand All @@ -53,5 +54,7 @@ the binary with runfiles.
| <a id="native_test-src"></a>src | path of the pre-built executable | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="native_test-data"></a>data | data dependencies. See https://bazel.build/reference/be/common-definitions#typical.data | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="native_test-out"></a>out | An output name for the copy of the binary. Defaults to name.exe. (We add .exe to the name by default because it's required on Windows and tolerated on other platforms.) | String | optional | `""` |
| <a id="native_test-env"></a>env | additional environment variables to set when the target is executed by `bazel`. Values are subject to location expansion for labels in `src` and `data`. | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | `{}` |
| <a id="native_test-env_inherit"></a>env_inherit | additional environment variables to inherit from the external environment when the test is executed by `bazel test`. | List of strings | optional | `[]` |


49 changes: 32 additions & 17 deletions rules/native_binary.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,25 @@ def _impl_rule(ctx):
)
runfiles = ctx.runfiles(files = ctx.files.data)

# Bazel 4.x LTS does not support `merge_all`.
# TODO: remove `merge` branch once we drop support for Bazel 4.x.
if hasattr(runfiles, "merge_all"):
runfiles = runfiles.merge_all([
d[DefaultInfo].default_runfiles
for d in ctx.attr.data + [ctx.attr.src]
])
else:
for d in ctx.attr.data:
runfiles = runfiles.merge(d[DefaultInfo].default_runfiles)
runfiles = runfiles.merge(ctx.attr.src[DefaultInfo].default_runfiles)
runfiles = runfiles.merge_all([
d[DefaultInfo].default_runfiles
for d in ctx.attr.data + [ctx.attr.src]
])

return DefaultInfo(
executable = out,
files = depset([out]),
runfiles = runfiles,
)
targets = [ctx.attr.src] + ctx.attr.data
env = {k: ctx.expand_location(v, targets) for k, v in ctx.attr.env.items()}

return [
DefaultInfo(
executable = out,
files = depset([out]),
runfiles = runfiles,
),
RunEnvironmentInfo(
environment = env,
inherited_environment = getattr(ctx.attr, "env_inherit", []),
),
]

_ATTRS = {
"src": attr.label(
Expand All @@ -70,6 +72,12 @@ _ATTRS = {
"name.exe. (We add .exe to the name by default because it's " +
"required on Windows and tolerated on other platforms.)",
),
"env": attr.string_dict(
doc = "additional environment variables to set when the target is executed by " +
"`bazel`. Values are subject to location expansion for labels in `src` and " +
"`data`.",
default = {},
),
}

native_binary = rule(
Expand All @@ -86,7 +94,14 @@ in genrule.tools for example. You can also augment the binary with runfiles.

native_test = rule(
implementation = _impl_rule,
attrs = _ATTRS,
attrs = dict(
_ATTRS,
env_inherit = attr.string_list(
doc = "additional environment variables to inherit from the external " +
"environment when the test is executed by `bazel test`. ",
default = [],
),
),
test = True,
doc = """
Wraps a pre-built binary or script with a test rule.
Expand Down
29 changes: 29 additions & 0 deletions tests/native_binary/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ cc_binary(
deps = ["@bazel_tools//tools/cpp/runfiles"],
)

cc_binary(
name = "assertenv",
srcs = ["assertenv.cc"],
)

# A rule that copies "assertarg"'s output as an opaque executable, simulating a
# binary that's not built from source and needs to be wrapped in native_binary.
copy_file(
Expand All @@ -54,6 +59,16 @@ copy_file(
is_executable = True,
)

copy_file(
name = "copy_assertenv_exe",
src = ":assertenv",
# On Windows we need the ".exe" extension.
# On other platforms the extension doesn't matter.
# Therefore we can use ".exe" on every platform.
out = "assertenv_copy.exe",
is_executable = True,
)

_ARGS = [
"'a b'",
"c\\ d",
Expand Down Expand Up @@ -121,3 +136,17 @@ native_test(
# Therefore we can use ".exe" on every platform.
out = "data_from_binary_test.exe",
)

native_test(
name = "env_test",
src = ":copy_assertenv_exe",
data = ["BUILD"],
env = {
"TEST_ENV_VAR": "test_env_var_value",
"TEST_ENV_VAR_WITH_EXPANSION": "|$(rootpath BUILD)|",
},
env_inherit = [
"HOME", # for POSIX
"APPDATA", # for Windows
],
)
31 changes: 31 additions & 0 deletions tests/native_binary/assertenv.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

bool check(const char *var, const char *expected = nullptr);

int main() {
bool ok = true;
ok = ok && check("TEST_ENV_VAR", "test_env_var_value");
#ifdef _WIN32
ok = ok && check("APPDATA");
#else
ok = ok && check("HOME");
#endif
ok =
ok && check("TEST_ENV_VAR_WITH_EXPANSION", "|tests/native_binary/BUILD|");
return ok ? 0 : 1;
}

bool check(const char *var, const char *expected) {
const char *actual = getenv(var);
if (actual == nullptr) {
fprintf(stderr, "expected %s\n", var);
return false;
}
if (expected && strcmp(actual, expected) != 0) {
fprintf(stderr, "expected %s=%s, got %s\n", var, expected, actual);
return false;
}
return true;
}