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(":lto_transitions.bzl", "lto_deps_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 _cc_object_impl(ctx): 59 cc_toolchain = ctx.toolchains["//prebuilts/clang/host/linux-x86:nocrt_toolchain"].cc 60 61 extra_features = [] 62 63 extra_disabled_features = [ 64 "disable_pack_relocations", 65 "dynamic_executable", 66 "dynamic_linker", 67 "linker_flags", 68 "no_undefined_symbols", 69 "pack_dynamic_relocations", 70 "strip_debug_symbols", 71 # TODO(cparsons): Look into disabling this feature for nocrt toolchain? 72 "use_libcrt", 73 ] 74 if is_external_directory(ctx.label.package): 75 extra_disabled_features.append("non_external_compiler_flags") 76 extra_features.append("external_compiler_flags") 77 else: 78 extra_features.append("non_external_compiler_flags") 79 extra_disabled_features.append("external_compiler_flags") 80 81 apex_min_sdk_version = ctx.attr._apex_min_sdk_version[BuildSettingInfo].value 82 if ctx.attr.crt and apex_min_sdk_version: 83 extra_disabled_features.append("sdk_version_default") 84 extra_features += parse_sdk_version(apex_min_sdk_version) 85 elif ctx.attr.min_sdk_version: 86 extra_disabled_features.append("sdk_version_default") 87 extra_features += parse_sdk_version(ctx.attr.min_sdk_version) 88 89 # Disable coverage for cc object because we link cc objects below and 90 # clang will link extra lib behind the scene to support profiling if coverage 91 # is enabled, so the symbols of the extra lib will be loaded into the generated 92 # object file. When later we link a shared library that depends on more than 93 # one such cc objects it will fail due to the duplicated symbols problem. 94 extra_disabled_features.append("coverage") 95 96 feature_configuration = cc_common.configure_features( 97 ctx = ctx, 98 cc_toolchain = cc_toolchain, 99 requested_features = ctx.features + extra_features, 100 unsupported_features = ctx.disabled_features + extra_disabled_features, 101 ) 102 103 compilation_contexts = [] 104 deps_objects = [] 105 for obj in ctx.attr.objs: 106 compilation_contexts.append(obj[CcInfo].compilation_context) 107 deps_objects.append(obj[CcObjectInfo].objects) 108 for includes_dep in ctx.attr.includes_deps: 109 compilation_contexts.append(includes_dep[CcInfo].compilation_context) 110 111 product_variables = ctx.attr._android_product_variables[platform_common.TemplateVariableInfo] 112 asflags = [ctx.expand_make_variables("asflags", flag, product_variables.variables) for flag in ctx.attr.asflags] 113 114 srcs_c, srcs_as, private_hdrs = split_srcs_hdrs(ctx.files.srcs + ctx.files.srcs_as) 115 116 (compilation_context, compilation_outputs_c) = cc_common.compile( 117 name = ctx.label.name, 118 actions = ctx.actions, 119 feature_configuration = feature_configuration, 120 cc_toolchain = cc_toolchain, 121 srcs = srcs_c, 122 includes = get_includes_paths(ctx, ctx.attr.local_includes) + get_includes_paths(ctx, ctx.attr.absolute_includes, package_relative = False), 123 public_hdrs = ctx.files.hdrs, 124 private_hdrs = private_hdrs, 125 user_compile_flags = ctx.attr.copts, 126 compilation_contexts = compilation_contexts, 127 ) 128 129 (compilation_context, compilation_outputs_as) = cc_common.compile( 130 name = ctx.label.name, 131 actions = ctx.actions, 132 feature_configuration = feature_configuration, 133 cc_toolchain = cc_toolchain, 134 srcs = srcs_as, 135 includes = get_includes_paths(ctx, ctx.attr.local_includes) + get_includes_paths(ctx, ctx.attr.absolute_includes, package_relative = False), 136 public_hdrs = ctx.files.hdrs, 137 private_hdrs = private_hdrs, 138 user_compile_flags = ctx.attr.copts + asflags, 139 compilation_contexts = compilation_contexts, 140 ) 141 142 # do not propagate includes 143 compilation_context = cc_common.create_compilation_context( 144 headers = compilation_context.headers, 145 defines = compilation_context.defines, 146 local_defines = compilation_context.local_defines, 147 ) 148 149 objects_to_link = cc_common.merge_compilation_outputs(compilation_outputs = deps_objects + [compilation_outputs_c, compilation_outputs_as]) 150 151 user_link_flags = [] + ctx.attr.linkopts 152 user_link_flags.extend(_CC_OBJECT_LINKOPTS) 153 additional_inputs = [] 154 155 if ctx.attr.linker_script != None: 156 linker_script = ctx.files.linker_script[0] 157 user_link_flags.append("-Wl,-T," + linker_script.path) 158 additional_inputs.append(linker_script) 159 160 # partially link if there are multiple object files 161 if len(objects_to_link.objects) + len(objects_to_link.pic_objects) > 1: 162 linking_output = cc_common.link( 163 name = ctx.label.name + ".o", 164 actions = ctx.actions, 165 feature_configuration = feature_configuration, 166 cc_toolchain = cc_toolchain, 167 user_link_flags = user_link_flags, 168 compilation_outputs = objects_to_link, 169 additional_inputs = additional_inputs, 170 ) 171 files = depset([linking_output.executable]) 172 else: 173 files = depset(objects_to_link.objects + objects_to_link.pic_objects) 174 175 return [ 176 DefaultInfo(files = files), 177 CcInfo(compilation_context = compilation_context), 178 CcObjectInfo(objects = objects_to_link), 179 ] 180 181_cc_object = rule( 182 implementation = _cc_object_impl, 183 attrs = { 184 "srcs": attr.label_list(allow_files = constants.all_dot_exts), 185 "srcs_as": attr.label_list(allow_files = constants.all_dot_exts), 186 "hdrs": attr.label_list(allow_files = constants.hdr_dot_exts), 187 "absolute_includes": attr.string_list(), 188 "local_includes": attr.string_list(), 189 "copts": attr.string_list(), 190 "asflags": attr.string_list(), 191 "linkopts": attr.string_list(), 192 "objs": attr.label_list( 193 providers = [CcInfo, CcObjectInfo], 194 cfg = lto_deps_transition, 195 ), 196 "includes_deps": attr.label_list(providers = [CcInfo]), 197 "linker_script": attr.label(allow_single_file = True), 198 "sdk_version": attr.string(), 199 "min_sdk_version": attr.string(), 200 "crt": attr.bool(default = False), 201 "_android_product_variables": attr.label( 202 default = Label("//build/bazel/product_config:product_vars"), 203 providers = [platform_common.TemplateVariableInfo], 204 ), 205 "_apex_min_sdk_version": attr.label( 206 default = "//build/bazel/rules/apex:min_sdk_version", 207 ), 208 "_allowlist_function_transition": attr.label( 209 default = "@bazel_tools//tools/allowlists/function_transition_allowlist", 210 ), 211 }, 212 toolchains = ["//prebuilts/clang/host/linux-x86:nocrt_toolchain"], 213 fragments = ["cpp"], 214) 215 216def cc_object( 217 name, 218 copts = [], 219 hdrs = [], 220 asflags = [], 221 linkopts = [], 222 srcs = [], 223 srcs_as = [], 224 objs = [], 225 deps = [], 226 native_bridge_supported = False, # TODO: not supported yet. @unused 227 stl = "", 228 system_dynamic_deps = None, 229 sdk_version = "", 230 min_sdk_version = "", 231 **kwargs): 232 "Build macro to correspond with the cc_object Soong module." 233 234 if system_dynamic_deps == None: 235 system_dynamic_deps = system_dynamic_deps_defaults 236 237 stl_info = stl_info_from_attr(stl, False) 238 linkopts = linkopts + stl_info.linkopts 239 copts = copts + stl_info.cppflags 240 241 _cc_object( 242 name = name, 243 hdrs = hdrs, 244 asflags = asflags, 245 copts = _CC_OBJECT_COPTS + copts, 246 linkopts = linkopts, 247 # TODO(b/261996812): we shouldn't need to have both srcs and srcs_as as inputs here 248 srcs = srcs, 249 srcs_as = srcs_as, 250 objs = objs, 251 includes_deps = stl_info.static_deps + stl_info.shared_deps + system_dynamic_deps + deps, 252 sdk_version = sdk_version, 253 min_sdk_version = min_sdk_version, 254 **kwargs 255 ) 256