• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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