Skip to content

Commit 5711009

Browse files
authored
Add env and env_inherit support to kt_jvm_binary (#1379)
This adds parity with java_binary and kt_jvm_test by allowing kt_jvm_binary to specify environment variables when executed with bazel run. Two new attributes are added: - env: Dictionary of environment variables to set - env_inherit: List of environment variable names to inherit from the shell environment The implementation uses RunEnvironmentInfo provider, following the same pattern as the existing kt_jvm_test support (PR #837). Fixes #1359
1 parent d673361 commit 5711009

File tree

8 files changed

+135
-5
lines changed

8 files changed

+135
-5
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ Also, `kt_jvm_*` rules support the following standard `java_*` rules attributes:
3232
* `resources`
3333
* `resources_strip_prefix`
3434
* `exports`
35-
35+
36+
Additionally, `kt_jvm_binary` and `kt_jvm_test` support environment variable configuration:
37+
* `env` - Dictionary of environment variables to set when the target is executed with `bazel run` or `bazel test`
38+
* `env_inherit` - List of environment variable names to inherit from the shell environment
39+
3640
Android rules also support custom_package for `R.java` generation, `manifest=`, `resource_files`, etc.
3741

3842
Other features:

docs/kotlin.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ Define java compiler options for `kt_jvm_*` rules with java sources.
3737
<pre>
3838
load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_binary")
3939

40-
kt_jvm_binary(<a href="#kt_jvm_binary-name">name</a>, <a href="#kt_jvm_binary-deps">deps</a>, <a href="#kt_jvm_binary-srcs">srcs</a>, <a href="#kt_jvm_binary-data">data</a>, <a href="#kt_jvm_binary-resources">resources</a>, <a href="#kt_jvm_binary-associates">associates</a>, <a href="#kt_jvm_binary-java_stub_template">java_stub_template</a>, <a href="#kt_jvm_binary-javac_opts">javac_opts</a>,
41-
<a href="#kt_jvm_binary-jvm_flags">jvm_flags</a>, <a href="#kt_jvm_binary-kotlinc_opts">kotlinc_opts</a>, <a href="#kt_jvm_binary-main_class">main_class</a>, <a href="#kt_jvm_binary-module_name">module_name</a>, <a href="#kt_jvm_binary-plugins">plugins</a>, <a href="#kt_jvm_binary-resource_jars">resource_jars</a>,
40+
kt_jvm_binary(<a href="#kt_jvm_binary-name">name</a>, <a href="#kt_jvm_binary-deps">deps</a>, <a href="#kt_jvm_binary-srcs">srcs</a>, <a href="#kt_jvm_binary-data">data</a>, <a href="#kt_jvm_binary-resources">resources</a>, <a href="#kt_jvm_binary-associates">associates</a>, <a href="#kt_jvm_binary-env">env</a>, <a href="#kt_jvm_binary-env_inherit">env_inherit</a>, <a href="#kt_jvm_binary-java_stub_template">java_stub_template</a>,
41+
<a href="#kt_jvm_binary-javac_opts">javac_opts</a>, <a href="#kt_jvm_binary-jvm_flags">jvm_flags</a>, <a href="#kt_jvm_binary-kotlinc_opts">kotlinc_opts</a>, <a href="#kt_jvm_binary-main_class">main_class</a>, <a href="#kt_jvm_binary-module_name">module_name</a>, <a href="#kt_jvm_binary-plugins">plugins</a>, <a href="#kt_jvm_binary-resource_jars">resource_jars</a>,
4242
<a href="#kt_jvm_binary-resource_strip_prefix">resource_strip_prefix</a>, <a href="#kt_jvm_binary-runtime_deps">runtime_deps</a>)
4343
</pre>
4444

@@ -60,6 +60,8 @@ It is appropriate for building workspace utilities. `java_binary` should be pref
6060
| <a id="kt_jvm_binary-data"></a>data | The list of files needed by this rule at runtime. See general comments about `data` at [Attributes common to all build rules](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes). | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
6161
| <a id="kt_jvm_binary-resources"></a>resources | A list of files that should be include in a Java jar. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
6262
| <a id="kt_jvm_binary-associates"></a>associates | Kotlin deps who should be considered part of the same module/compilation-unit for the purposes of "internal" access. Such deps must all share the same module space and so a target cannot associate to two deps from two different modules. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
63+
| <a id="kt_jvm_binary-env"></a>env | Environment variables to set when this binary is executed with `bazel run`. Note: for Starlark rules, values are used as-is (no automatic $(location) / make variable expansion). | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | `{}` |
64+
| <a id="kt_jvm_binary-env_inherit"></a>env_inherit | Names of environment variables to inherit from the shell when executed with `bazel run`. | List of strings | optional | `[]` |
6365
| <a id="kt_jvm_binary-java_stub_template"></a>java_stub_template | - | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `"@rules_kotlin//third_party:java_stub_template.txt"` |
6466
| <a id="kt_jvm_binary-javac_opts"></a>javac_opts | Javac options to be used when compiling this target. These opts if provided will be used instead of the ones provided to the toolchain. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
6567
| <a id="kt_jvm_binary-jvm_flags"></a>jvm_flags | A list of flags to embed in the wrapper script generated for running this binary. Note: does not yet support make variable substitution. | List of strings | optional | `[]` |

examples/env_demo/BUILD.bazel

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
load("//kotlin:jvm.bzl", "kt_jvm_binary")
2+
3+
# Example demonstrating env and env_inherit support in kt_jvm_binary
4+
kt_jvm_binary(
5+
name = "env_demo",
6+
srcs = ["Main.kt"],
7+
# Set custom environment variables
8+
env = {
9+
"GREETING": "Hello from Bazel!",
10+
"MESSAGE": "Environment variables are working!",
11+
},
12+
# Inherit environment variables from the shell
13+
env_inherit = ["HOME"],
14+
main_class = "com.example.MainKt",
15+
)

examples/env_demo/Main.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.example
2+
3+
fun main() {
4+
println("Environment variable demo:")
5+
println("GREETING = ${System.getenv("GREETING") ?: "not set"}")
6+
println("MESSAGE = ${System.getenv("MESSAGE") ?: "not set"}")
7+
println("HOME = ${System.getenv("HOME") ?: "not set"}")
8+
}

kotlin/internal/jvm/impl.bzl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,12 +260,16 @@ def kt_jvm_binary_impl(ctx):
260260
return _make_providers(
261261
ctx,
262262
providers,
263-
transitive_files = depset(
263+
ctx.attr.deps + ctx.attr.runtime_deps + ctx.attr.data,
264+
depset(
264265
order = "default",
265266
transitive = [providers.java.transitive_runtime_jars],
266267
direct = ctx.files._java_runtime,
267268
),
268-
runfiles_targets = ctx.attr.deps + ctx.attr.runtime_deps + ctx.attr.data,
269+
RunEnvironmentInfo(
270+
environment = ctx.attr.env,
271+
inherited_environment = ctx.attr.env_inherit,
272+
),
269273
)
270274

271275
_SPLIT_STRINGS = [

kotlin/internal/jvm/jvm.bzl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,15 @@ _runnable_common_attr = utils.add_dicts(_common_attr, _runnable_implicit_deps, {
297297
support make variable substitution.""",
298298
default = [],
299299
),
300+
"env": attr.string_dict(
301+
doc = """Environment variables to set when this binary is executed with `bazel run`.
302+
Note: for Starlark rules, values are used as-is (no automatic $(location) / make variable expansion).""",
303+
default = {},
304+
),
305+
"env_inherit": attr.string_list(
306+
doc = """Names of environment variables to inherit from the shell when executed with `bazel run`.""",
307+
default = [],
308+
),
300309
})
301310

302311
_common_outputs = dict(
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
load(":jvm_deps_tests.bzl", "jvm_deps_test_suite")
2+
load(":kt_jvm_binary_env_test.bzl", "kt_jvm_binary_env_test_suite")
23

34
jvm_deps_test_suite(name = "jvm_tests")
5+
6+
kt_jvm_binary_env_test_suite(name = "kt_jvm_binary_env_tests")
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
load("@rules_testing//lib:analysis_test.bzl", "analysis_test")
2+
load("@rules_testing//lib:test_suite.bzl", "test_suite")
3+
load("@rules_testing//lib:util.bzl", "util")
4+
load("//kotlin:jvm.bzl", "kt_jvm_binary")
5+
6+
def _kt_jvm_binary_env_test_impl(env, target):
7+
"""Test that kt_jvm_binary sets RunEnvironmentInfo correctly."""
8+
9+
# Check that RunEnvironmentInfo is present
10+
env.expect.that_target(target).has_provider(RunEnvironmentInfo)
11+
12+
# Get the RunEnvironmentInfo provider
13+
run_env_info = target[RunEnvironmentInfo]
14+
15+
# Verify the environment variables
16+
env.expect.that_dict(run_env_info.environment).contains_exactly({
17+
"FOO": "bar",
18+
"BAZ": "qux",
19+
})
20+
21+
# Verify the inherited environment variables
22+
env.expect.that_collection(run_env_info.inherited_environment).contains_exactly([
23+
"HOME",
24+
"PATH",
25+
])
26+
27+
def _kt_jvm_binary_env_test(name):
28+
"""Creates a test that verifies env and env_inherit attributes work."""
29+
kt_jvm_binary(
30+
name = name + "_subject",
31+
srcs = [util.empty_file(name + "_Main.kt")],
32+
main_class = "test.Main",
33+
env = {
34+
"FOO": "bar",
35+
"BAZ": "qux",
36+
},
37+
env_inherit = ["HOME", "PATH"],
38+
tags = ["manual"],
39+
)
40+
41+
analysis_test(
42+
name = name,
43+
impl = _kt_jvm_binary_env_test_impl,
44+
target = name + "_subject",
45+
)
46+
47+
def _kt_jvm_binary_empty_env_test_impl(env, target):
48+
"""Test that kt_jvm_binary works with no env attributes."""
49+
50+
# Check that RunEnvironmentInfo is present
51+
env.expect.that_target(target).has_provider(RunEnvironmentInfo)
52+
53+
# Get the RunEnvironmentInfo provider
54+
run_env_info = target[RunEnvironmentInfo]
55+
56+
# Verify the environment is empty
57+
env.expect.that_dict(run_env_info.environment).contains_exactly({})
58+
59+
# Verify no inherited environment variables
60+
env.expect.that_collection(run_env_info.inherited_environment).contains_exactly([])
61+
62+
def _kt_jvm_binary_empty_env_test(name):
63+
"""Creates a test that verifies default env behavior."""
64+
kt_jvm_binary(
65+
name = name + "_subject",
66+
srcs = [util.empty_file(name + "_Main.kt")],
67+
main_class = "test.Main",
68+
tags = ["manual"],
69+
)
70+
71+
analysis_test(
72+
name = name,
73+
impl = _kt_jvm_binary_empty_env_test_impl,
74+
target = name + "_subject",
75+
)
76+
77+
def kt_jvm_binary_env_test_suite(name):
78+
"""Test suite for kt_jvm_binary env support."""
79+
test_suite(
80+
name = name,
81+
tests = [
82+
_kt_jvm_binary_env_test,
83+
_kt_jvm_binary_empty_env_test,
84+
],
85+
)

0 commit comments

Comments
 (0)