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 15load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") 16load(":cc_constants.bzl", "constants") 17load( 18 ":cc_library_common.bzl", 19 "get_includes_paths", 20 "is_external_directory", 21 "parse_sdk_version", 22 "system_dynamic_deps_defaults", 23) 24load(":composed_transitions.bzl", "drop_sanitizer_transition") 25load(":stl.bzl", "stl_info_from_attr") 26 27# "cc_object" module copts, taken from build/soong/cc/object.go 28_CC_OBJECT_COPTS = ["-fno-addrsig"] 29 30# partialLd module link opts, taken from build/soong/cc/builder.go 31# https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/builder.go;l=87;drc=f2be52c4dcc2e3d743318e106633e61de0ad2afd 32_CC_OBJECT_LINKOPTS = [ 33 "-fuse-ld=lld", 34 "-nostdlib", 35 "-no-pie", 36 "-Wl,-r", 37] 38 39CcObjectInfo = provider(fields = [ 40 # The merged compilation outputs for this cc_object and its transitive 41 # dependencies. 42 "objects", 43]) 44 45def split_srcs_hdrs(files): 46 headers = [] 47 non_headers_as = [] 48 non_headers_c = [] 49 for f in files: 50 if f.extension in constants.hdr_exts: 51 headers.append(f) 52 elif f.extension in constants.as_src_exts: 53 non_headers_as.append(f) 54 else: 55 non_headers_c.append(f) 56 return non_headers_c, non_headers_as, headers 57 58def _objcopy_noaddrsig(ctx, noaddrsig_output, linking_output, cc_toolchain): 59 output_file = ctx.actions.declare_file(noaddrsig_output) 60 61 feature_configuration = cc_common.configure_features( 62 ctx = ctx, 63 cc_toolchain = cc_toolchain, 64 requested_features = ctx.features, 65 unsupported_features = ctx.disabled_features, 66 ) 67 68 objcopy_path = cc_common.get_tool_for_action( 69 feature_configuration = feature_configuration, 70 action_name = "objcopy", 71 ) 72 command_line = cc_common.get_memory_inefficient_command_line( 73 feature_configuration = feature_configuration, 74 action_name = "objcopy", 75 variables = cc_common.empty_variables(), 76 ) 77 78 args = ctx.actions.args() 79 args.add_all(command_line) 80 args.add("--remove-section=.llvm_addrsig") 81 args.add(linking_output.executable) 82 args.add(output_file) 83 84 ctx.actions.run( 85 executable = objcopy_path, 86 arguments = [args], 87 inputs = depset( 88 direct = [linking_output.executable], 89 transitive = [ 90 cc_toolchain.all_files, 91 ], 92 ), 93 outputs = [output_file], 94 mnemonic = "CppObjcopyNoAddrsig", 95 ) 96 97 return output_file 98 99def _cc_object_impl(ctx): 100 cc_toolchain = ctx.toolchains["//prebuilts/clang/host/linux-x86:nocrt_toolchain"].cc 101 102 extra_features = [] 103 104 extra_disabled_features = [ 105 "disable_pack_relocations", 106 "dynamic_executable", 107 "dynamic_linker", 108 "linker_flags", 109 "no_undefined_symbols", 110 "pack_dynamic_relocations", 111 "strip_debug_symbols", 112 # TODO(cparsons): Look into disabling this feature for nocrt toolchain? 113 "use_libcrt", 114 ] 115 if is_external_directory(ctx.label.package): 116 extra_disabled_features.append("non_external_compiler_flags") 117 extra_features.append("external_compiler_flags") 118 else: 119 extra_features.append("non_external_compiler_flags") 120 extra_disabled_features.append("external_compiler_flags") 121 122 apex_min_sdk_version = ctx.attr._apex_min_sdk_version[BuildSettingInfo].value 123 if ctx.attr.crt and apex_min_sdk_version: 124 extra_disabled_features.append("sdk_version_default") 125 extra_features += parse_sdk_version(apex_min_sdk_version) 126 elif ctx.attr.min_sdk_version: 127 extra_disabled_features.append("sdk_version_default") 128 extra_features += parse_sdk_version(ctx.attr.min_sdk_version) 129 130 # Disable coverage for cc object because we link cc objects below and 131 # clang will link extra lib behind the scene to support profiling if coverage 132 # is enabled, so the symbols of the extra lib will be loaded into the generated 133 # object file. When later we link a shared library that depends on more than 134 # one such cc objects it will fail due to the duplicated symbols problem. 135 extra_disabled_features.append("coverage") 136 137 feature_configuration = cc_common.configure_features( 138 ctx = ctx, 139 cc_toolchain = cc_toolchain, 140 requested_features = ctx.features + extra_features, 141 unsupported_features = ctx.disabled_features + extra_disabled_features, 142 ) 143 144 compilation_contexts = [] 145 deps_objects = [] 146 for obj in ctx.attr.objs: 147 compilation_contexts.append(obj[CcInfo].compilation_context) 148 deps_objects.append(obj[CcObjectInfo].objects) 149 for includes_dep in ctx.attr.includes_deps: 150 compilation_contexts.append(includes_dep[CcInfo].compilation_context) 151 152 product_variables = ctx.attr._android_product_variables[platform_common.TemplateVariableInfo] 153 asflags = [ctx.expand_make_variables("asflags", flag, product_variables.variables) for flag in ctx.attr.asflags] 154 155 srcs_c, srcs_as, private_hdrs = split_srcs_hdrs(ctx.files.srcs + ctx.files.srcs_as) 156 157 (compilation_context, compilation_outputs_c) = cc_common.compile( 158 name = ctx.label.name, 159 actions = ctx.actions, 160 feature_configuration = feature_configuration, 161 cc_toolchain = cc_toolchain, 162 srcs = srcs_c, 163 includes = get_includes_paths(ctx, ctx.attr.local_includes) + get_includes_paths(ctx, ctx.attr.absolute_includes, package_relative = False), 164 public_hdrs = ctx.files.hdrs, 165 private_hdrs = private_hdrs, 166 user_compile_flags = ctx.attr.copts, 167 compilation_contexts = compilation_contexts, 168 ) 169 170 (compilation_context, compilation_outputs_as) = cc_common.compile( 171 name = ctx.label.name, 172 actions = ctx.actions, 173 feature_configuration = feature_configuration, 174 cc_toolchain = cc_toolchain, 175 srcs = srcs_as, 176 includes = get_includes_paths(ctx, ctx.attr.local_includes) + get_includes_paths(ctx, ctx.attr.absolute_includes, package_relative = False), 177 public_hdrs = ctx.files.hdrs, 178 private_hdrs = private_hdrs, 179 user_compile_flags = ctx.attr.copts + asflags, 180 compilation_contexts = compilation_contexts, 181 ) 182 183 # do not propagate includes 184 compilation_context = cc_common.create_compilation_context( 185 headers = compilation_context.headers, 186 defines = compilation_context.defines, 187 local_defines = compilation_context.local_defines, 188 ) 189 190 objects_to_link = cc_common.merge_compilation_outputs(compilation_outputs = deps_objects + [compilation_outputs_c, compilation_outputs_as]) 191 192 user_link_flags = [] + ctx.attr.linkopts 193 user_link_flags.extend(_CC_OBJECT_LINKOPTS) 194 additional_inputs = [] 195 196 if ctx.attr.linker_script != None: 197 linker_script = ctx.files.linker_script[0] 198 user_link_flags.append("-Wl,-T," + linker_script.path) 199 additional_inputs.append(linker_script) 200 201 # partially link if there are multiple object files 202 if len(objects_to_link.objects) + len(objects_to_link.pic_objects) > 1: 203 linking_output = cc_common.link( 204 name = ctx.label.name + ".addrsig.o", 205 actions = ctx.actions, 206 feature_configuration = feature_configuration, 207 cc_toolchain = cc_toolchain, 208 user_link_flags = user_link_flags, 209 compilation_outputs = objects_to_link, 210 additional_inputs = additional_inputs, 211 ) 212 213 noaddrsig_output = _objcopy_noaddrsig(ctx, ctx.label.name + ".o", linking_output, cc_toolchain) 214 215 files = depset([noaddrsig_output]) 216 else: 217 files = depset(objects_to_link.objects + objects_to_link.pic_objects) 218 219 return [ 220 DefaultInfo(files = files), 221 CcInfo(compilation_context = compilation_context), 222 CcObjectInfo(objects = objects_to_link), 223 ] 224 225_cc_object = rule( 226 implementation = _cc_object_impl, 227 cfg = drop_sanitizer_transition, 228 attrs = { 229 "srcs": attr.label_list(allow_files = constants.all_dot_exts), 230 "srcs_as": attr.label_list(allow_files = constants.all_dot_exts), 231 "hdrs": attr.label_list(allow_files = constants.hdr_dot_exts), 232 "absolute_includes": attr.string_list(), 233 "local_includes": attr.string_list(), 234 "copts": attr.string_list(), 235 "asflags": attr.string_list(), 236 "linkopts": attr.string_list(), 237 "objs": attr.label_list( 238 providers = [CcInfo, CcObjectInfo], 239 ), 240 "includes_deps": attr.label_list(providers = [CcInfo]), 241 "linker_script": attr.label(allow_single_file = True), 242 "sdk_version": attr.string(), 243 "min_sdk_version": attr.string(), 244 "crt": attr.bool(default = False), 245 "package_name": attr.string( 246 mandatory = True, 247 doc = "Just the path to the target package. Used by transitions.", 248 ), 249 "_android_product_variables": attr.label( 250 default = Label("//build/bazel/product_config:product_variables_for_attributes"), 251 providers = [platform_common.TemplateVariableInfo], 252 ), 253 "_apex_min_sdk_version": attr.label( 254 default = "//build/bazel/rules/apex:min_sdk_version", 255 ), 256 "_allowlist_function_transition": attr.label( 257 default = "@bazel_tools//tools/allowlists/function_transition_allowlist", 258 ), 259 }, 260 toolchains = ["//prebuilts/clang/host/linux-x86:nocrt_toolchain"], 261 fragments = ["cpp"], 262) 263 264def cc_object( 265 name, 266 copts = [], 267 hdrs = [], 268 asflags = [], 269 linkopts = [], 270 srcs = [], 271 srcs_as = [], 272 objs = [], 273 deps = [], 274 native_bridge_supported = False, # TODO: not supported yet. @unused 275 stl = "", 276 system_dynamic_deps = None, 277 sdk_version = "", 278 min_sdk_version = "", 279 **kwargs): 280 "Build macro to correspond with the cc_object Soong module." 281 282 if system_dynamic_deps == None: 283 system_dynamic_deps = system_dynamic_deps_defaults 284 285 stl_info = stl_info_from_attr(stl, False) 286 linkopts = linkopts + stl_info.linkopts 287 copts = copts + stl_info.cppflags 288 289 _cc_object( 290 name = name, 291 hdrs = hdrs, 292 asflags = asflags, 293 copts = _CC_OBJECT_COPTS + copts, 294 linkopts = linkopts, 295 # TODO(b/261996812): we shouldn't need to have both srcs and srcs_as as inputs here 296 srcs = srcs, 297 srcs_as = srcs_as, 298 objs = objs, 299 includes_deps = stl_info.static_deps + stl_info.shared_deps + system_dynamic_deps + deps, 300 sdk_version = sdk_version, 301 min_sdk_version = min_sdk_version, 302 package_name = native.package_name(), 303 **kwargs 304 ) 305