1# Copyright (C) 2021 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 15"""A macro to handle shared library stripping.""" 16 17load(":cc_library_common.bzl", "CcAndroidMkInfo") 18load(":clang_tidy.bzl", "collect_deps_clang_tidy_info") 19load( 20 ":lto_transitions.bzl", 21 "drop_lto_transition", 22 "lto_deps_transition", 23) 24 25CcUnstrippedInfo = provider( 26 "Provides unstripped binary/shared library", 27 fields = { 28 "unstripped": "unstripped target", 29 }, 30) 31 32# Keep this consistent with soong/cc/strip.go#NeedsStrip. 33def _needs_strip(ctx): 34 if ctx.attr.none: 35 return False 36 if ctx.target_platform_has_constraint(ctx.attr._android_constraint[platform_common.ConstraintValueInfo]): 37 return True 38 return (ctx.attr.all or ctx.attr.keep_symbols or 39 ctx.attr.keep_symbols_and_debug_frame or ctx.attr.keep_symbols_list) 40 41# Keep this consistent with soong/cc/strip.go#strip and soong/cc/builder.go#transformStrip. 42def _get_strip_args(attrs): 43 strip_args = [] 44 keep_mini_debug_info = False 45 if attrs.keep_symbols: 46 strip_args.append("--keep-symbols") 47 elif attrs.keep_symbols_and_debug_frame: 48 strip_args.append("--keep-symbols-and-debug-frame") 49 elif attrs.keep_symbols_list: 50 strip_args.append("-k" + ",".join(attrs.keep_symbols_list)) 51 elif not attrs.all: 52 strip_args.append("--keep-mini-debug-info") 53 keep_mini_debug_info = True 54 55 if not keep_mini_debug_info: 56 strip_args.append("--add-gnu-debuglink") 57 58 return strip_args 59 60# https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/builder.go;l=131-146;drc=master 61def stripped_impl(ctx, prefix = "", suffix = "", extension = ""): 62 out_file = ctx.actions.declare_file(prefix + ctx.attr.name + suffix + extension) 63 if not _needs_strip(ctx): 64 ctx.actions.symlink( 65 output = out_file, 66 target_file = ctx.files.src[0], 67 ) 68 return out_file 69 d_file = ctx.actions.declare_file(ctx.attr.name + ".d") 70 ctx.actions.run( 71 env = { 72 "CREATE_MINIDEBUGINFO": ctx.executable._create_minidebuginfo.path, 73 "XZ": ctx.executable._xz.path, 74 "CLANG_BIN": ctx.executable._ar.dirname, 75 }, 76 inputs = ctx.files.src, 77 tools = [ 78 ctx.executable._ar, 79 ctx.executable._create_minidebuginfo, 80 ctx.executable._objcopy, 81 ctx.executable._readelf, 82 ctx.executable._strip, 83 ctx.executable._strip_script, 84 ctx.executable._xz, 85 ], 86 outputs = [out_file, d_file], 87 executable = ctx.executable._strip_script, 88 arguments = _get_strip_args(ctx.attr) + [ 89 "-i", 90 ctx.files.src[0].path, 91 "-o", 92 out_file.path, 93 "-d", 94 d_file.path, 95 ], 96 mnemonic = "CcStrip", 97 ) 98 return out_file 99 100strip_attrs = dict( 101 keep_symbols = attr.bool(default = False), 102 keep_symbols_and_debug_frame = attr.bool(default = False), 103 all = attr.bool(default = False), 104 none = attr.bool(default = False), 105 keep_symbols_list = attr.string_list(default = []), 106) 107common_strip_attrs = dict( 108 strip_attrs, 109 _xz = attr.label( 110 cfg = "exec", 111 executable = True, 112 allow_single_file = True, 113 default = "//prebuilts/build-tools:linux-x86/bin/xz", 114 ), 115 _create_minidebuginfo = attr.label( 116 cfg = "exec", 117 executable = True, 118 allow_single_file = True, 119 default = "//prebuilts/build-tools:linux-x86/bin/create_minidebuginfo", 120 ), 121 _strip_script = attr.label( 122 cfg = "exec", 123 executable = True, 124 allow_single_file = True, 125 default = "//build/soong/scripts:strip.sh", 126 ), 127 _ar = attr.label( 128 cfg = "exec", 129 executable = True, 130 allow_single_file = True, 131 default = "//prebuilts/clang/host/linux-x86:llvm-ar", 132 ), 133 _strip = attr.label( 134 cfg = "exec", 135 executable = True, 136 allow_single_file = True, 137 default = "//prebuilts/clang/host/linux-x86:llvm-strip", 138 ), 139 _readelf = attr.label( 140 cfg = "exec", 141 executable = True, 142 allow_single_file = True, 143 default = "//prebuilts/clang/host/linux-x86:llvm-readelf", 144 ), 145 _objcopy = attr.label( 146 cfg = "exec", 147 executable = True, 148 allow_single_file = True, 149 default = "//prebuilts/clang/host/linux-x86:llvm-objcopy", 150 ), 151 _cc_toolchain = attr.label( 152 default = Label("@local_config_cc//:toolchain"), 153 providers = [cc_common.CcToolchainInfo], 154 ), 155 _android_constraint = attr.label( 156 default = Label("//build/bazel/platforms/os:android"), 157 ), 158) 159 160def _stripped_shared_library_impl(ctx): 161 out_file = stripped_impl(ctx, prefix = "lib", extension = ".so") 162 163 return [ 164 DefaultInfo(files = depset([out_file])), 165 ctx.attr.src[CcSharedLibraryInfo], 166 ctx.attr.src[OutputGroupInfo], 167 ] 168 169stripped_shared_library = rule( 170 implementation = _stripped_shared_library_impl, 171 attrs = dict( 172 common_strip_attrs, 173 src = attr.label( 174 mandatory = True, 175 # TODO(b/217908237): reenable allow_single_file 176 # allow_single_file = True, 177 providers = [CcSharedLibraryInfo], 178 ), 179 ), 180 toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], 181) 182 183# A marker provider to distinguish a cc_binary from everything else that exports 184# a CcInfo. 185StrippedCcBinaryInfo = provider() 186 187def _stripped_binary_impl(ctx): 188 common_providers = [ 189 ctx.attr.src[0][CcInfo], 190 ctx.attr.src[0][InstrumentedFilesInfo], 191 ctx.attr.src[0][DebugPackageInfo], 192 ctx.attr.src[0][OutputGroupInfo], 193 StrippedCcBinaryInfo(), # a marker for dependents 194 CcUnstrippedInfo( 195 unstripped = ctx.attr.unstripped, 196 ), 197 collect_deps_clang_tidy_info(ctx), 198 ] + [ 199 d[CcAndroidMkInfo] 200 for d in ctx.attr.androidmk_deps 201 ] 202 203 out_file = stripped_impl(ctx, suffix = ctx.attr.suffix) 204 205 return [ 206 DefaultInfo( 207 files = depset([out_file]), 208 executable = out_file, 209 ), 210 ] + common_providers 211 212_rule_attrs = dict( 213 common_strip_attrs, 214 src = attr.label( 215 mandatory = True, 216 allow_single_file = True, 217 providers = [CcInfo], 218 cfg = lto_deps_transition, 219 ), 220 runtime_deps = attr.label_list( 221 providers = [CcInfo], 222 doc = "Deps that should be installed along with this target. Read by the apex cc aspect.", 223 ), 224 androidmk_deps = attr.label_list( 225 providers = [CcAndroidMkInfo], 226 ), 227 suffix = attr.string(), 228 unstripped = attr.label( 229 mandatory = True, 230 allow_single_file = True, 231 cfg = lto_deps_transition, 232 doc = "Unstripped binary to be returned by ", 233 ), 234 _allowlist_function_transition = attr.label( 235 default = "@bazel_tools//tools/allowlists/function_transition_allowlist", 236 ), 237) 238 239stripped_binary = rule( 240 implementation = _stripped_binary_impl, 241 cfg = drop_lto_transition, 242 attrs = _rule_attrs, 243 executable = True, 244 toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], 245) 246 247stripped_test = rule( 248 implementation = _stripped_binary_impl, 249 cfg = drop_lto_transition, 250 attrs = _rule_attrs, 251 test = True, 252 toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], 253) 254