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 _run_binary_impl(ctx): 24 tool_as_list = [ctx.attr.tool] 25 args = [ 26 # Expand $(execpath ...) / $(execpaths ...) / $(location ...) / $(locations ...) in args. 27 # 28 # To keep the rule simple, do not expand Make Variables (like *_binary.args usually would). 29 # (We can add this feature later if users ask for it.) 30 # 31 # Also for simple implementation and usage, do not Bash-tokenize the arguments. Without 32 # tokenization the user can write args=["a b"] to pass (a b) as one argument, but with 33 # tokenization they would have to write args=["'a b'"] or args=["a\\ b"]. There's no 34 # documented tokenization function anyway (as of 2019-05-21 ctx.tokenize exists but is 35 # undocumented, see https://github.com/bazelbuild/bazel/issues/8389). 36 ctx.expand_location(a, tool_as_list) 37 for a in ctx.attr.args 38 ] 39 envs = { 40 # Expand $(execpath ...) / $(execpaths ...) / $(location ...) / $(locations ...) in the values. 41 k: ctx.expand_location(v, tool_as_list) 42 for k, v in ctx.attr.env.items() 43 } 44 ctx.actions.run( 45 outputs = ctx.outputs.outs, 46 inputs = ctx.files.srcs, 47 tools = [ctx.executable.tool], 48 executable = ctx.executable.tool, 49 arguments = args, 50 mnemonic = "RunBinary", 51 use_default_shell_env = False, 52 env = dicts.add(ctx.configuration.default_shell_env, envs), 53 ) 54 return DefaultInfo( 55 files = depset(ctx.outputs.outs), 56 runfiles = ctx.runfiles(files = ctx.outputs.outs), 57 ) 58 59run_binary = rule( 60 implementation = _run_binary_impl, 61 doc = "Runs a binary as a build action.\n\nThis rule does not require Bash (unlike" + 62 " `native.genrule`).", 63 attrs = { 64 "tool": attr.label( 65 doc = "The tool to run in the action.\n\nMust be the label of a *_binary rule," + 66 " of a rule that generates an executable file, or of a file that can be" + 67 " executed as a subprocess (e.g. an .exe or .bat file on Windows or a binary" + 68 " with executable permission on Linux). This label is available for" + 69 " `$(execpath)` and `$(location)` expansion in `args` and `env`.", 70 executable = True, 71 allow_files = True, 72 mandatory = True, 73 cfg = "exec", 74 ), 75 "env": attr.string_dict( 76 doc = "Environment variables of the action.\n\nSubject to " + 77 " [`$(execpath)` and `$(location)`](https://bazel.build/reference/be/make-variables#predefined_label_variables)" + 78 " expansion.", 79 ), 80 "srcs": attr.label_list( 81 allow_files = True, 82 doc = "Additional inputs of the action.\n\nThese labels are available for" + 83 " `$(execpath)` and `$(location)` expansion in `args` and `env`.", 84 ), 85 "outs": attr.output_list( 86 mandatory = True, 87 doc = "Output files generated by the action.\n\nThese labels are available for" + 88 " `$(execpath)` and `$(location)` expansion in `args` and `env`.", 89 ), 90 "args": attr.string_list( 91 doc = "Command line arguments of the binary.\n\nSubject to" + 92 " [`$(execpath)` and `$(location)`](https://bazel.build/reference/be/make-variables#predefined_label_variables)" + 93 " expansion.", 94 ), 95 }, 96) 97