1# Copyright (C) 2022 The Android Open Source Project 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 15load("@bazel_skylib//lib:paths.bzl", "paths") 16load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") 17 18def _get_clang_cmd_output(ctx): 19 copts = [ 20 "--target=bpf", 21 "-nostdlibinc", 22 "-no-canonical-prefixes", 23 "-O2", 24 ] 25 copts.extend(ctx.attr.copts) 26 if ctx.attr.btf: 27 copts.append("-g") 28 29 includes = [ 30 "packages/modules/Connectivity/staticlibs/native/bpf_headers/include/bpf", 31 # TODO(b/149785767): only give access to specific file with AID_* constants 32 "system/core/libcutils/include", 33 "external/musl/src/env", 34 ctx.label.package, 35 ] 36 includes.extend(ctx.attr.absolute_includes) 37 38 system_includes = [ 39 "bionic/libc/include", 40 "bionic/libc/kernel/uapi", 41 # The architecture doesn't matter here, but asm/types.h is included by linux/types.h. 42 "bionic/libc/kernel/uapi/asm-arm64", 43 "bionic/libc/kernel/android/uapi", 44 ] 45 46 toolchain = find_cpp_toolchain(ctx) 47 extra_features = [ 48 "dependency_file", 49 "bpf_compiler_flags", 50 ] 51 extra_disabled_features = [ 52 "sdk_version_flag", 53 "pie", 54 "non_external_compiler_flags", 55 "common_compiler_flags", 56 "asm_compiler_flags", 57 "cpp_compiler_flags", 58 "c_compiler_flags", 59 "external_compiler_flags", 60 "arm_isa_arm", 61 "arm_isa_thumb", 62 "no_override_clang_global_copts", 63 ] 64 feature_configuration = cc_common.configure_features( 65 ctx = ctx, 66 cc_toolchain = toolchain, 67 requested_features = ctx.features + extra_features, 68 unsupported_features = ctx.disabled_features + extra_disabled_features, 69 ) 70 71 compilation_context = [] 72 dir_name = ctx.label.name 73 if ctx.attr.btf: 74 # If btf is true, intermediate dir ("unstripped") is added when 75 # clang command is executed, because ctx.actions.run used in stripped 76 # command does not allow the same input and output names. 77 # "unstripped" will be removed when strip command is executed. 78 dir_name = paths.join("unstripped", dir_name) 79 (compilation_context, compilation_outputs) = cc_common.compile( 80 name = dir_name, 81 actions = ctx.actions, 82 feature_configuration = feature_configuration, 83 cc_toolchain = toolchain, 84 srcs = ctx.files.srcs, 85 system_includes = system_includes, 86 includes = includes, 87 user_compile_flags = copts, 88 compilation_contexts = compilation_context, 89 ) 90 91 return compilation_outputs.objects 92 93def _declare_stripped_cmd_output_file(ctx, src): 94 file_path = paths.join("_objs", src.basename, src.basename) 95 return ctx.actions.declare_file(file_path) 96 97def _get_stripped_cmd_output(ctx, srcs): 98 out_files = [_declare_stripped_cmd_output_file(ctx, src) for src in srcs] 99 100 args = ctx.actions.args() 101 args.add("--strip-unneeded") 102 args.add("--remove-section=.rel.BTF") 103 args.add("--remove-section=.rel.BTF.ext") 104 args.add("--remove-section=.BTF.ext") 105 106 for in_file, out_file in zip(srcs, out_files): 107 ctx.actions.run( 108 inputs = [in_file], 109 outputs = [out_file], 110 executable = ctx.executable._strip, 111 arguments = [args] + [in_file.path, "-o", out_file.path], 112 ) 113 114 return out_files 115 116def _bpf_impl(ctx): 117 for src in ctx.files.srcs: 118 if "_" in src.basename: 119 fail("Invalid character '_' in source name") 120 121 clang_outfiles = _get_clang_cmd_output(ctx) 122 123 if not ctx.attr.btf: 124 return [DefaultInfo(files = depset(clang_outfiles))] 125 else: 126 stripped_outfiles = _get_stripped_cmd_output(ctx, clang_outfiles) 127 return [DefaultInfo(files = depset(stripped_outfiles))] 128 129bpf = rule( 130 implementation = _bpf_impl, 131 attrs = { 132 "srcs": attr.label_list( 133 mandatory = True, 134 allow_files = True, 135 ), 136 "copts": attr.string_list(), 137 "absolute_includes": attr.string_list(), 138 "btf": attr.bool( 139 default = True, 140 doc = "if set to true, generate BTF debug info for maps & programs", 141 ), 142 "_strip": attr.label( 143 cfg = "exec", 144 executable = True, 145 default = "//prebuilts/clang/host/linux-x86:llvm-strip", 146 allow_files = True, 147 ), 148 }, 149 toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], 150 fragments = ["cpp"], 151) 152