@@ -8,6 +8,7 @@ load("//internal/linker:link_node_modules.bzl", "module_mappings_aspect")
88# so that we can generate macros that act as either an output-producing tool or an executable
99_ATTRS = {
1010 "args" : attr .string_list (mandatory = True ),
11+ "chdir" : attr .string (),
1112 "configuration_env_vars" : attr .string_list (default = []),
1213 "data" : attr .label_list (allow_files = True , aspects = [module_mappings_aspect , node_modules_aspect ]),
1314 "exit_code_out" : attr .output (),
@@ -78,6 +79,7 @@ def _impl(ctx):
7879 outputs = outputs ,
7980 arguments = [args ],
8081 configuration_env_vars = ctx .attr .configuration_env_vars ,
82+ chdir = expand_variables (ctx , ctx .attr .chdir ),
8183 stdout = ctx .outputs .stdout ,
8284 stderr = ctx .outputs .stderr ,
8385 exit_code_out = ctx .outputs .exit_code_out ,
@@ -91,19 +93,16 @@ _npm_package_bin = rule(
9193 attrs = _ATTRS ,
9294)
9395
94- def npm_package_bin (tool = None , package = None , package_bin = None , data = [], outs = [], args = [], output_dir = False , link_workspace_root = False , ** kwargs ):
96+ def npm_package_bin (tool = None , package = None , package_bin = None , data = [], outs = [], args = [], output_dir = False , link_workspace_root = False , chdir = None , ** kwargs ):
9597 """Run an arbitrary npm package binary (e.g. a program under node_modules/.bin/*) under Bazel.
9698
9799 It must produce outputs. If you just want to run a program with `bazel run`, use the nodejs_binary rule.
98100
99101 This is like a genrule() except that it runs our launcher script that first
100102 links the node_modules tree before running the program.
101103
102- Bazel always runs actions with a working directory set to your workspace root.
103- If your tool needs to run in a different directory, you can write a `process.chdir` helper script
104- and invoke it before the action with a `--require` argument, like
105- `args = ["--node_options=--require=./$(execpath chdir.js)"]`
106- See rules_nodejs/internal/node/test/chdir for an example.
104+ By default, Bazel runs actions with a working directory set to your workspace root.
105+ Use the `chdir` attribute to change the working directory before the program runs.
107106
108107 This is a great candidate to wrap with a macro, as documented:
109108 https://docs.bazel.build/versions/master/skylark/macros.html#full-example
@@ -168,6 +167,30 @@ def npm_package_bin(tool = None, package = None, package_bin = None, data = [],
168167 Note that you can also refer to a binary in your local workspace.
169168 link_workspace_root: Link the workspace root to the bin_dir to support absolute requires like 'my_wksp/path/to/file'.
170169 If source files need to be required then they can be copied to the bin_dir with copy_to_bin.
170+ chdir: Working directory to run the binary or test in, relative to the workspace.
171+
172+ By default, Bazel always runs in the workspace root.
173+
174+ To run in the directory containing the `npm_package_bin` under the source tree, use
175+ `chdir = package_name()`
176+ (or if you're in a macro, use `native.package_name()`).
177+
178+ To run in the output directory where the npm_package_bin writes outputs, use
179+ `chdir = "$(RULEDIR)"`
180+
181+ NOTE that this can affect other paths passed to the program, which are workspace-relative.
182+ You may need `../../` segments to re-relativize such paths to the new working directory.
183+ In a BUILD file you could do something like this to point to the output path:
184+
185+ ```python
186+ _package_segments = len(package_name().split("/"))
187+ npm_package_bin(
188+ ...
189+ chdir = package_name(),
190+ args = ["/".join([".."] * _package_segments + ["$@"])],
191+ )
192+ ```
193+ **kwargs: additional undocumented keyword args
171194 """
172195 if not tool :
173196 if not package :
@@ -179,6 +202,7 @@ def npm_package_bin(tool = None, package = None, package_bin = None, data = [],
179202 data = data ,
180203 outs = outs ,
181204 args = args ,
205+ chdir = chdir ,
182206 output_dir = output_dir ,
183207 tool = tool ,
184208 link_workspace_root = link_workspace_root ,
0 commit comments