1# Copyright 2023 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"""Implementation of cc_tool""" 15 16load("//cc/toolchains/impl:collect.bzl", "collect_data", "collect_provider") 17load( 18 ":cc_toolchain_info.bzl", 19 "FeatureConstraintInfo", 20 "ToolInfo", 21) 22 23def _cc_tool_impl(ctx): 24 exe_info = ctx.attr.src[DefaultInfo] 25 if exe_info.files_to_run != None and exe_info.files_to_run.executable != None: 26 exe = exe_info.files_to_run.executable 27 elif len(exe_info.files.to_list()) == 1: 28 exe = exe_info.files.to_list()[0] 29 else: 30 fail("Expected cc_tool's src attribute to be either an executable or a single file") 31 32 runfiles = collect_data(ctx, ctx.attr.data + [ctx.attr.src]) 33 tool = ToolInfo( 34 label = ctx.label, 35 exe = exe, 36 runfiles = runfiles, 37 requires_any_of = tuple(collect_provider( 38 ctx.attr.requires_any_of, 39 FeatureConstraintInfo, 40 )), 41 execution_requirements = tuple(ctx.attr.execution_requirements), 42 ) 43 44 link = ctx.actions.declare_file(ctx.label.name) 45 ctx.actions.symlink( 46 output = link, 47 target_file = exe, 48 is_executable = True, 49 ) 50 return [ 51 tool, 52 # This isn't required, but now we can do "bazel run <tool>", which can 53 # be very helpful when debugging toolchains. 54 DefaultInfo( 55 files = depset([link]), 56 runfiles = runfiles, 57 executable = link, 58 ), 59 ] 60 61cc_tool = rule( 62 implementation = _cc_tool_impl, 63 # @unsorted-dict-items 64 attrs = { 65 "src": attr.label( 66 allow_files = True, 67 cfg = "exec", 68 doc = """The underlying binary that this tool represents. 69 70Usually just a single prebuilt (eg. @sysroot//:bin/clang), but may be any 71executable label. 72""", 73 ), 74 "data": attr.label_list( 75 allow_files = True, 76 doc = "Additional files that are required for this tool to run.", 77 ), 78 "execution_requirements": attr.string_list( 79 doc = "A list of strings that provide hints for execution environment compatibility (e.g. `requires-network`).", 80 ), 81 "requires_any_of": attr.label_list( 82 providers = [FeatureConstraintInfo], 83 doc = """This will be enabled when any of the constraints are met. 84 85If omitted, this tool will be enabled unconditionally. 86""", 87 ), 88 }, 89 provides = [ToolInfo], 90 doc = """Declares a tool that can be bound to action configs. 91 92A tool is a binary with extra metadata for the action config rule to consume 93(eg. execution_requirements). 94 95Example: 96``` 97cc_tool( 98 name = "clang_tool", 99 executable = "@llvm_toolchain//:bin/clang", 100 # Suppose clang needs libc to run. 101 data = ["@llvm_toolchain//:lib/x86_64-linux-gnu/libc.so.6"] 102) 103``` 104""", 105 executable = True, 106) 107