• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2019 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#    http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""
16run_binary() build rule implementation.
17
18Runs a binary as a build action. This rule does not require Bash (unlike native.genrule()).
19"""
20
21load("//lib:dicts.bzl", "dicts")
22
23def _impl(ctx):
24    tool_as_list = [ctx.attr.tool]
25    tool_inputs, tool_input_mfs = ctx.resolve_tools(tools = tool_as_list)
26    args = [
27        # Expand $(location) / $(locations) in args.
28        #
29        # To keep the rule simple, do not expand Make Variables (like *_binary.args usually would).
30        # (We can add this feature later if users ask for it.)
31        #
32        # Also for simple implementation and usage, do not Bash-tokenize the arguments. Without
33        # tokenization the user can write args=["a b"] to pass (a b) as one argument, but with
34        # tokenization they would have to write args=["'a b'"] or args=["a\\ b"]. There's no
35        # documented tokenization function anyway (as of 2019-05-21 ctx.tokenize exists but is
36        # undocumented, see https://github.com/bazelbuild/bazel/issues/8389).
37        ctx.expand_location(a, tool_as_list) if "$(location" in a else a
38        for a in ctx.attr.args
39    ]
40    envs = {
41        # Expand $(location) / $(locations) in the values.
42        k: ctx.expand_location(v, tool_as_list) if "$(location" in v else v
43        for k, v in ctx.attr.env.items()
44    }
45    ctx.actions.run(
46        outputs = ctx.outputs.outs,
47        inputs = ctx.files.srcs,
48        tools = tool_inputs,
49        executable = ctx.executable.tool,
50        arguments = args,
51        mnemonic = "RunBinary",
52        use_default_shell_env = False,
53        env = dicts.add(ctx.configuration.default_shell_env, envs),
54        input_manifests = tool_input_mfs,
55    )
56    return DefaultInfo(
57        files = depset(ctx.outputs.outs),
58        runfiles = ctx.runfiles(files = ctx.outputs.outs),
59    )
60
61run_binary = rule(
62    implementation = _impl,
63    doc = "Runs a binary as a build action.<br/><br/>This rule does not require Bash (unlike" +
64          " <code>native.genrule</code>).",
65    attrs = {
66        "tool": attr.label(
67            doc = "The tool to run in the action.<br/><br/>Must be the label of a *_binary rule," +
68                  " of a rule that generates an executable file, or of a file that can be" +
69                  " executed as a subprocess (e.g. an .exe or .bat file on Windows or a binary" +
70                  " with executable permission on Linux). This label is available for" +
71                  " <code>$(location)</code> expansion in <code>args</code> and <code>env</code>.",
72            executable = True,
73            allow_files = True,
74            mandatory = True,
75            cfg = "host",
76        ),
77        "env": attr.string_dict(
78            doc = "Environment variables of the action.<br/><br/>Subject to " +
79                  " <code><a href=\"https://docs.bazel.build/versions/master/be/make-variables.html#location\">$(location)</a></code>" +
80                  " expansion.",
81        ),
82        "srcs": attr.label_list(
83            allow_files = True,
84            doc = "Additional inputs of the action.<br/><br/>These labels are available for" +
85                  " <code>$(location)</code> expansion in <code>args</code> and <code>env</code>.",
86        ),
87        "outs": attr.output_list(
88            mandatory = True,
89            doc = "Output files generated by the action.<br/><br/>These labels are available for" +
90                  " <code>$(location)</code> expansion in <code>args</code> and <code>env</code>.",
91        ),
92        "args": attr.string_list(
93            doc = "Command line arguments of the binary.<br/><br/>Subject to" +
94                  "<code><a href=\"https://docs.bazel.build/versions/master/be/make-variables.html#location\">$(location)</a></code>" +
95                  " expansion.",
96        ),
97    },
98)
99