blob: 42e97eaeccc64c1045736b9bf573ba810d576417 [file] [view]
# use_execroot_entry_point
This page describes the `use_execroot_entry_point` option on `js_run_binary`
and provides guidance on when to use each value.
## Background
When a `js_binary` is used as a tool in `js_run_binary`, Bazel runs it as a
build action on the exec platform. The execroot is the root of the build
sandbox; beneath it sits `bazel-out/`, which contains output directories for
both the exec and target configurations. The tool's sources can therefore appear
in up to three places:
- **Exec-platform bin** (`bazel-out/<exec-cfg>/bin/`): where build artifacts for
the exec platform land.
- **Runfiles tree** (`bazel-out/<exec-cfg>/bin/path/to/my_binary.runfiles/`):
where the tool's runtime dependencies (including `node_modules`) are
symlinked and made available to the build action.
- **Target-platform bin** (`bazel-out/<target-cfg>/bin/`): where the `srcs` of
the `js_run_binary` action land.
When Node.js resolves `require()`, it walks up the directory tree looking for
`node_modules`. If the working directory is somewhere that can see
`node_modules` from both the exec output tree and the runfiles tree, the same
package can resolve from two different paths, which can cause subtle bugs.
## What `use_execroot_entry_point` does
**`use_execroot_entry_point = True` (the current default):**
The tool's runfiles are hoisted into `srcs`, which causes them to be rebuilt in
the target configuration and land in the target-platform bin directory. The
entry point used is the one in that output tree (the "execroot entry point"),
rather than the copy inside the runfiles symlink tree. With everything
consolidated in `bazel-out/<target-cfg>/bin/`, Node.js sees a single
`node_modules` tree. This can be the right choice for some frameworks such as
Next.js, which expects inputs and outputs to be in the same directory tree.
The tradeoff is that if the exec platform differs from the target platform (for
example, cross-compiling from macOS to Linux), target-platform artifacts such as
native Node.js addons are rebuilt for the target and may fail to run on the exec
platform.
**`use_execroot_entry_point = False`:**
The entry point used is the one from the runfiles tree. All code executed during
the build action runs from the runfiles tree, which avoids cross-platform
issues. However, you must ensure that any code executed during the build (for
example, JavaScript config files for tools like Webpack or Rspack) is a declared
dependency of the `js_binary` tool, not merely a source file passed to
`js_run_binary`. Config files in the `js_run_binary`'s `srcs` will land in the
target-platform bin directory and will therefore not be visible to the tool's
runfiles resolution.
## Recommendation
We recommend setting `use_execroot_entry_point = False` wherever possible and
ensuring that all code executed during the build is declared as a dependency of
the `js_binary`. The main exception is Next.js and similar frameworks that
expect inputs and outputs in the same directory tree or that execute
target-platform code during the build, in which case `True` is required.
To disable `use_execroot_entry_point` by default, pass the build flag:
```
--@aspect_rules_js//js:use_execroot_entry_point=False
```
Individual targets can still override the flag by explicitly setting
`use_execroot_entry_point = True` or `use_execroot_entry_point = False`.
In a future major version, we will likely disable the `use_execroot_entry_point`
behavior by default.