feat: add command attribute to run_binary
diff --git a/docs/run_binary.md b/docs/run_binary.md
index d50db14..2beceef 100644
--- a/docs/run_binary.md
+++ b/docs/run_binary.md
@@ -10,7 +10,7 @@
## run_binary
<pre>
-run_binary(<a href="#run_binary-name">name</a>, <a href="#run_binary-tool">tool</a>, <a href="#run_binary-srcs">srcs</a>, <a href="#run_binary-args">args</a>, <a href="#run_binary-env">env</a>, <a href="#run_binary-outs">outs</a>, <a href="#run_binary-out_dirs">out_dirs</a>, <a href="#run_binary-mnemonic">mnemonic</a>, <a href="#run_binary-progress_message">progress_message</a>,
+run_binary(<a href="#run_binary-name">name</a>, <a href="#run_binary-tool">tool</a>, <a href="#run_binary-command">command</a>, <a href="#run_binary-srcs">srcs</a>, <a href="#run_binary-args">args</a>, <a href="#run_binary-env">env</a>, <a href="#run_binary-outs">outs</a>, <a href="#run_binary-out_dirs">out_dirs</a>, <a href="#run_binary-mnemonic">mnemonic</a>, <a href="#run_binary-progress_message">progress_message</a>,
<a href="#run_binary-execution_requirements">execution_requirements</a>, <a href="#run_binary-stamp">stamp</a>, <a href="#run_binary-output_dir">output_dir</a>, <a href="#run_binary-kwargs">kwargs</a>)
</pre>
@@ -25,7 +25,8 @@
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="run_binary-name"></a>name | The target name | none |
-| <a id="run_binary-tool"></a>tool | The tool to run in the action.<br><br>Must be the label of a *_binary rule of a rule that generates an executable file, or of a file that can be executed as a subprocess (e.g. an .exe or .bat file on Windows or a binary with executable permission on Linux). This label is available for <code>$(location)</code> expansion in <code>args</code> and <code>env</code>. | none |
+| <a id="run_binary-tool"></a>tool | The tool to run in the action.<br><br>Must be the label of a *_binary rule of a rule that generates an executable file, or of a file that can be executed as a subprocess (e.g. an .exe or .bat file on Windows or a binary with executable permission on Linux). This label is available for <code>$(location)</code> expansion in <code>args</code> and <code>env</code>.<br><br>Only one of <code>command</code> or <code>tool</code> may be specified. | <code>None</code> |
+| <a id="run_binary-command"></a>command | The command to run in the action.<br><br>Only one of <code>command</code> or <code>tool</code> may be specified. | <code>None</code> |
| <a id="run_binary-srcs"></a>srcs | Additional inputs of the action.<br><br>These labels are available for <code>$(location)</code> expansion in <code>args</code> and <code>env</code>. | <code>[]</code> |
| <a id="run_binary-args"></a>args | Command line arguments of the binary.<br><br>Subject to <code>$(location)</code> and makevar expansions. | <code>[]</code> |
| <a id="run_binary-env"></a>env | Environment variables of the action.<br><br>Subject to <code>$(location)</code> and makevar expansions. | <code>{}</code> |
diff --git a/lib/private/run_binary.bzl b/lib/private/run_binary.bzl
index d7fe14d..c0f4abc 100644
--- a/lib/private/run_binary.bzl
+++ b/lib/private/run_binary.bzl
@@ -20,8 +20,11 @@
load("//lib:stamping.bzl", "STAMP_ATTRS", "maybe_stamp")
def _run_binary_impl(ctx):
- tool_as_list = [ctx.attr.tool]
- tool_inputs, tool_input_mfs = ctx.resolve_tools(tools = tool_as_list)
+ if not ctx.attr.tool and not ctx.attr.command:
+ fail("Either tool or command must be specified")
+ if ctx.attr.tool and ctx.attr.command:
+ fail("Only one of tool or command may be specified")
+
args = ctx.actions.args()
outputs = []
@@ -35,19 +38,19 @@
fail("output directory {} is nested within output directory {}; outputs cannot be nested within each other!".format(out_dir.path, output.path))
outputs.append(out_dir)
if len(outputs) < 1:
- fail("""\
+ msg = """\
ERROR: target {target} is not configured to produce any outputs.
Bazel only executes actions when their outputs are required, so it's never correct to create an action with no outputs.
Possible fixes:
- Predict what outputs are created, and list them in the outs and out_dirs attributes.
-- If {rule_kind} is a binary, and you meant to run it for its side-effects,
- then call it directly with `bazel run` and don't wrap it in a run_binary rule.
-""".format(
- target = str(ctx.label),
- rule_kind = str(ctx.attr.tool.label),
- ))
+""".format(target = str(ctx.label))
+ if ctx.attr.tool:
+ msg += """- If {rule_kind} is a binary, and you meant to run it for its side-effects,
+then call it directly with `bazel run` and don't wrap it in a run_binary rule.
+""".format(rule_kind = str(ctx.attr.tool.label))
+ fail(msg)
# `expand_locations(...).split(" ")` is a work-around https://github.com/bazelbuild/bazel/issues/10309
# _expand_locations returns an array of args to support $(execpaths) expansions.
@@ -67,19 +70,34 @@
else:
inputs = ctx.files.srcs
- ctx.actions.run(
- outputs = outputs,
- inputs = inputs,
- tools = tool_inputs,
- executable = ctx.executable.tool,
- arguments = [args],
- mnemonic = ctx.attr.mnemonic if ctx.attr.mnemonic else None,
- progress_message = ctx.attr.progress_message if ctx.attr.progress_message else None,
- execution_requirements = ctx.attr.execution_requirements if ctx.attr.execution_requirements else None,
- use_default_shell_env = False,
- env = dicts.add(ctx.configuration.default_shell_env, envs),
- input_manifests = tool_input_mfs,
- )
+ if ctx.attr.tool:
+ tool_inputs, tool_input_mfs = ctx.resolve_tools(tools = [ctx.attr.tool])
+ ctx.actions.run(
+ outputs = outputs,
+ inputs = inputs,
+ tools = tool_inputs,
+ executable = ctx.executable.tool,
+ arguments = [args],
+ mnemonic = ctx.attr.mnemonic if ctx.attr.mnemonic else None,
+ progress_message = ctx.attr.progress_message if ctx.attr.progress_message else None,
+ execution_requirements = ctx.attr.execution_requirements if ctx.attr.execution_requirements else None,
+ use_default_shell_env = False,
+ env = dicts.add(ctx.configuration.default_shell_env, envs),
+ input_manifests = tool_input_mfs,
+ )
+ else:
+ ctx.actions.run_shell(
+ outputs = outputs,
+ inputs = inputs,
+ command = ctx.attr.command,
+ arguments = [args],
+ mnemonic = ctx.attr.mnemonic if ctx.attr.mnemonic else None,
+ progress_message = ctx.attr.progress_message if ctx.attr.progress_message else None,
+ execution_requirements = ctx.attr.execution_requirements if ctx.attr.execution_requirements else None,
+ use_default_shell_env = False,
+ env = dicts.add(ctx.configuration.default_shell_env, envs),
+ )
+
return DefaultInfo(
files = depset(outputs),
runfiles = ctx.runfiles(files = outputs),
@@ -91,9 +109,9 @@
"tool": attr.label(
executable = True,
allow_files = True,
- mandatory = True,
cfg = "exec",
),
+ "command": attr.string(),
"env": attr.string_dict(),
"srcs": attr.label_list(
allow_files = True,
@@ -109,7 +127,8 @@
def run_binary(
name,
- tool,
+ tool = None,
+ command = None,
srcs = [],
args = [],
env = {},
@@ -135,6 +154,13 @@
a file that can be executed as a subprocess (e.g. an .exe or .bat file on Windows or a
binary with executable permission on Linux). This label is available for `$(location)`
expansion in `args` and `env`.
+
+ Only one of `command` or `tool` may be specified.
+
+ command: The command to run in the action.
+
+ Only one of `command` or `tool` may be specified.
+
srcs: Additional inputs of the action.
These labels are available for `$(location)` expansion in `args` and `env`.
@@ -213,6 +239,7 @@
_run_binary(
name = name,
tool = tool,
+ command = command,
srcs = srcs,
args = args,
env = env,