Skip to content

Commit 608af09

Browse files
authored
Add support for extra rustc environment variables (#3510)
This adds support for injecting environment variables into rustc invocations via build settings: - `//rust/settings:extra_rustc_env` for the target configuration - `//rust/settings:extra_exec_rustc_env` for the exec configuration These settings can be set from the command line with flags like: ``` --@rules_rust//rust/settings:extra_rustc_env=RUSTC_BOOTSTRAP=1 ``` This mirrors how extra rustc flags are handled and enables build-wide env-based feature control without editing individual rules. Useful for enabling unstable features across many crates, or toggling behavior in proc macros and build scripts.
1 parent c4b6b41 commit 608af09

File tree

5 files changed

+99
-0
lines changed

5 files changed

+99
-0
lines changed

rust/private/rust.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,12 +537,18 @@ RUSTC_ATTRS = {
537537
"_error_format": attr.label(
538538
default = Label("//rust/settings:error_format"),
539539
),
540+
"_extra_exec_rustc_env": attr.label(
541+
default = Label("//rust/settings:extra_exec_rustc_env"),
542+
),
540543
"_extra_exec_rustc_flag": attr.label(
541544
default = Label("//rust/settings:extra_exec_rustc_flag"),
542545
),
543546
"_extra_exec_rustc_flags": attr.label(
544547
default = Label("//rust/settings:extra_exec_rustc_flags"),
545548
),
549+
"_extra_rustc_env": attr.label(
550+
default = Label("//rust/settings:extra_rustc_env"),
551+
),
546552
"_extra_rustc_flag": attr.label(
547553
default = Label("//rust/settings:extra_rustc_flag"),
548554
),

rust/private/rustc.bzl

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ load(
4141
"is_exec_configuration",
4242
"is_std_dylib",
4343
"make_static_lib_symlink",
44+
"parse_env_strings",
4445
"relativize",
4546
)
4647

@@ -67,6 +68,16 @@ ErrorFormatInfo = provider(
6768
fields = {"error_format": "(string) [" + ", ".join(_error_format_values) + "]"},
6869
)
6970

71+
ExtraRustcEnvInfo = provider(
72+
doc = "Pass each value as an environment variable to non-exec rustc invocations",
73+
fields = {"extra_rustc_env": "List[string] Extra env to pass to rustc in non-exec configuration"},
74+
)
75+
76+
ExtraExecRustcEnvInfo = provider(
77+
doc = "Pass each value as an environment variable to exec rustc invocations",
78+
fields = {"extra_exec_rustc_env": "List[string] Extra env to pass to rustc in exec configuration"},
79+
)
80+
7081
ExtraRustcFlagsInfo = provider(
7182
doc = "Pass each value as an additional flag to non-exec rustc invocations",
7283
fields = {"extra_rustc_flags": "List[string] Extra flags to pass to rustc in non-exec configuration"},
@@ -1104,6 +1115,10 @@ def construct_arguments(
11041115
else:
11051116
rustc_flags.add_all(toolchain.extra_rustc_flags, map_each = map_flag)
11061117

1118+
# extra_rustc_env applies to the target configuration, not the exec configuration.
1119+
if hasattr(ctx.attr, "_extra_rustc_env") and not is_exec_configuration(ctx):
1120+
env.update(ctx.attr._extra_rustc_env[ExtraRustcEnvInfo].extra_rustc_env)
1121+
11071122
# extra_rustc_flags apply to the target configuration, not the exec configuration.
11081123
if hasattr(ctx.attr, "_extra_rustc_flags") and not is_exec_configuration(ctx):
11091124
rustc_flags.add_all(ctx.attr._extra_rustc_flags[ExtraRustcFlagsInfo].extra_rustc_flags, map_each = map_flag)
@@ -1115,6 +1130,9 @@ def construct_arguments(
11151130
per_crate_rustc_flags = ctx.attr._per_crate_rustc_flag[PerCrateRustcFlagsInfo].per_crate_rustc_flags
11161131
_add_per_crate_rustc_flags(ctx, rustc_flags, map_flag, crate_info, per_crate_rustc_flags)
11171132

1133+
if hasattr(ctx.attr, "_extra_exec_rustc_env") and is_exec_configuration(ctx):
1134+
env.update(ctx.attr._extra_exec_rustc_env[ExtraExecRustcEnvInfo].extra_exec_rustc_env)
1135+
11181136
if hasattr(ctx.attr, "_extra_exec_rustc_flags") and is_exec_configuration(ctx):
11191137
rustc_flags.add_all(ctx.attr._extra_exec_rustc_flags[ExtraExecRustcFlagsInfo].extra_exec_rustc_flags, map_each = map_flag)
11201138

@@ -2336,6 +2354,19 @@ rustc_output_diagnostics = rule(
23362354
build_setting = config.bool(flag = True),
23372355
)
23382356

2357+
def _extra_rustc_env_impl(ctx):
2358+
env_vars = parse_env_strings(ctx.build_setting_value)
2359+
return ExtraRustcEnvInfo(extra_rustc_env = env_vars)
2360+
2361+
extra_rustc_env = rule(
2362+
doc = (
2363+
"Add additional environment variables to rustc in non-exec configuration using " +
2364+
"`--@rules_rust//rust/settings:extra_rustc_env=FOO=bar`. Multiple values may be specified."
2365+
),
2366+
implementation = _extra_rustc_env_impl,
2367+
build_setting = config.string_list(flag = True),
2368+
)
2369+
23392370
def _extra_rustc_flags_impl(ctx):
23402371
return ExtraRustcFlagsInfo(extra_rustc_flags = ctx.build_setting_value)
23412372

@@ -2376,6 +2407,19 @@ extra_exec_rustc_flags = rule(
23762407
build_setting = config.string_list(flag = True),
23772408
)
23782409

2410+
def _extra_exec_rustc_env_impl(ctx):
2411+
env_vars = parse_env_strings(ctx.build_setting_value)
2412+
return ExtraExecRustcEnvInfo(extra_exec_rustc_env = env_vars)
2413+
2414+
extra_exec_rustc_env = rule(
2415+
doc = (
2416+
"Add additional environment variables to rustc in non-exec configuration using " +
2417+
"`--@rules_rust//rust/settings:extra_exec_rustc_env=FOO=bar`. Multiple values may be specified."
2418+
),
2419+
implementation = _extra_exec_rustc_env_impl,
2420+
build_setting = config.string_list(flag = True),
2421+
)
2422+
23792423
def _extra_exec_rustc_flag_impl(ctx):
23802424
return ExtraExecRustcFlagsInfo(extra_exec_rustc_flags = [f for f in ctx.build_setting_value if f != ""])
23812425

rust/private/utils.bzl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,23 @@ UNSUPPORTED_FEATURES = [
3333
"rules_rust_unsupported_feature",
3434
]
3535

36+
def parse_env_strings(entries):
37+
"""Parses a list of environment variable entries in the form 'KEY=value'.
38+
39+
Args:
40+
entries(list): A list of strings, each of the form 'KEY=value'.
41+
42+
Returns:
43+
A dict mapping environment variable names to their values.
44+
"""
45+
env_vars = {}
46+
for entry in entries:
47+
if "=" not in entry:
48+
fail("Invalid format for env var: '{}'. Expected 'KEY=value'".format(entry))
49+
key, val = entry.split("=", 1)
50+
env_vars[key] = val
51+
return env_vars
52+
3653
def find_toolchain(ctx):
3754
"""Finds the first rust toolchain that is configured.
3855

rust/settings/BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ load(
1515
"experimental_use_coverage_metadata_files",
1616
"experimental_use_global_allocator",
1717
"experimental_use_sh_toolchain_for_bootstrap_process_wrapper",
18+
"extra_exec_rustc_env",
1819
"extra_exec_rustc_flag",
1920
"extra_exec_rustc_flags",
21+
"extra_rustc_env",
2022
"extra_rustc_flag",
2123
"extra_rustc_flags",
2224
"incompatible_change_clippy_error_format",
@@ -82,10 +84,14 @@ experimental_use_allocator_libraries_with_mangled_symbols(
8284

8385
experimental_use_sh_toolchain_for_bootstrap_process_wrapper()
8486

87+
extra_exec_rustc_env()
88+
8589
extra_exec_rustc_flag()
8690

8791
extra_exec_rustc_flags()
8892

93+
extra_rustc_env()
94+
8995
extra_rustc_flag()
9096

9197
extra_rustc_flags()

rust/settings/settings.bzl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ load("//rust/private:lto.bzl", "rust_lto_flag")
1919
load(
2020
"//rust/private:rustc.bzl",
2121
_error_format = "error_format",
22+
_extra_exec_rustc_env = "extra_exec_rustc_env",
2223
_extra_exec_rustc_flag = "extra_exec_rustc_flag",
2324
_extra_exec_rustc_flags = "extra_exec_rustc_flags",
25+
_extra_rustc_env = "extra_rustc_env",
2426
_extra_rustc_flag = "extra_rustc_flag",
2527
_extra_rustc_flags = "extra_rustc_flags",
2628
_no_std = "no_std",
@@ -342,6 +344,18 @@ def clippy_flags():
342344
build_setting_default = [],
343345
)
344346

347+
# buildifier: disable=unnamed-macro
348+
def extra_rustc_env():
349+
"""This setting may be used to pass extra environment variables to rustc from the command line in non-exec configuration.
350+
351+
It applies across all targets whereas environment variables set in a specific rule apply only to that target.
352+
This can be useful for setting build-wide env flags such as `RUSTC_BOOTSTRAP=1`.
353+
"""
354+
_extra_rustc_env(
355+
name = "extra_rustc_env",
356+
build_setting_default = [],
357+
)
358+
345359
# buildifier: disable=unnamed-macro
346360
def clippy_flag():
347361
"""Add a custom clippy flag from the command line with `--@rules_rust//rust/settings:clippy_flag`.
@@ -376,6 +390,18 @@ def extra_rustc_flag():
376390
build_setting_default = [],
377391
)
378392

393+
# buildifier: disable=unnamed-macro
394+
def extra_exec_rustc_env():
395+
"""This setting may be used to pass extra environment variables to rustc from the command line in exec configuration.
396+
397+
It applies to tools built and run during the build process, such as proc-macros and build scripts.
398+
This can be useful for enabling features that are needed during tool compilation.
399+
"""
400+
_extra_exec_rustc_env(
401+
name = "extra_exec_rustc_env",
402+
build_setting_default = [],
403+
)
404+
379405
# buildifier: disable=unnamed-macro
380406
def extra_exec_rustc_flags():
381407
"""This setting may be used to pass extra options to rustc from the command line in exec configuration.

0 commit comments

Comments
 (0)