# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ run_binary() build rule implementation. Runs a binary as a build action. This rule does not require Bash (unlike native.genrule()). """ load("//lib:dicts.bzl", "dicts") def _impl(ctx): tool_as_list = [ctx.attr.tool] tool_inputs, tool_input_mfs = ctx.resolve_tools(tools = tool_as_list) args = [ # Expand $(location) / $(locations) in args. # # To keep the rule simple, do not expand Make Variables (like *_binary.args usually would). # (We can add this feature later if users ask for it.) # # Also for simple implementation and usage, do not Bash-tokenize the arguments. Without # tokenization the user can write args=["a b"] to pass (a b) as one argument, but with # tokenization they would have to write args=["'a b'"] or args=["a\\ b"]. There's no # documented tokenization function anyway (as of 2019-05-21 ctx.tokenize exists but is # undocumented, see https://github.com/bazelbuild/bazel/issues/8389). ctx.expand_location(a, tool_as_list) if "$(location" in a else a for a in ctx.attr.args ] envs = { # Expand $(location) / $(locations) in the values. k: ctx.expand_location(v, tool_as_list) if "$(location" in v else v for k, v in ctx.attr.env.items() } ctx.actions.run( outputs = ctx.outputs.outs, inputs = ctx.files.srcs, tools = tool_inputs, executable = ctx.executable.tool, arguments = args, mnemonic = "RunBinary", use_default_shell_env = False, env = dicts.add(ctx.configuration.default_shell_env, envs), input_manifests = tool_input_mfs, ) return DefaultInfo( files = depset(items = ctx.outputs.outs), runfiles = ctx.runfiles(files = ctx.outputs.outs), ) run_binary = rule( implementation = _impl, doc = "Runs a binary as a build action.

This rule does not require Bash (unlike" + " native.genrule).", attrs = { "tool": attr.label( doc = "The tool to run in the action.

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" + " $(location) expansion in args and env.", executable = True, allow_files = True, mandatory = True, cfg = "host", ), "env": attr.string_dict( doc = "Environment variables of the action.

Subject to " + " $(location)" + " expansion.", ), "srcs": attr.label_list( allow_files = True, doc = "Additional inputs of the action.

These labels are available for" + " $(location) expansion in args and env.", ), "outs": attr.output_list( mandatory = True, doc = "Output files generated by the action.

These labels are available for" + " $(location) expansion in args and env.", ), "args": attr.string_list( doc = "Command line arguments of the binary.

Subject to" + "$(location)" + " expansion.", ), }, )