From c888d4806b25a3546a499d7efb881acec5a48429 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Tue, 14 Jul 2026 09:34:22 -0700 Subject: [PATCH 01/21] feat(js_run_binary): add support for path mapping This change adds support for path mapping in `js_run_binary` by updating it to use the new `--bazel-bindir` flag instead of setting the `BAZEL_BINDIR` environment variable. The only mechanism Bazel provides for determining path-mapped paths is by adding inputs directly to an `Args` object from `ctx.actions.args()`. We can now compute the output Bazel bin directory that way using a special case added to `run_binary()` for this purpose in https://github.com/bazel-contrib/bazel-lib/pull/1269. The `js_run_binary` macro currently sets several other problematic environment variables: BAZEL_BUILD_FILE_PATH, BAZEL_COMPILATION_MODE, BAZEL_TARGET_CPU, BAZEL_TARGET, and BAZEL_WORKSPACE. These are determined by evaluating Make variables, and `run_binary` conservatively assumes that path mapping is not safe if any location or Make variable expansion occurs. This change deprecates these variables and adds a `set_legacy_environment_variables` parameter (default `True`) so they can be disabled without a breaking change, ahead of flipping the default in a future release. To enable path mapping on a particular `js_run_binary` target, make sure to set this parameter to `False`. Co-Authored-By: Claude Sonnet 5 --- js/private/js_run_binary.bzl | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index 538c5a1214..4fe5022346 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -45,6 +45,7 @@ def js_run_binary( patch_node_fs = True, allow_execroot_entry_point_with_no_copy_data_to_bin = False, use_default_shell_env = False, + set_legacy_environment_variables = True, **kwargs): """Wrapper around @bazel_lib `run_binary` that adds convenience attributes for using a `js_binary` tool. @@ -53,16 +54,16 @@ def js_run_binary( The following environment variables are made available to the Node.js runtime based on available Bazel [Make variables](https://bazel.build/reference/be/make-variables#predefined_variables): * BAZEL_BINDIR: the bazel bin directory; equivalent to the `$(BINDIR)` Make variable of the `js_run_binary` target - * BAZEL_COMPILATION_MODE: One of `fastbuild`, `dbg`, or `opt` as set by [`--compilation_mode`](https://bazel.build/docs/user-manual#compilation-mode); equivalent to `$(COMPILATION_MODE)` Make variable of the `js_run_binary` target - * BAZEL_TARGET_CPU: the target cpu architecture; equivalent to `$(TARGET_CPU)` Make variable of the `js_run_binary` target + * BAZEL_TARGET_CPU (legacy; see `set_legacy_environment_variables`): the target cpu architecture; equivalent to `$(TARGET_CPU)` Make variable of the `js_run_binary` target + * BAZEL_COMPILATION_MODE (legacy; see `set_legacy_environment_variables`): One of `fastbuild`, `dbg`, or `opt` as set by [`--compilation_mode`](https://bazel.build/docs/user-manual#compilation-mode); equivalent to `$(COMPILATION_MODE)` Make variable of the `js_run_binary` target The following environment variables are made available to the Node.js runtime based on the rule context: - * BAZEL_BUILD_FILE_PATH: the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context * BAZEL_PACKAGE: the package of the bazel target being run; equivalent to `ctx.label.package` of the `js_run_binary` target's rule context * BAZEL_TARGET_NAME: the full label of the bazel target being run; a stringified version of `ctx.label` of the `js_run_binary` target's rule context - * BAZEL_TARGET: the name of the bazel target being run; equivalent to `ctx.label.name` of the `js_run_binary` target's rule context - * BAZEL_WORKSPACE: the bazel repository name; equivalent to `ctx.workspace_name` of the `js_run_binary` target's rule context + * BAZEL_BUILD_FILE_PATH (legacy; see `set_legacy_environment_variables`): the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context + * BAZEL_TARGET (legacy; see `set_legacy_environment_variables`): the name of the bazel target being run; equivalent to `ctx.label.name` of the `js_run_binary` target's rule context + * BAZEL_WORKSPACE (legacy; see `set_legacy_environment_variables`): the bazel repository name; equivalent to `ctx.workspace_name` of the `js_run_binary` target's rule context Args: name: Target name @@ -253,6 +254,13 @@ def js_run_binary( Refer to https://bazel.build/rules/lib/builtins/actions#run for more details. + set_legacy_environment_variables: Whether to set the legacy `BAZEL_BUILD_FILE_PATH`, + `BAZEL_COMPILATION_MODE`, `BAZEL_TARGET_CPU`, `BAZEL_TARGET` and `BAZEL_WORKSPACE` + environment variables. + + These variables are deprecated and setting them will default to False in a future + release. Set this to False to opt out now. + **kwargs: Additional arguments """ @@ -298,16 +306,19 @@ def js_run_binary( # Automatically add common and useful make variables to the environment for js_run_binary build targets fixed_env = { - "BAZEL_BINDIR": "$(BINDIR)", - "BAZEL_BUILD_FILE_PATH": "$(BUILD_FILE_PATH)", - "BAZEL_COMPILATION_MODE": "$(COMPILATION_MODE)", "BAZEL_PACKAGE": native.package_name(), - "BAZEL_TARGET_CPU": "$(TARGET_CPU)", "BAZEL_TARGET_NAME": name, - "BAZEL_TARGET": "$(TARGET)", - "BAZEL_WORKSPACE": "$(WORKSPACE)", } + # These environment variables are deprecated and will default to not being set in a future + # release; see the `set_legacy_environment_variables` docstring. + if set_legacy_environment_variables: + fixed_env["BAZEL_BUILD_FILE_PATH"] = "$(BUILD_FILE_PATH)" + fixed_env["BAZEL_COMPILATION_MODE"] = "$(COMPILATION_MODE)" + fixed_env["BAZEL_TARGET_CPU"] = "$(TARGET_CPU)" + fixed_env["BAZEL_TARGET"] = "$(TARGET)" + fixed_env["BAZEL_WORKSPACE"] = "$(WORKSPACE)" + # Configure working directory to `chdir` is set if chdir != None: normalized_chdir = "." if chdir == "" else chdir @@ -422,7 +433,7 @@ See https://github.com/aspect-build/rules_js/tree/main/docs#using-binaries-publi srcs = srcs + extra_srcs + execroot_extra_srcs, outs = outs + extra_outs, out_dirs = out_dirs, - args = args, + args = ["--bazel-bindir", "$(BINDIR)"] + args, mnemonic = mnemonic, progress_message = progress_message, execution_requirements = execution_requirements, From ab3e8da8ab49d99566c622c80d159ce2425f15e4 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Sat, 1 Aug 2026 15:55:35 -0700 Subject: [PATCH 02/21] Upgrade bazel_lib to 3.7.0 --- MODULE.bazel | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MODULE.bazel b/MODULE.bazel index 2b47c33b29..16e891975b 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -19,7 +19,8 @@ bazel_dep(name = "rules_nodejs", version = "6.7.3") # Changes ensured by rules_js: # 3.2.2: https://github.com/bazel-contrib/bazel-lib/commit/cac2d7855949d1b222fa26888892fbbe1d31015d -bazel_dep(name = "bazel_lib", version = "3.2.2") +# 3.7.0: https://github.com/bazel-contrib/bazel-lib/commit/e5c0630270f70dd2c7b50471bb9c872781a55282 +bazel_dep(name = "bazel_lib", version = "3.7.0") # NB: LOWER BOUND on earliest BCR release of protobuf module, to avoid upgrading the root module by accident bazel_dep(name = "protobuf", version = "3.19.6") From 1d5d563e92aa836d6ccc2e69b496e6447deabfde Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Sat, 1 Aug 2026 16:12:12 -0700 Subject: [PATCH 03/21] Added e2e test --- .../BUILD.bazel | 29 +++++++++++++++++++ .../check.mjs | 26 +++++++++++++++++ e2e/path_mapping/test.sh | 28 ++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel create mode 100644 e2e/path_mapping/js_run_binary_path_mapping_check/check.mjs diff --git a/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel b/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel new file mode 100644 index 0000000000..57bd6d4dbd --- /dev/null +++ b/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel @@ -0,0 +1,29 @@ +load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_run_binary") +load("@bazel_skylib//rules:build_test.bzl", "build_test") + +# Verifies that a js_run_binary target itself (as opposed to a custom rule +# using js_run_binary_action, exercised by ../bindir_path_mapping_check) +# supports Bazel's path mapping. This requires use_execroot_entry_point and +# set_legacy_environment_variables to both be disabled, and args must avoid +# Make variable and location expansion, since js_run_binary's underlying +# run_binary only advertises path mapping support when none of that +# expansion occurs. +js_binary( + name = "check", + entry_point = "check.mjs", +) + +js_run_binary( + name = "js_run_binary_path_mapping_check", + out_dirs = ["out"], + args = [package_name() + "/out"], + mnemonic = "JsRunBinaryPathMappingCheck", + tool = ":check", + use_execroot_entry_point = False, + set_legacy_environment_variables = False, +) + +build_test( + name = "js_run_binary_path_mapping_check_test", + targets = [":js_run_binary_path_mapping_check"], +) diff --git a/e2e/path_mapping/js_run_binary_path_mapping_check/check.mjs b/e2e/path_mapping/js_run_binary_path_mapping_check/check.mjs new file mode 100644 index 0000000000..9c7fffe3ec --- /dev/null +++ b/e2e/path_mapping/js_run_binary_path_mapping_check/check.mjs @@ -0,0 +1,26 @@ +import { mkdirSync, writeFileSync } from 'fs' +import { join } from 'path' + +const outDir = process.argv[2] +if (!outDir) { + process.stderr.write('Usage: check.mjs \n') + process.exit(1) +} + +const bindir = process.env.BAZEL_BINDIR +if (bindir !== 'bazel-out/cfg/bin') { + process.stderr.write( + `Expected BAZEL_BINDIR to be "bazel-out/cfg/bin", got "${bindir}"\n` + ) + process.exit(1) +} + +const leaked = process.argv.filter((arg) => arg === '--bazel-bindir') +if (leaked.length > 0) { + process.stderr.write(`--bazel-bindir flag leaked into argv: ${leaked}\n`) + process.exit(1) +} + +mkdirSync(outDir, { recursive: true }) +writeFileSync(join(outDir, 'file1'), 'OK\n') +writeFileSync(join(outDir, 'file2'), 'OK\n') diff --git a/e2e/path_mapping/test.sh b/e2e/path_mapping/test.sh index a7f6e782fe..aabf0a2d0f 100755 --- a/e2e/path_mapping/test.sh +++ b/e2e/path_mapping/test.sh @@ -47,3 +47,31 @@ if [ "$cache_hit" != "true" ]; then fi echo "PASS: action was cache-shared across -c fastbuild and -c opt" + +# Same proof as above, but exercising a plain js_run_binary target instead of +# a custom rule built on js_run_binary_action. +exec_log2="$scratch/exec_log2.json" + +bazel build -c fastbuild //js_run_binary_path_mapping_check \ + --disk_cache="$disk_cache" \ + --action_env="JS_RUN_BINARY_PATH_MAPPING_CHECK_INVALIDATE=$invalidate" + +bazel build -c opt //js_run_binary_path_mapping_check \ + --disk_cache="$disk_cache" \ + --action_env="JS_RUN_BINARY_PATH_MAPPING_CHECK_INVALIDATE=$invalidate" \ + --execution_log_json_file="$exec_log2" + +matches2="$(jq -s '[.[] | select(.mnemonic == "JsRunBinaryPathMappingCheck")]' "$exec_log2")" +count2="$(echo "$matches2" | jq 'length')" +if [ "$count2" -eq 0 ]; then + echo "FAIL: no JsRunBinaryPathMappingCheck entry found in the -c opt execution log" >&2 + exit 1 +fi + +cache_hit2="$(echo "$matches2" | jq -r '.[0].cacheHit')" +if [ "$cache_hit2" != "true" ]; then + echo "FAIL: js_run_binary action was re-executed under -c opt (cacheHit=$cache_hit2); path mapping did not share the cache entry from -c fastbuild" >&2 + exit 1 +fi + +echo "PASS: js_run_binary action was cache-shared across -c fastbuild and -c opt" From fde0d204ef64acc4ee1251ab25b50c567c59c3eb Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Sat, 1 Aug 2026 16:19:18 -0700 Subject: [PATCH 04/21] Simplify some things --- .../js_run_binary_path_mapping_check/BUILD.bazel | 14 +++++--------- .../js_run_binary_path_mapping_check/check.mjs | 13 +++++-------- e2e/path_mapping/test.sh | 4 ++-- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel b/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel index 57bd6d4dbd..6580c3c22d 100644 --- a/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel +++ b/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel @@ -1,13 +1,9 @@ load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_run_binary") load("@bazel_skylib//rules:build_test.bzl", "build_test") -# Verifies that a js_run_binary target itself (as opposed to a custom rule -# using js_run_binary_action, exercised by ../bindir_path_mapping_check) -# supports Bazel's path mapping. This requires use_execroot_entry_point and -# set_legacy_environment_variables to both be disabled, and args must avoid -# Make variable and location expansion, since js_run_binary's underlying -# run_binary only advertises path mapping support when none of that -# expansion occurs. +# Verifies that a js_run_binary target supports path mapping. This requires +# use_execroot_entry_point and set_legacy_environment_variables to both be +# disabled, and args must avoid Make variable and location expansion. js_binary( name = "check", entry_point = "check.mjs", @@ -15,8 +11,8 @@ js_binary( js_run_binary( name = "js_run_binary_path_mapping_check", - out_dirs = ["out"], - args = [package_name() + "/out"], + outs = ["out.txt"], + args = [package_name() + "/out.txt"], mnemonic = "JsRunBinaryPathMappingCheck", tool = ":check", use_execroot_entry_point = False, diff --git a/e2e/path_mapping/js_run_binary_path_mapping_check/check.mjs b/e2e/path_mapping/js_run_binary_path_mapping_check/check.mjs index 9c7fffe3ec..076912720f 100644 --- a/e2e/path_mapping/js_run_binary_path_mapping_check/check.mjs +++ b/e2e/path_mapping/js_run_binary_path_mapping_check/check.mjs @@ -1,9 +1,8 @@ -import { mkdirSync, writeFileSync } from 'fs' -import { join } from 'path' +import { writeFileSync } from 'fs' -const outDir = process.argv[2] -if (!outDir) { - process.stderr.write('Usage: check.mjs \n') +const outFile = process.argv[2] +if (!outFile) { + process.stderr.write('Usage: check.mjs \n') process.exit(1) } @@ -21,6 +20,4 @@ if (leaked.length > 0) { process.exit(1) } -mkdirSync(outDir, { recursive: true }) -writeFileSync(join(outDir, 'file1'), 'OK\n') -writeFileSync(join(outDir, 'file2'), 'OK\n') +writeFileSync(outFile, 'OK\n') diff --git a/e2e/path_mapping/test.sh b/e2e/path_mapping/test.sh index aabf0a2d0f..ed18fdd8ea 100755 --- a/e2e/path_mapping/test.sh +++ b/e2e/path_mapping/test.sh @@ -48,8 +48,8 @@ fi echo "PASS: action was cache-shared across -c fastbuild and -c opt" -# Same proof as above, but exercising a plain js_run_binary target instead of -# a custom rule built on js_run_binary_action. +# Same as above, but exercising a js_run_binary target instead of a custom rule +# built on js_run_binary_action. exec_log2="$scratch/exec_log2.json" bazel build -c fastbuild //js_run_binary_path_mapping_check \ From 2daa7fac3a854c3b588b707516740f59e7eeb11b Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Sat, 1 Aug 2026 16:20:15 -0700 Subject: [PATCH 05/21] buildifier --- e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel b/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel index 6580c3c22d..8b0e84baf4 100644 --- a/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel +++ b/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel @@ -14,9 +14,9 @@ js_run_binary( outs = ["out.txt"], args = [package_name() + "/out.txt"], mnemonic = "JsRunBinaryPathMappingCheck", + set_legacy_environment_variables = False, tool = ":check", use_execroot_entry_point = False, - set_legacy_environment_variables = False, ) build_test( From e4affbee519c9f63da407980698c8469d5a43b9a Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Sat, 1 Aug 2026 16:22:27 -0700 Subject: [PATCH 06/21] Avoid re-ordering variables --- js/private/js_run_binary.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index 4fe5022346..1facbfcd8f 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -54,8 +54,8 @@ def js_run_binary( The following environment variables are made available to the Node.js runtime based on available Bazel [Make variables](https://bazel.build/reference/be/make-variables#predefined_variables): * BAZEL_BINDIR: the bazel bin directory; equivalent to the `$(BINDIR)` Make variable of the `js_run_binary` target - * BAZEL_TARGET_CPU (legacy; see `set_legacy_environment_variables`): the target cpu architecture; equivalent to `$(TARGET_CPU)` Make variable of the `js_run_binary` target * BAZEL_COMPILATION_MODE (legacy; see `set_legacy_environment_variables`): One of `fastbuild`, `dbg`, or `opt` as set by [`--compilation_mode`](https://bazel.build/docs/user-manual#compilation-mode); equivalent to `$(COMPILATION_MODE)` Make variable of the `js_run_binary` target + * BAZEL_TARGET_CPU (legacy; see `set_legacy_environment_variables`): the target cpu architecture; equivalent to `$(TARGET_CPU)` Make variable of the `js_run_binary` target The following environment variables are made available to the Node.js runtime based on the rule context: From 6721f5702c195ed7687a487584893857e3a4395b Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 14:19:50 -0700 Subject: [PATCH 07/21] Compute some of these variables inside the macro --- js/private/js_run_binary.bzl | 43 ++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index 1facbfcd8f..7ee31b9be2 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -17,6 +17,24 @@ load(":js_helpers.bzl", _envs_for_log_level = "envs_for_log_level") load(":js_info_files.bzl", _js_info_files = "js_info_files") load(":js_library.bzl", _js_library = "js_library") +def _build_file_path(): + """Returns the package-relative path to the current package's BUILD file. + + Equivalent to `ctx.build_file_path`, but computed at macro-evaluation time since macros have + no `ctx`. The build file's name isn't known in advance (`BUILD` or `BUILD.bazel`), so this + uses `glob()` to detect it; if both are present, `BUILD.bazel` wins, matching Bazel's own + precedence. + """ + matches = native.glob(["BUILD.bazel", "BUILD"], allow_empty = True) + if "BUILD.bazel" in matches: + build_file_name = "BUILD.bazel" + elif "BUILD" in matches: + build_file_name = "BUILD" + else: + fail("Could not find a BUILD or BUILD.bazel file in package '{}'".format(native.package_name())) + package = native.package_name() + return "{}/{}".format(package, build_file_name) if package else build_file_name + def js_run_binary( name, tool, @@ -61,9 +79,9 @@ def js_run_binary( * BAZEL_PACKAGE: the package of the bazel target being run; equivalent to `ctx.label.package` of the `js_run_binary` target's rule context * BAZEL_TARGET_NAME: the full label of the bazel target being run; a stringified version of `ctx.label` of the `js_run_binary` target's rule context - * BAZEL_BUILD_FILE_PATH (legacy; see `set_legacy_environment_variables`): the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context - * BAZEL_TARGET (legacy; see `set_legacy_environment_variables`): the name of the bazel target being run; equivalent to `ctx.label.name` of the `js_run_binary` target's rule context - * BAZEL_WORKSPACE (legacy; see `set_legacy_environment_variables`): the bazel repository name; equivalent to `ctx.workspace_name` of the `js_run_binary` target's rule context + * BAZEL_BUILD_FILE_PATH: the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context + * BAZEL_TARGET: the name of the bazel target being run; equivalent to `ctx.label.name` of the `js_run_binary` target's rule context + * BAZEL_WORKSPACE: the bazel repository name; equivalent to `ctx.workspace_name` of the `js_run_binary` target's rule context Args: name: Target name @@ -254,9 +272,8 @@ def js_run_binary( Refer to https://bazel.build/rules/lib/builtins/actions#run for more details. - set_legacy_environment_variables: Whether to set the legacy `BAZEL_BUILD_FILE_PATH`, - `BAZEL_COMPILATION_MODE`, `BAZEL_TARGET_CPU`, `BAZEL_TARGET` and `BAZEL_WORKSPACE` - environment variables. + set_legacy_environment_variables: Whether to set the legacy `BAZEL_COMPILATION_MODE` + and `BAZEL_TARGET_CPU` environment variables. These variables are deprecated and setting them will default to False in a future release. Set this to False to opt out now. @@ -305,19 +322,27 @@ def js_run_binary( extra_srcs.append(":{}".format(copy_to_bin_name)) # Automatically add common and useful make variables to the environment for js_run_binary build targets + label = native.package_relative_label(name) fixed_env = { + "BAZEL_BUILD_FILE_PATH": _build_file_path(), "BAZEL_PACKAGE": native.package_name(), "BAZEL_TARGET_NAME": name, + "BAZEL_TARGET": "{}//{}:{}".format( + "@" + label.repo_name if label.repo_name else "", + label.package, + label.name, + ), + # This variable used to be derived from ctx.workspace_name and was the + # name from the WORKSPACE file, but with bzlmod it is always just + # "_main". + "BAZEL_WORKSPACE": "_main", } # These environment variables are deprecated and will default to not being set in a future # release; see the `set_legacy_environment_variables` docstring. if set_legacy_environment_variables: - fixed_env["BAZEL_BUILD_FILE_PATH"] = "$(BUILD_FILE_PATH)" fixed_env["BAZEL_COMPILATION_MODE"] = "$(COMPILATION_MODE)" fixed_env["BAZEL_TARGET_CPU"] = "$(TARGET_CPU)" - fixed_env["BAZEL_TARGET"] = "$(TARGET)" - fixed_env["BAZEL_WORKSPACE"] = "$(WORKSPACE)" # Configure working directory to `chdir` is set if chdir != None: From 48a9dd6abb50da50c91c91ecb00ec47ef74ee1e3 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 14:23:16 -0700 Subject: [PATCH 08/21] Fix ordering --- js/private/js_run_binary.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index 7ee31b9be2..9ae44e0b54 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -77,9 +77,9 @@ def js_run_binary( The following environment variables are made available to the Node.js runtime based on the rule context: + * BAZEL_BUILD_FILE_PATH: the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context * BAZEL_PACKAGE: the package of the bazel target being run; equivalent to `ctx.label.package` of the `js_run_binary` target's rule context * BAZEL_TARGET_NAME: the full label of the bazel target being run; a stringified version of `ctx.label` of the `js_run_binary` target's rule context - * BAZEL_BUILD_FILE_PATH: the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context * BAZEL_TARGET: the name of the bazel target being run; equivalent to `ctx.label.name` of the `js_run_binary` target's rule context * BAZEL_WORKSPACE: the bazel repository name; equivalent to `ctx.workspace_name` of the `js_run_binary` target's rule context From ab101ca1bfcbc2ff33906c9e7154fe144e697f9e Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 14:55:49 -0700 Subject: [PATCH 09/21] Add e2e tests for BAZEL_BUILD_FILE_PATH and BAZEL_TARGET across modules Verify these js_run_binary env vars, now computed directly in the macro instead of via Make-variable substitution, are correct when the js_run_binary target lives in a module other than the main one. --- e2e/js_binary_workspace/BUILD.bazel | 2 + e2e/js_binary_workspace/workspace/BUILD.bazel | 58 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/e2e/js_binary_workspace/BUILD.bazel b/e2e/js_binary_workspace/BUILD.bazel index 9d9ced94c9..c2f6f25103 100644 --- a/e2e/js_binary_workspace/BUILD.bazel +++ b/e2e/js_binary_workspace/BUILD.bazel @@ -45,6 +45,8 @@ build_test( test_suite( name = "external_tests", tests = [ + "@workspace//:bazel_build_file_path_test", + "@workspace//:bazel_target_test", "@workspace//:js_binary_chdir_test", "@workspace//:js_test_chdir_test", ], diff --git a/e2e/js_binary_workspace/workspace/BUILD.bazel b/e2e/js_binary_workspace/workspace/BUILD.bazel index c9ada1d870..aa8389a3ab 100644 --- a/e2e/js_binary_workspace/workspace/BUILD.bazel +++ b/e2e/js_binary_workspace/workspace/BUILD.bazel @@ -16,6 +16,64 @@ js_run_binary( visibility = ["//visibility:public"], ) +# Verify that BAZEL_BUILD_FILE_PATH and BAZEL_TARGET, which js_run_binary now computes itself +# instead of expanding via Make variables, are correct for a js_run_binary target that lives in +# a module other than the main one (this "workspace" module is consumed as an external repo by +# the root module in ../BUILD.bazel). +js_run_binary( + name = "check_bazel_vars", + log_level = "debug", + silent_on_success = False, + stderr = "check_bazel_vars_stderr.txt", + tool = ":bin", + visibility = ["//visibility:public"], +) + +write_file( + name = "assert_contains_sh", + out = "assert_contains.sh", + content = [ + "#!/usr/bin/env bash", + "set -euo pipefail", + "file=$1", + "shift", + # Bazel's test runner may pass each whitespace-separated word of an `args` entry as its + # own argv item, so the expected substring is split across argv and rejoined here with + # single spaces rather than passed as one already-spaced string. + 'expected="$*"', + "if ! grep -qF -- \"$expected\" \"$file\"; then", + " echo \"expected '$file' to contain '$expected', but it did not. Contents:\" >&2", + " cat \"$file\" >&2", + " exit 1", + "fi", + ], +) + +# Expect the canonical label of this js_run_binary target, prefixed with this module's canonical +# repo name (not the root module's, and not aspect_rules_js's own). +sh_test( + name = "bazel_target_test", + srcs = [":assert_contains.sh"], + args = [ + "$(rootpath :check_bazel_vars_stderr.txt)", + "BAZEL_TARGET", + "@workspace+//:check_bazel_vars", + ], + data = [":check_bazel_vars_stderr.txt"], +) + +# Expect the BUILD file path relative to this module's root, not the root module's. +sh_test( + name = "bazel_build_file_path_test", + srcs = [":assert_contains.sh"], + args = [ + "$(rootpath :check_bazel_vars_stderr.txt)", + "BAZEL_BUILD_FILE_PATH", + "BUILD.bazel", + ], + data = [":check_bazel_vars_stderr.txt"], +) + # Write the expected relative working directory beginning with bazel-out/ genrule( name = "working_directory_expected", From 3406fb50b89a07086a806da671c39d1242ead020 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 15:02:23 -0700 Subject: [PATCH 10/21] Shorten long comment --- e2e/js_binary_workspace/workspace/BUILD.bazel | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e/js_binary_workspace/workspace/BUILD.bazel b/e2e/js_binary_workspace/workspace/BUILD.bazel index aa8389a3ab..b0cba13473 100644 --- a/e2e/js_binary_workspace/workspace/BUILD.bazel +++ b/e2e/js_binary_workspace/workspace/BUILD.bazel @@ -16,10 +16,10 @@ js_run_binary( visibility = ["//visibility:public"], ) -# Verify that BAZEL_BUILD_FILE_PATH and BAZEL_TARGET, which js_run_binary now computes itself -# instead of expanding via Make variables, are correct for a js_run_binary target that lives in -# a module other than the main one (this "workspace" module is consumed as an external repo by -# the root module in ../BUILD.bazel). +# Verify that BAZEL_BUILD_FILE_PATH and BAZEL_TARGET are correct for a +# js_run_binary target that lives in a module other than the main one (this +# "workspace" module is consumed as an external repo by the root module in +# ../BUILD.bazel). js_run_binary( name = "check_bazel_vars", log_level = "debug", From b2211b6d84868b1a894327dd35f45f27e28cac0e Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 15:17:47 -0700 Subject: [PATCH 11/21] Fix bazel_target_test to work across Bazel versions The expected BAZEL_TARGET value hardcoded the canonical repo name's separator ("workspace+"), which differs across Bazel versions ("workspace~" on Bazel 7, "workspace+" on Bazel 9+), causing the test to fail under Bazel 7.7.1. Derive it via repo_name() instead. --- e2e/js_binary_workspace/workspace/BUILD.bazel | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/e2e/js_binary_workspace/workspace/BUILD.bazel b/e2e/js_binary_workspace/workspace/BUILD.bazel index b0cba13473..972a38673d 100644 --- a/e2e/js_binary_workspace/workspace/BUILD.bazel +++ b/e2e/js_binary_workspace/workspace/BUILD.bazel @@ -50,14 +50,16 @@ write_file( ) # Expect the canonical label of this js_run_binary target, prefixed with this module's canonical -# repo name (not the root module's, and not aspect_rules_js's own). +# repo name (not the root module's, and not aspect_rules_js's own). The canonical name's +# separator differs across Bazel versions ("workspace~" on Bazel 7, "workspace+" on Bazel 9), so +# it's derived via repo_name() here rather than hardcoded. sh_test( name = "bazel_target_test", srcs = [":assert_contains.sh"], args = [ "$(rootpath :check_bazel_vars_stderr.txt)", "BAZEL_TARGET", - "@workspace+//:check_bazel_vars", + "{}//:check_bazel_vars".format("@" + repo_name() if repo_name() else ""), ], data = [":check_bazel_vars_stderr.txt"], ) From d7aea7d5f8e5aad4597d1f8716f5fbdc8d3b7436 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 16:02:11 -0700 Subject: [PATCH 12/21] Revert to Make-variable expansion for the legacy js_run_binary env vars --- e2e/js_binary_workspace/BUILD.bazel | 2 - e2e/js_binary_workspace/workspace/BUILD.bazel | 60 ------------------- js/private/js_run_binary.bzl | 45 ++++---------- 3 files changed, 10 insertions(+), 97 deletions(-) diff --git a/e2e/js_binary_workspace/BUILD.bazel b/e2e/js_binary_workspace/BUILD.bazel index c2f6f25103..9d9ced94c9 100644 --- a/e2e/js_binary_workspace/BUILD.bazel +++ b/e2e/js_binary_workspace/BUILD.bazel @@ -45,8 +45,6 @@ build_test( test_suite( name = "external_tests", tests = [ - "@workspace//:bazel_build_file_path_test", - "@workspace//:bazel_target_test", "@workspace//:js_binary_chdir_test", "@workspace//:js_test_chdir_test", ], diff --git a/e2e/js_binary_workspace/workspace/BUILD.bazel b/e2e/js_binary_workspace/workspace/BUILD.bazel index 972a38673d..c9ada1d870 100644 --- a/e2e/js_binary_workspace/workspace/BUILD.bazel +++ b/e2e/js_binary_workspace/workspace/BUILD.bazel @@ -16,66 +16,6 @@ js_run_binary( visibility = ["//visibility:public"], ) -# Verify that BAZEL_BUILD_FILE_PATH and BAZEL_TARGET are correct for a -# js_run_binary target that lives in a module other than the main one (this -# "workspace" module is consumed as an external repo by the root module in -# ../BUILD.bazel). -js_run_binary( - name = "check_bazel_vars", - log_level = "debug", - silent_on_success = False, - stderr = "check_bazel_vars_stderr.txt", - tool = ":bin", - visibility = ["//visibility:public"], -) - -write_file( - name = "assert_contains_sh", - out = "assert_contains.sh", - content = [ - "#!/usr/bin/env bash", - "set -euo pipefail", - "file=$1", - "shift", - # Bazel's test runner may pass each whitespace-separated word of an `args` entry as its - # own argv item, so the expected substring is split across argv and rejoined here with - # single spaces rather than passed as one already-spaced string. - 'expected="$*"', - "if ! grep -qF -- \"$expected\" \"$file\"; then", - " echo \"expected '$file' to contain '$expected', but it did not. Contents:\" >&2", - " cat \"$file\" >&2", - " exit 1", - "fi", - ], -) - -# Expect the canonical label of this js_run_binary target, prefixed with this module's canonical -# repo name (not the root module's, and not aspect_rules_js's own). The canonical name's -# separator differs across Bazel versions ("workspace~" on Bazel 7, "workspace+" on Bazel 9), so -# it's derived via repo_name() here rather than hardcoded. -sh_test( - name = "bazel_target_test", - srcs = [":assert_contains.sh"], - args = [ - "$(rootpath :check_bazel_vars_stderr.txt)", - "BAZEL_TARGET", - "{}//:check_bazel_vars".format("@" + repo_name() if repo_name() else ""), - ], - data = [":check_bazel_vars_stderr.txt"], -) - -# Expect the BUILD file path relative to this module's root, not the root module's. -sh_test( - name = "bazel_build_file_path_test", - srcs = [":assert_contains.sh"], - args = [ - "$(rootpath :check_bazel_vars_stderr.txt)", - "BAZEL_BUILD_FILE_PATH", - "BUILD.bazel", - ], - data = [":check_bazel_vars_stderr.txt"], -) - # Write the expected relative working directory beginning with bazel-out/ genrule( name = "working_directory_expected", diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index 9ae44e0b54..4fe5022346 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -17,24 +17,6 @@ load(":js_helpers.bzl", _envs_for_log_level = "envs_for_log_level") load(":js_info_files.bzl", _js_info_files = "js_info_files") load(":js_library.bzl", _js_library = "js_library") -def _build_file_path(): - """Returns the package-relative path to the current package's BUILD file. - - Equivalent to `ctx.build_file_path`, but computed at macro-evaluation time since macros have - no `ctx`. The build file's name isn't known in advance (`BUILD` or `BUILD.bazel`), so this - uses `glob()` to detect it; if both are present, `BUILD.bazel` wins, matching Bazel's own - precedence. - """ - matches = native.glob(["BUILD.bazel", "BUILD"], allow_empty = True) - if "BUILD.bazel" in matches: - build_file_name = "BUILD.bazel" - elif "BUILD" in matches: - build_file_name = "BUILD" - else: - fail("Could not find a BUILD or BUILD.bazel file in package '{}'".format(native.package_name())) - package = native.package_name() - return "{}/{}".format(package, build_file_name) if package else build_file_name - def js_run_binary( name, tool, @@ -72,16 +54,16 @@ def js_run_binary( The following environment variables are made available to the Node.js runtime based on available Bazel [Make variables](https://bazel.build/reference/be/make-variables#predefined_variables): * BAZEL_BINDIR: the bazel bin directory; equivalent to the `$(BINDIR)` Make variable of the `js_run_binary` target - * BAZEL_COMPILATION_MODE (legacy; see `set_legacy_environment_variables`): One of `fastbuild`, `dbg`, or `opt` as set by [`--compilation_mode`](https://bazel.build/docs/user-manual#compilation-mode); equivalent to `$(COMPILATION_MODE)` Make variable of the `js_run_binary` target * BAZEL_TARGET_CPU (legacy; see `set_legacy_environment_variables`): the target cpu architecture; equivalent to `$(TARGET_CPU)` Make variable of the `js_run_binary` target + * BAZEL_COMPILATION_MODE (legacy; see `set_legacy_environment_variables`): One of `fastbuild`, `dbg`, or `opt` as set by [`--compilation_mode`](https://bazel.build/docs/user-manual#compilation-mode); equivalent to `$(COMPILATION_MODE)` Make variable of the `js_run_binary` target The following environment variables are made available to the Node.js runtime based on the rule context: - * BAZEL_BUILD_FILE_PATH: the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context * BAZEL_PACKAGE: the package of the bazel target being run; equivalent to `ctx.label.package` of the `js_run_binary` target's rule context * BAZEL_TARGET_NAME: the full label of the bazel target being run; a stringified version of `ctx.label` of the `js_run_binary` target's rule context - * BAZEL_TARGET: the name of the bazel target being run; equivalent to `ctx.label.name` of the `js_run_binary` target's rule context - * BAZEL_WORKSPACE: the bazel repository name; equivalent to `ctx.workspace_name` of the `js_run_binary` target's rule context + * BAZEL_BUILD_FILE_PATH (legacy; see `set_legacy_environment_variables`): the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context + * BAZEL_TARGET (legacy; see `set_legacy_environment_variables`): the name of the bazel target being run; equivalent to `ctx.label.name` of the `js_run_binary` target's rule context + * BAZEL_WORKSPACE (legacy; see `set_legacy_environment_variables`): the bazel repository name; equivalent to `ctx.workspace_name` of the `js_run_binary` target's rule context Args: name: Target name @@ -272,8 +254,9 @@ def js_run_binary( Refer to https://bazel.build/rules/lib/builtins/actions#run for more details. - set_legacy_environment_variables: Whether to set the legacy `BAZEL_COMPILATION_MODE` - and `BAZEL_TARGET_CPU` environment variables. + set_legacy_environment_variables: Whether to set the legacy `BAZEL_BUILD_FILE_PATH`, + `BAZEL_COMPILATION_MODE`, `BAZEL_TARGET_CPU`, `BAZEL_TARGET` and `BAZEL_WORKSPACE` + environment variables. These variables are deprecated and setting them will default to False in a future release. Set this to False to opt out now. @@ -322,27 +305,19 @@ def js_run_binary( extra_srcs.append(":{}".format(copy_to_bin_name)) # Automatically add common and useful make variables to the environment for js_run_binary build targets - label = native.package_relative_label(name) fixed_env = { - "BAZEL_BUILD_FILE_PATH": _build_file_path(), "BAZEL_PACKAGE": native.package_name(), "BAZEL_TARGET_NAME": name, - "BAZEL_TARGET": "{}//{}:{}".format( - "@" + label.repo_name if label.repo_name else "", - label.package, - label.name, - ), - # This variable used to be derived from ctx.workspace_name and was the - # name from the WORKSPACE file, but with bzlmod it is always just - # "_main". - "BAZEL_WORKSPACE": "_main", } # These environment variables are deprecated and will default to not being set in a future # release; see the `set_legacy_environment_variables` docstring. if set_legacy_environment_variables: + fixed_env["BAZEL_BUILD_FILE_PATH"] = "$(BUILD_FILE_PATH)" fixed_env["BAZEL_COMPILATION_MODE"] = "$(COMPILATION_MODE)" fixed_env["BAZEL_TARGET_CPU"] = "$(TARGET_CPU)" + fixed_env["BAZEL_TARGET"] = "$(TARGET)" + fixed_env["BAZEL_WORKSPACE"] = "$(WORKSPACE)" # Configure working directory to `chdir` is set if chdir != None: From 042330ed933fcc00ead72c3eeee86b4c0ed84f11 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 16:09:18 -0700 Subject: [PATCH 13/21] Simplify test --- e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel b/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel index 8b0e84baf4..69347a9a6c 100644 --- a/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel +++ b/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel @@ -12,7 +12,8 @@ js_binary( js_run_binary( name = "js_run_binary_path_mapping_check", outs = ["out.txt"], - args = [package_name() + "/out.txt"], + chdir = package_name(), + args = ["out.txt"], mnemonic = "JsRunBinaryPathMappingCheck", set_legacy_environment_variables = False, tool = ":check", From 7f3ac976905ca9c1150a3a431c80ce2ce2b96411 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 16:11:37 -0700 Subject: [PATCH 14/21] Fix up ordering --- js/private/js_run_binary.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index 4fe5022346..e7ea1c6ee9 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -54,14 +54,14 @@ def js_run_binary( The following environment variables are made available to the Node.js runtime based on available Bazel [Make variables](https://bazel.build/reference/be/make-variables#predefined_variables): * BAZEL_BINDIR: the bazel bin directory; equivalent to the `$(BINDIR)` Make variable of the `js_run_binary` target - * BAZEL_TARGET_CPU (legacy; see `set_legacy_environment_variables`): the target cpu architecture; equivalent to `$(TARGET_CPU)` Make variable of the `js_run_binary` target * BAZEL_COMPILATION_MODE (legacy; see `set_legacy_environment_variables`): One of `fastbuild`, `dbg`, or `opt` as set by [`--compilation_mode`](https://bazel.build/docs/user-manual#compilation-mode); equivalent to `$(COMPILATION_MODE)` Make variable of the `js_run_binary` target + * BAZEL_TARGET_CPU (legacy; see `set_legacy_environment_variables`): the target cpu architecture; equivalent to `$(TARGET_CPU)` Make variable of the `js_run_binary` target The following environment variables are made available to the Node.js runtime based on the rule context: + * BAZEL_BUILD_FILE_PATH (legacy; see `set_legacy_environment_variables`): the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context * BAZEL_PACKAGE: the package of the bazel target being run; equivalent to `ctx.label.package` of the `js_run_binary` target's rule context * BAZEL_TARGET_NAME: the full label of the bazel target being run; a stringified version of `ctx.label` of the `js_run_binary` target's rule context - * BAZEL_BUILD_FILE_PATH (legacy; see `set_legacy_environment_variables`): the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context * BAZEL_TARGET (legacy; see `set_legacy_environment_variables`): the name of the bazel target being run; equivalent to `ctx.label.name` of the `js_run_binary` target's rule context * BAZEL_WORKSPACE (legacy; see `set_legacy_environment_variables`): the bazel repository name; equivalent to `ctx.workspace_name` of the `js_run_binary` target's rule context From d8ce43112a41fb563304b3322da7a31cea4f60d4 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 16:14:24 -0700 Subject: [PATCH 15/21] Move BAZEL_PACKAGE and BAZEL_TARGET_NAME behind set_legacy_environment_variables All seven js_run_binary-provided BAZEL_* env vars are now gated behind the same flag, for consistency. --- js/private/js_run_binary.bzl | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index e7ea1c6ee9..7cbff45800 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -60,8 +60,8 @@ def js_run_binary( The following environment variables are made available to the Node.js runtime based on the rule context: * BAZEL_BUILD_FILE_PATH (legacy; see `set_legacy_environment_variables`): the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context - * BAZEL_PACKAGE: the package of the bazel target being run; equivalent to `ctx.label.package` of the `js_run_binary` target's rule context - * BAZEL_TARGET_NAME: the full label of the bazel target being run; a stringified version of `ctx.label` of the `js_run_binary` target's rule context + * BAZEL_PACKAGE (legacy; see `set_legacy_environment_variables`): the package of the bazel target being run; equivalent to `ctx.label.package` of the `js_run_binary` target's rule context + * BAZEL_TARGET_NAME (legacy; see `set_legacy_environment_variables`): the full label of the bazel target being run; a stringified version of `ctx.label` of the `js_run_binary` target's rule context * BAZEL_TARGET (legacy; see `set_legacy_environment_variables`): the name of the bazel target being run; equivalent to `ctx.label.name` of the `js_run_binary` target's rule context * BAZEL_WORKSPACE (legacy; see `set_legacy_environment_variables`): the bazel repository name; equivalent to `ctx.workspace_name` of the `js_run_binary` target's rule context @@ -255,8 +255,8 @@ def js_run_binary( Refer to https://bazel.build/rules/lib/builtins/actions#run for more details. set_legacy_environment_variables: Whether to set the legacy `BAZEL_BUILD_FILE_PATH`, - `BAZEL_COMPILATION_MODE`, `BAZEL_TARGET_CPU`, `BAZEL_TARGET` and `BAZEL_WORKSPACE` - environment variables. + `BAZEL_COMPILATION_MODE`, `BAZEL_TARGET_CPU`, `BAZEL_TARGET`, `BAZEL_WORKSPACE`, + `BAZEL_PACKAGE` and `BAZEL_TARGET_NAME` environment variables. These variables are deprecated and setting them will default to False in a future release. Set this to False to opt out now. @@ -305,10 +305,7 @@ def js_run_binary( extra_srcs.append(":{}".format(copy_to_bin_name)) # Automatically add common and useful make variables to the environment for js_run_binary build targets - fixed_env = { - "BAZEL_PACKAGE": native.package_name(), - "BAZEL_TARGET_NAME": name, - } + fixed_env = {} # These environment variables are deprecated and will default to not being set in a future # release; see the `set_legacy_environment_variables` docstring. @@ -318,6 +315,8 @@ def js_run_binary( fixed_env["BAZEL_TARGET_CPU"] = "$(TARGET_CPU)" fixed_env["BAZEL_TARGET"] = "$(TARGET)" fixed_env["BAZEL_WORKSPACE"] = "$(WORKSPACE)" + fixed_env["BAZEL_PACKAGE"] = native.package_name() + fixed_env["BAZEL_TARGET_NAME"] = name # Configure working directory to `chdir` is set if chdir != None: From 6ab19569520a1a2c7d4e5feb86d98f3fbea60bfa Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 16:16:14 -0700 Subject: [PATCH 16/21] Remove outdated comment --- js/private/js_run_binary.bzl | 1 - 1 file changed, 1 deletion(-) diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index 7cbff45800..bd3543b2cd 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -304,7 +304,6 @@ def js_run_binary( ) extra_srcs.append(":{}".format(copy_to_bin_name)) - # Automatically add common and useful make variables to the environment for js_run_binary build targets fixed_env = {} # These environment variables are deprecated and will default to not being set in a future From 88d464331860b4f8ad7c366a9ce2fd97618d2d3a Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 16:25:54 -0700 Subject: [PATCH 17/21] buildifier --- e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel b/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel index 69347a9a6c..183c116e40 100644 --- a/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel +++ b/e2e/path_mapping/js_run_binary_path_mapping_check/BUILD.bazel @@ -12,8 +12,8 @@ js_binary( js_run_binary( name = "js_run_binary_path_mapping_check", outs = ["out.txt"], - chdir = package_name(), args = ["out.txt"], + chdir = package_name(), mnemonic = "JsRunBinaryPathMappingCheck", set_legacy_environment_variables = False, tool = ":check", From 438cf1503844f3b4ad8127a7cb2c4c5c3cff0040 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Mon, 3 Aug 2026 20:16:48 -0700 Subject: [PATCH 18/21] Simplify comment --- js/private/js_run_binary.bzl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index bd3543b2cd..4fcf8ac9dd 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -57,13 +57,13 @@ def js_run_binary( * BAZEL_COMPILATION_MODE (legacy; see `set_legacy_environment_variables`): One of `fastbuild`, `dbg`, or `opt` as set by [`--compilation_mode`](https://bazel.build/docs/user-manual#compilation-mode); equivalent to `$(COMPILATION_MODE)` Make variable of the `js_run_binary` target * BAZEL_TARGET_CPU (legacy; see `set_legacy_environment_variables`): the target cpu architecture; equivalent to `$(TARGET_CPU)` Make variable of the `js_run_binary` target - The following environment variables are made available to the Node.js runtime based on the rule context: + The following environment variables are made available to the Node.js runtime based on the rule context (all are legacy; see `set_legacy_environment_variables`): - * BAZEL_BUILD_FILE_PATH (legacy; see `set_legacy_environment_variables`): the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context - * BAZEL_PACKAGE (legacy; see `set_legacy_environment_variables`): the package of the bazel target being run; equivalent to `ctx.label.package` of the `js_run_binary` target's rule context - * BAZEL_TARGET_NAME (legacy; see `set_legacy_environment_variables`): the full label of the bazel target being run; a stringified version of `ctx.label` of the `js_run_binary` target's rule context - * BAZEL_TARGET (legacy; see `set_legacy_environment_variables`): the name of the bazel target being run; equivalent to `ctx.label.name` of the `js_run_binary` target's rule context - * BAZEL_WORKSPACE (legacy; see `set_legacy_environment_variables`): the bazel repository name; equivalent to `ctx.workspace_name` of the `js_run_binary` target's rule context + * BAZEL_BUILD_FILE_PATH: the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context + * BAZEL_PACKAGE: the package of the bazel target being run; equivalent to `ctx.label.package` of the `js_run_binary` target's rule context + * BAZEL_TARGET_NAME: the full label of the bazel target being run; a stringified version of `ctx.label` of the `js_run_binary` target's rule context + * BAZEL_TARGET: the name of the bazel target being run; equivalent to `ctx.label.name` of the `js_run_binary` target's rule context + * BAZEL_WORKSPACE: the bazel repository name; equivalent to `ctx.workspace_name` of the `js_run_binary` target's rule context Args: name: Target name From 9c0bd7332d9235f76c4bdabde453c26ef2dc7688 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Tue, 4 Aug 2026 11:09:09 -0700 Subject: [PATCH 19/21] Explicitly set BAZEL_BINDIR if set_legacy_environment_variables --- js/private/js_run_binary.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index 4fcf8ac9dd..82a58de66b 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -309,6 +309,7 @@ def js_run_binary( # These environment variables are deprecated and will default to not being set in a future # release; see the `set_legacy_environment_variables` docstring. if set_legacy_environment_variables: + fixed_env["BAZEL_BINDIR"] = "$(BINDIR)" fixed_env["BAZEL_BUILD_FILE_PATH"] = "$(BUILD_FILE_PATH)" fixed_env["BAZEL_COMPILATION_MODE"] = "$(COMPILATION_MODE)" fixed_env["BAZEL_TARGET_CPU"] = "$(TARGET_CPU)" From 4b3f4188b993d5374479451648481ab5993faa7c Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Tue, 4 Aug 2026 14:22:36 -0700 Subject: [PATCH 20/21] Tweak comment --- js/private/js_run_binary.bzl | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index 82a58de66b..7d31931cbe 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -51,14 +51,11 @@ def js_run_binary( This rule does not require Bash `native.genrule`. - The following environment variables are made available to the Node.js runtime based on available Bazel [Make variables](https://bazel.build/reference/be/make-variables#predefined_variables): + The following environment variables are made available to the Node.js runtime if set_legacy_environment_variables is enabled. They are deprecated and will be removed in a future release: * BAZEL_BINDIR: the bazel bin directory; equivalent to the `$(BINDIR)` Make variable of the `js_run_binary` target - * BAZEL_COMPILATION_MODE (legacy; see `set_legacy_environment_variables`): One of `fastbuild`, `dbg`, or `opt` as set by [`--compilation_mode`](https://bazel.build/docs/user-manual#compilation-mode); equivalent to `$(COMPILATION_MODE)` Make variable of the `js_run_binary` target - * BAZEL_TARGET_CPU (legacy; see `set_legacy_environment_variables`): the target cpu architecture; equivalent to `$(TARGET_CPU)` Make variable of the `js_run_binary` target - - The following environment variables are made available to the Node.js runtime based on the rule context (all are legacy; see `set_legacy_environment_variables`): - + * BAZEL_COMPILATION_MODE: One of `fastbuild`, `dbg`, or `opt` as set by [`--compilation_mode`](https://bazel.build/docs/user-manual#compilation-mode); equivalent to `$(COMPILATION_MODE)` Make variable of the `js_run_binary` target + * BAZEL_TARGET_CPU: the target cpu architecture; equivalent to `$(TARGET_CPU)` Make variable of the `js_run_binary` target * BAZEL_BUILD_FILE_PATH: the path to the BUILD file of the bazel target being run; equivalent to `ctx.build_file_path` of the `js_run_binary` target's rule context * BAZEL_PACKAGE: the package of the bazel target being run; equivalent to `ctx.label.package` of the `js_run_binary` target's rule context * BAZEL_TARGET_NAME: the full label of the bazel target being run; a stringified version of `ctx.label` of the `js_run_binary` target's rule context From 4722d213aba15b1925dc0325ba510f9cd1f0e272 Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Tue, 4 Aug 2026 14:23:58 -0700 Subject: [PATCH 21/21] Fix comment --- js/private/js_run_binary.bzl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/js/private/js_run_binary.bzl b/js/private/js_run_binary.bzl index 7d31931cbe..40ae93b4f0 100644 --- a/js/private/js_run_binary.bzl +++ b/js/private/js_run_binary.bzl @@ -251,9 +251,10 @@ def js_run_binary( Refer to https://bazel.build/rules/lib/builtins/actions#run for more details. - set_legacy_environment_variables: Whether to set the legacy `BAZEL_BUILD_FILE_PATH`, - `BAZEL_COMPILATION_MODE`, `BAZEL_TARGET_CPU`, `BAZEL_TARGET`, `BAZEL_WORKSPACE`, - `BAZEL_PACKAGE` and `BAZEL_TARGET_NAME` environment variables. + set_legacy_environment_variables: Whether to set the legacy `BAZEL_BINDIR`, + `BAZEL_BUILD_FILE_PATH`, `BAZEL_COMPILATION_MODE`, `BAZEL_TARGET_CPU`, + `BAZEL_TARGET`, `BAZEL_WORKSPACE`, `BAZEL_PACKAGE` and `BAZEL_TARGET_NAME` + environment variables. These variables are deprecated and setting them will default to False in a future release. Set this to False to opt out now.