unplugged-system/build/bazel/rules/cc/cc_object.bzl

256 lines
9.6 KiB
Python

# Copyright (C) 2021 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load(":cc_constants.bzl", "constants")
load(
":cc_library_common.bzl",
"get_includes_paths",
"is_external_directory",
"parse_sdk_version",
"system_dynamic_deps_defaults",
)
load(":lto_transitions.bzl", "lto_deps_transition")
load(":stl.bzl", "stl_info_from_attr")
# "cc_object" module copts, taken from build/soong/cc/object.go
_CC_OBJECT_COPTS = ["-fno-addrsig"]
# partialLd module link opts, taken from build/soong/cc/builder.go
# https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/builder.go;l=87;drc=f2be52c4dcc2e3d743318e106633e61de0ad2afd
_CC_OBJECT_LINKOPTS = [
"-fuse-ld=lld",
"-nostdlib",
"-no-pie",
"-Wl,-r",
]
CcObjectInfo = provider(fields = [
# The merged compilation outputs for this cc_object and its transitive
# dependencies.
"objects",
])
def split_srcs_hdrs(files):
headers = []
non_headers_as = []
non_headers_c = []
for f in files:
if f.extension in constants.hdr_exts:
headers.append(f)
elif f.extension in constants.as_src_exts:
non_headers_as.append(f)
else:
non_headers_c.append(f)
return non_headers_c, non_headers_as, headers
def _cc_object_impl(ctx):
cc_toolchain = ctx.toolchains["//prebuilts/clang/host/linux-x86:nocrt_toolchain"].cc
extra_features = []
extra_disabled_features = [
"disable_pack_relocations",
"dynamic_executable",
"dynamic_linker",
"linker_flags",
"no_undefined_symbols",
"pack_dynamic_relocations",
"strip_debug_symbols",
# TODO(cparsons): Look into disabling this feature for nocrt toolchain?
"use_libcrt",
]
if is_external_directory(ctx.label.package):
extra_disabled_features.append("non_external_compiler_flags")
extra_features.append("external_compiler_flags")
else:
extra_features.append("non_external_compiler_flags")
extra_disabled_features.append("external_compiler_flags")
apex_min_sdk_version = ctx.attr._apex_min_sdk_version[BuildSettingInfo].value
if ctx.attr.crt and apex_min_sdk_version:
extra_disabled_features.append("sdk_version_default")
extra_features += parse_sdk_version(apex_min_sdk_version)
elif ctx.attr.min_sdk_version:
extra_disabled_features.append("sdk_version_default")
extra_features += parse_sdk_version(ctx.attr.min_sdk_version)
# Disable coverage for cc object because we link cc objects below and
# clang will link extra lib behind the scene to support profiling if coverage
# is enabled, so the symbols of the extra lib will be loaded into the generated
# object file. When later we link a shared library that depends on more than
# one such cc objects it will fail due to the duplicated symbols problem.
extra_disabled_features.append("coverage")
feature_configuration = cc_common.configure_features(
ctx = ctx,
cc_toolchain = cc_toolchain,
requested_features = ctx.features + extra_features,
unsupported_features = ctx.disabled_features + extra_disabled_features,
)
compilation_contexts = []
deps_objects = []
for obj in ctx.attr.objs:
compilation_contexts.append(obj[CcInfo].compilation_context)
deps_objects.append(obj[CcObjectInfo].objects)
for includes_dep in ctx.attr.includes_deps:
compilation_contexts.append(includes_dep[CcInfo].compilation_context)
product_variables = ctx.attr._android_product_variables[platform_common.TemplateVariableInfo]
asflags = [ctx.expand_make_variables("asflags", flag, product_variables.variables) for flag in ctx.attr.asflags]
srcs_c, srcs_as, private_hdrs = split_srcs_hdrs(ctx.files.srcs + ctx.files.srcs_as)
(compilation_context, compilation_outputs_c) = cc_common.compile(
name = ctx.label.name,
actions = ctx.actions,
feature_configuration = feature_configuration,
cc_toolchain = cc_toolchain,
srcs = srcs_c,
includes = get_includes_paths(ctx, ctx.attr.local_includes) + get_includes_paths(ctx, ctx.attr.absolute_includes, package_relative = False),
public_hdrs = ctx.files.hdrs,
private_hdrs = private_hdrs,
user_compile_flags = ctx.attr.copts,
compilation_contexts = compilation_contexts,
)
(compilation_context, compilation_outputs_as) = cc_common.compile(
name = ctx.label.name,
actions = ctx.actions,
feature_configuration = feature_configuration,
cc_toolchain = cc_toolchain,
srcs = srcs_as,
includes = get_includes_paths(ctx, ctx.attr.local_includes) + get_includes_paths(ctx, ctx.attr.absolute_includes, package_relative = False),
public_hdrs = ctx.files.hdrs,
private_hdrs = private_hdrs,
user_compile_flags = ctx.attr.copts + asflags,
compilation_contexts = compilation_contexts,
)
# do not propagate includes
compilation_context = cc_common.create_compilation_context(
headers = compilation_context.headers,
defines = compilation_context.defines,
local_defines = compilation_context.local_defines,
)
objects_to_link = cc_common.merge_compilation_outputs(compilation_outputs = deps_objects + [compilation_outputs_c, compilation_outputs_as])
user_link_flags = [] + ctx.attr.linkopts
user_link_flags.extend(_CC_OBJECT_LINKOPTS)
additional_inputs = []
if ctx.attr.linker_script != None:
linker_script = ctx.files.linker_script[0]
user_link_flags.append("-Wl,-T," + linker_script.path)
additional_inputs.append(linker_script)
# partially link if there are multiple object files
if len(objects_to_link.objects) + len(objects_to_link.pic_objects) > 1:
linking_output = cc_common.link(
name = ctx.label.name + ".o",
actions = ctx.actions,
feature_configuration = feature_configuration,
cc_toolchain = cc_toolchain,
user_link_flags = user_link_flags,
compilation_outputs = objects_to_link,
additional_inputs = additional_inputs,
)
files = depset([linking_output.executable])
else:
files = depset(objects_to_link.objects + objects_to_link.pic_objects)
return [
DefaultInfo(files = files),
CcInfo(compilation_context = compilation_context),
CcObjectInfo(objects = objects_to_link),
]
_cc_object = rule(
implementation = _cc_object_impl,
attrs = {
"srcs": attr.label_list(allow_files = constants.all_dot_exts),
"srcs_as": attr.label_list(allow_files = constants.all_dot_exts),
"hdrs": attr.label_list(allow_files = constants.hdr_dot_exts),
"absolute_includes": attr.string_list(),
"local_includes": attr.string_list(),
"copts": attr.string_list(),
"asflags": attr.string_list(),
"linkopts": attr.string_list(),
"objs": attr.label_list(
providers = [CcInfo, CcObjectInfo],
cfg = lto_deps_transition,
),
"includes_deps": attr.label_list(providers = [CcInfo]),
"linker_script": attr.label(allow_single_file = True),
"sdk_version": attr.string(),
"min_sdk_version": attr.string(),
"crt": attr.bool(default = False),
"_android_product_variables": attr.label(
default = Label("//build/bazel/product_config:product_vars"),
providers = [platform_common.TemplateVariableInfo],
),
"_apex_min_sdk_version": attr.label(
default = "//build/bazel/rules/apex:min_sdk_version",
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
toolchains = ["//prebuilts/clang/host/linux-x86:nocrt_toolchain"],
fragments = ["cpp"],
)
def cc_object(
name,
copts = [],
hdrs = [],
asflags = [],
linkopts = [],
srcs = [],
srcs_as = [],
objs = [],
deps = [],
native_bridge_supported = False, # TODO: not supported yet. @unused
stl = "",
system_dynamic_deps = None,
sdk_version = "",
min_sdk_version = "",
**kwargs):
"Build macro to correspond with the cc_object Soong module."
if system_dynamic_deps == None:
system_dynamic_deps = system_dynamic_deps_defaults
stl_info = stl_info_from_attr(stl, False)
linkopts = linkopts + stl_info.linkopts
copts = copts + stl_info.cppflags
_cc_object(
name = name,
hdrs = hdrs,
asflags = asflags,
copts = _CC_OBJECT_COPTS + copts,
linkopts = linkopts,
# TODO(b/261996812): we shouldn't need to have both srcs and srcs_as as inputs here
srcs = srcs,
srcs_as = srcs_as,
objs = objs,
includes_deps = stl_info.static_deps + stl_info.shared_deps + system_dynamic_deps + deps,
sdk_version = sdk_version,
min_sdk_version = min_sdk_version,
**kwargs
)