# 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 _run_binary_impl(ctx): tool_as_list = [ctx.attr.tool] args = [ # Expand $(execpath ...) / $(execpaths ...) / $(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) for a in ctx.attr.args ] envs = { # Expand $(execpath ...) / $(execpaths ...) / $(location ...) / $(locations ...) in the values. k: ctx.expand_location(v, tool_as_list) for k, v in ctx.attr.env.items() } ctx.actions.run( outputs = ctx.outputs.outs, inputs = ctx.files.srcs, tools = [ctx.executable.tool], executable = ctx.executable.tool, arguments = args, mnemonic = "RunBinary", use_default_shell_env = False, env = dicts.add(ctx.configuration.default_shell_env, envs), ) return DefaultInfo( files = depset(ctx.outputs.outs), runfiles = ctx.runfiles(files = ctx.outputs.outs), ) run_binary = rule( implementation = _run_binary_impl, doc = "Runs a binary as a build action.\n\nThis rule does not require Bash (unlike" + " `native.genrule`).", attrs = { "tool": attr.label( doc = "The tool to run in the action.\n\nMust 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" + " `$(execpath)` and `$(location)` expansion in `args` and `env`.", executable = True, allow_files = True, mandatory = True, cfg = "exec", ), "env": attr.string_dict( doc = "Environment variables of the action.\n\nSubject to " + " [`$(execpath)` and `$(location)`](https://bazel.build/reference/be/make-variables#predefined_label_variables)" + " expansion.", ), "srcs": attr.label_list( allow_files = True, doc = "Additional inputs of the action.\n\nThese labels are available for" + " `$(execpath)` and `$(location)` expansion in `args` and `env`.", ), "outs": attr.output_list( mandatory = True, doc = "Output files generated by the action.\n\nThese labels are available for" + " `$(execpath)` and `$(location)` expansion in `args` and `env`.", ), "args": attr.string_list( doc = "Command line arguments of the binary.\n\nSubject to" + " [`$(execpath)` and `$(location)`](https://bazel.build/reference/be/make-variables#predefined_label_variables)" + " expansion.", ), }, )