xref: /aosp_15_r20/build/bazel/rules/abi/abi_dump.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
1*7594170eSAndroid Build Coastguard Worker# Copyright (C) 2022 The Android Open Source Project
2*7594170eSAndroid Build Coastguard Worker#
3*7594170eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*7594170eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*7594170eSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*7594170eSAndroid Build Coastguard Worker#
7*7594170eSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*7594170eSAndroid Build Coastguard Worker#
9*7594170eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*7594170eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*7594170eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*7594170eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*7594170eSAndroid Build Coastguard Worker# limitations under the License.
14*7594170eSAndroid Build Coastguard Worker
15*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:paths.bzl", "paths")
16*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
17*7594170eSAndroid Build Coastguard Workerload(
18*7594170eSAndroid Build Coastguard Worker    "@bazel_tools//tools/build_defs/cc:action_names.bzl",
19*7594170eSAndroid Build Coastguard Worker    "CPP_COMPILE_ACTION_NAME",
20*7594170eSAndroid Build Coastguard Worker    "C_COMPILE_ACTION_NAME",
21*7594170eSAndroid Build Coastguard Worker)
22*7594170eSAndroid Build Coastguard Workerload("@soong_injection//api_levels:platform_versions.bzl", "platform_versions")
23*7594170eSAndroid Build Coastguard Workerload("//build/bazel/platforms:platform_utils.bzl", "platforms")
24*7594170eSAndroid Build Coastguard Workerload(
25*7594170eSAndroid Build Coastguard Worker    "//build/bazel/rules/cc:cc_library_common.bzl",
26*7594170eSAndroid Build Coastguard Worker    "build_compilation_flags",
27*7594170eSAndroid Build Coastguard Worker    "get_non_header_srcs",
28*7594170eSAndroid Build Coastguard Worker    "is_bionic_lib",
29*7594170eSAndroid Build Coastguard Worker    "is_bootstrap_lib",
30*7594170eSAndroid Build Coastguard Worker    "parse_apex_sdk_version",
31*7594170eSAndroid Build Coastguard Worker)
32*7594170eSAndroid Build Coastguard Workerload("//build/bazel/rules/cc:cc_library_static.bzl", "CcStaticLibraryInfo")
33*7594170eSAndroid Build Coastguard Worker
34*7594170eSAndroid Build Coastguard WorkerAbiDumpInfo = provider(fields = ["dump_files"])
35*7594170eSAndroid Build Coastguard WorkerAbiDiffInfo = provider(fields = ["diff_files"])
36*7594170eSAndroid Build Coastguard Worker
37*7594170eSAndroid Build Coastguard Worker_ABI_CLASS_PLATFORM = "platform"
38*7594170eSAndroid Build Coastguard Worker
39*7594170eSAndroid Build Coastguard Workerdef _abi_dump_aspect_impl(target, ctx):
40*7594170eSAndroid Build Coastguard Worker    if not _abi_diff_enabled(ctx, ctx.label.name, True):
41*7594170eSAndroid Build Coastguard Worker        return [
42*7594170eSAndroid Build Coastguard Worker            AbiDumpInfo(
43*7594170eSAndroid Build Coastguard Worker                dump_files = depset(),
44*7594170eSAndroid Build Coastguard Worker            ),
45*7594170eSAndroid Build Coastguard Worker        ]
46*7594170eSAndroid Build Coastguard Worker
47*7594170eSAndroid Build Coastguard Worker    transitive_dumps = []
48*7594170eSAndroid Build Coastguard Worker    direct_dumps = []
49*7594170eSAndroid Build Coastguard Worker
50*7594170eSAndroid Build Coastguard Worker    if CcStaticLibraryInfo in target:
51*7594170eSAndroid Build Coastguard Worker        direct_dumps.extend(_create_abi_dumps(
52*7594170eSAndroid Build Coastguard Worker            ctx,
53*7594170eSAndroid Build Coastguard Worker            target,
54*7594170eSAndroid Build Coastguard Worker            ctx.rule.files.srcs_cpp,
55*7594170eSAndroid Build Coastguard Worker            ctx.rule.attr.copts_cpp,
56*7594170eSAndroid Build Coastguard Worker            CPP_COMPILE_ACTION_NAME,
57*7594170eSAndroid Build Coastguard Worker        ))
58*7594170eSAndroid Build Coastguard Worker        direct_dumps.extend(_create_abi_dumps(
59*7594170eSAndroid Build Coastguard Worker            ctx,
60*7594170eSAndroid Build Coastguard Worker            target,
61*7594170eSAndroid Build Coastguard Worker            ctx.rule.files.srcs_c,
62*7594170eSAndroid Build Coastguard Worker            ctx.rule.attr.copts_c,
63*7594170eSAndroid Build Coastguard Worker            C_COMPILE_ACTION_NAME,
64*7594170eSAndroid Build Coastguard Worker        ))
65*7594170eSAndroid Build Coastguard Worker
66*7594170eSAndroid Build Coastguard Worker        for dep in ctx.rule.attr.static_deps:
67*7594170eSAndroid Build Coastguard Worker            if AbiDumpInfo in dep:
68*7594170eSAndroid Build Coastguard Worker                transitive_dumps.append(dep[AbiDumpInfo].dump_files)
69*7594170eSAndroid Build Coastguard Worker
70*7594170eSAndroid Build Coastguard Worker    return [
71*7594170eSAndroid Build Coastguard Worker        AbiDumpInfo(
72*7594170eSAndroid Build Coastguard Worker            dump_files = depset(
73*7594170eSAndroid Build Coastguard Worker                direct_dumps,
74*7594170eSAndroid Build Coastguard Worker                transitive = transitive_dumps,
75*7594170eSAndroid Build Coastguard Worker            ),
76*7594170eSAndroid Build Coastguard Worker        ),
77*7594170eSAndroid Build Coastguard Worker    ]
78*7594170eSAndroid Build Coastguard Worker
79*7594170eSAndroid Build Coastguard Workerabi_dump_aspect = aspect(
80*7594170eSAndroid Build Coastguard Worker    implementation = _abi_dump_aspect_impl,
81*7594170eSAndroid Build Coastguard Worker    attr_aspects = ["static_deps", "whole_archive_deps"],
82*7594170eSAndroid Build Coastguard Worker    attrs = {
83*7594170eSAndroid Build Coastguard Worker        "_skip_abi_checks": attr.label(
84*7594170eSAndroid Build Coastguard Worker            default = "//build/bazel/flags/cc/abi:skip_abi_checks",
85*7594170eSAndroid Build Coastguard Worker        ),
86*7594170eSAndroid Build Coastguard Worker        # Need this in order to call _abi_diff_enabled in the aspects code.
87*7594170eSAndroid Build Coastguard Worker        "_within_apex": attr.label(
88*7594170eSAndroid Build Coastguard Worker            default = "//build/bazel/rules/apex:within_apex",
89*7594170eSAndroid Build Coastguard Worker        ),
90*7594170eSAndroid Build Coastguard Worker        "_abi_dumper": attr.label(
91*7594170eSAndroid Build Coastguard Worker            allow_files = True,
92*7594170eSAndroid Build Coastguard Worker            executable = True,
93*7594170eSAndroid Build Coastguard Worker            cfg = "exec",
94*7594170eSAndroid Build Coastguard Worker            default = Label("//prebuilts/clang-tools:linux-x86/bin/header-abi-dumper"),
95*7594170eSAndroid Build Coastguard Worker        ),
96*7594170eSAndroid Build Coastguard Worker        "_platform_utils": attr.label(default = Label("//build/bazel/platforms:platform_utils")),
97*7594170eSAndroid Build Coastguard Worker    },
98*7594170eSAndroid Build Coastguard Worker    toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
99*7594170eSAndroid Build Coastguard Worker    fragments = ["cpp"],
100*7594170eSAndroid Build Coastguard Worker    provides = [AbiDumpInfo],
101*7594170eSAndroid Build Coastguard Worker)
102*7594170eSAndroid Build Coastguard Worker
103*7594170eSAndroid Build Coastguard Workerdef _create_abi_dumps(ctx, target, srcs, user_flags, action_name):
104*7594170eSAndroid Build Coastguard Worker    dumps = []
105*7594170eSAndroid Build Coastguard Worker
106*7594170eSAndroid Build Coastguard Worker    if len(srcs) == 0:
107*7594170eSAndroid Build Coastguard Worker        return dumps
108*7594170eSAndroid Build Coastguard Worker
109*7594170eSAndroid Build Coastguard Worker    compilation_context, compilation_flags = build_compilation_flags(
110*7594170eSAndroid Build Coastguard Worker        ctx,
111*7594170eSAndroid Build Coastguard Worker        ctx.rule.attr.roots + ctx.rule.attr.deps + ctx.rule.attr.includes,
112*7594170eSAndroid Build Coastguard Worker        user_flags,
113*7594170eSAndroid Build Coastguard Worker        action_name,
114*7594170eSAndroid Build Coastguard Worker    )
115*7594170eSAndroid Build Coastguard Worker    sources, headers = get_non_header_srcs(srcs)
116*7594170eSAndroid Build Coastguard Worker
117*7594170eSAndroid Build Coastguard Worker    header_inputs = (
118*7594170eSAndroid Build Coastguard Worker        headers +
119*7594170eSAndroid Build Coastguard Worker        compilation_context.headers.to_list() +
120*7594170eSAndroid Build Coastguard Worker        compilation_context.direct_headers +
121*7594170eSAndroid Build Coastguard Worker        compilation_context.direct_private_headers +
122*7594170eSAndroid Build Coastguard Worker        compilation_context.direct_public_headers +
123*7594170eSAndroid Build Coastguard Worker        compilation_context.direct_textual_headers
124*7594170eSAndroid Build Coastguard Worker    )
125*7594170eSAndroid Build Coastguard Worker    objects = []
126*7594170eSAndroid Build Coastguard Worker    linker_inputs = target[CcInfo].linking_context.linker_inputs.to_list()
127*7594170eSAndroid Build Coastguard Worker
128*7594170eSAndroid Build Coastguard Worker    # These are created in cc_library_static and there should be only one
129*7594170eSAndroid Build Coastguard Worker    # linker_inputs and one libraries
130*7594170eSAndroid Build Coastguard Worker    if CcInfo in target and len(linker_inputs) == 1 and len(linker_inputs[0].libraries) == 1:
131*7594170eSAndroid Build Coastguard Worker        objects = linker_inputs[0].libraries[0].objects
132*7594170eSAndroid Build Coastguard Worker    for file in sources:
133*7594170eSAndroid Build Coastguard Worker        output = _create_abi_dump(ctx, target, file, objects, header_inputs, compilation_flags)
134*7594170eSAndroid Build Coastguard Worker        dumps.append(output)
135*7594170eSAndroid Build Coastguard Worker
136*7594170eSAndroid Build Coastguard Worker    return dumps
137*7594170eSAndroid Build Coastguard Worker
138*7594170eSAndroid Build Coastguard Workerdef _include_flag(flag):
139*7594170eSAndroid Build Coastguard Worker    return ["-I", flag]
140*7594170eSAndroid Build Coastguard Worker
141*7594170eSAndroid Build Coastguard Workerdef _create_abi_dump(ctx, target, src, objects, header_inputs, compilation_flags):
142*7594170eSAndroid Build Coastguard Worker    """ Utility function to generate abi dump file."""
143*7594170eSAndroid Build Coastguard Worker
144*7594170eSAndroid Build Coastguard Worker    file = paths.join(src.dirname, target.label.name + "." + src.basename + ".sdump")
145*7594170eSAndroid Build Coastguard Worker    output = ctx.actions.declare_file(file)
146*7594170eSAndroid Build Coastguard Worker    args = ctx.actions.args()
147*7594170eSAndroid Build Coastguard Worker
148*7594170eSAndroid Build Coastguard Worker    args.add("--root-dir", ".")
149*7594170eSAndroid Build Coastguard Worker    args.add("-o", output)
150*7594170eSAndroid Build Coastguard Worker    args.add(src)
151*7594170eSAndroid Build Coastguard Worker
152*7594170eSAndroid Build Coastguard Worker    args.add_all(ctx.rule.attr.exports[0][CcInfo].compilation_context.includes.to_list(), map_each = _include_flag)
153*7594170eSAndroid Build Coastguard Worker
154*7594170eSAndroid Build Coastguard Worker    args.add("--")
155*7594170eSAndroid Build Coastguard Worker    args.add_all(compilation_flags)
156*7594170eSAndroid Build Coastguard Worker
157*7594170eSAndroid Build Coastguard Worker    # The following two args come from here:
158*7594170eSAndroid Build Coastguard Worker    # https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/builder.go;l=247;drc=ba17c7243d0e297efbc6fb5385d6d5aa81db9152
159*7594170eSAndroid Build Coastguard Worker    args.add("-w")
160*7594170eSAndroid Build Coastguard Worker
161*7594170eSAndroid Build Coastguard Worker    # TODO(b/254625084): support darwin as well.
162*7594170eSAndroid Build Coastguard Worker    args.add("-isystem", "prebuilts/clang-tools/linux-x86/clang-headers")
163*7594170eSAndroid Build Coastguard Worker
164*7594170eSAndroid Build Coastguard Worker    ctx.actions.run(
165*7594170eSAndroid Build Coastguard Worker        inputs = [src] + header_inputs + objects,
166*7594170eSAndroid Build Coastguard Worker        executable = ctx.executable._abi_dumper,
167*7594170eSAndroid Build Coastguard Worker        outputs = [output],
168*7594170eSAndroid Build Coastguard Worker        arguments = [args],
169*7594170eSAndroid Build Coastguard Worker        # TODO(b/186116353): enable sandbox once the bug is fixed.
170*7594170eSAndroid Build Coastguard Worker        execution_requirements = {
171*7594170eSAndroid Build Coastguard Worker            "no-sandbox": "1",
172*7594170eSAndroid Build Coastguard Worker        },
173*7594170eSAndroid Build Coastguard Worker        mnemonic = "AbiDump",
174*7594170eSAndroid Build Coastguard Worker    )
175*7594170eSAndroid Build Coastguard Worker
176*7594170eSAndroid Build Coastguard Worker    return output
177*7594170eSAndroid Build Coastguard Worker
178*7594170eSAndroid Build Coastguard Workerdef create_linked_abi_dump(ctx, dump_files):
179*7594170eSAndroid Build Coastguard Worker    """ Utility function to generate abi dump files."""
180*7594170eSAndroid Build Coastguard Worker    shared_files = ctx.attr.shared[DefaultInfo].files.to_list()
181*7594170eSAndroid Build Coastguard Worker    if len(shared_files) != 1:
182*7594170eSAndroid Build Coastguard Worker        fail("Expected only one shared library file")
183*7594170eSAndroid Build Coastguard Worker
184*7594170eSAndroid Build Coastguard Worker    file = ctx.attr.soname + ".lsdump"
185*7594170eSAndroid Build Coastguard Worker    output = ctx.actions.declare_file(file)
186*7594170eSAndroid Build Coastguard Worker    args = ctx.actions.args()
187*7594170eSAndroid Build Coastguard Worker
188*7594170eSAndroid Build Coastguard Worker    args.add("--root-dir", ".")
189*7594170eSAndroid Build Coastguard Worker    args.add("-o", output)
190*7594170eSAndroid Build Coastguard Worker    args.add("-so", shared_files[0])
191*7594170eSAndroid Build Coastguard Worker    inputs = dump_files + [shared_files[0]]
192*7594170eSAndroid Build Coastguard Worker
193*7594170eSAndroid Build Coastguard Worker    if ctx.file.symbol_file:
194*7594170eSAndroid Build Coastguard Worker        args.add("-v", ctx.file.symbol_file.path)
195*7594170eSAndroid Build Coastguard Worker        inputs.append(ctx.file.symbol_file)
196*7594170eSAndroid Build Coastguard Worker    for v in ctx.attr.exclude_symbol_versions:
197*7594170eSAndroid Build Coastguard Worker        args.add("--exclude-symbol-version", v)
198*7594170eSAndroid Build Coastguard Worker    for t in ctx.attr.exclude_symbol_tags:
199*7594170eSAndroid Build Coastguard Worker        args.add("--exclude-symbol-tag", t)
200*7594170eSAndroid Build Coastguard Worker
201*7594170eSAndroid Build Coastguard Worker    args.add("-arch", platforms.get_target_arch(ctx.attr._platform_utils))
202*7594170eSAndroid Build Coastguard Worker
203*7594170eSAndroid Build Coastguard Worker    args.add_all(ctx.attr.root[CcInfo].compilation_context.includes.to_list(), map_each = _include_flag)
204*7594170eSAndroid Build Coastguard Worker
205*7594170eSAndroid Build Coastguard Worker    args.add_all([d.path for d in dump_files])
206*7594170eSAndroid Build Coastguard Worker
207*7594170eSAndroid Build Coastguard Worker    ctx.actions.run(
208*7594170eSAndroid Build Coastguard Worker        inputs = inputs,
209*7594170eSAndroid Build Coastguard Worker        executable = ctx.executable._abi_linker,
210*7594170eSAndroid Build Coastguard Worker        outputs = [output],
211*7594170eSAndroid Build Coastguard Worker        arguments = [args],
212*7594170eSAndroid Build Coastguard Worker        # TODO(b/186116353): enable sandbox once the bug is fixed.
213*7594170eSAndroid Build Coastguard Worker        execution_requirements = {
214*7594170eSAndroid Build Coastguard Worker            "no-sandbox": "1",
215*7594170eSAndroid Build Coastguard Worker        },
216*7594170eSAndroid Build Coastguard Worker        mnemonic = "AbiLink",
217*7594170eSAndroid Build Coastguard Worker    )
218*7594170eSAndroid Build Coastguard Worker
219*7594170eSAndroid Build Coastguard Worker    return output
220*7594170eSAndroid Build Coastguard Worker
221*7594170eSAndroid Build Coastguard Workerdef find_abi_config(_ctx):
222*7594170eSAndroid Build Coastguard Worker    sdk_version = str(platform_versions.platform_sdk_version)
223*7594170eSAndroid Build Coastguard Worker    prev_version = int(parse_apex_sdk_version(sdk_version))
224*7594170eSAndroid Build Coastguard Worker    version = "current"
225*7594170eSAndroid Build Coastguard Worker    if platform_versions.platform_sdk_final:
226*7594170eSAndroid Build Coastguard Worker        prev_version -= 1
227*7594170eSAndroid Build Coastguard Worker        version = sdk_version
228*7594170eSAndroid Build Coastguard Worker
229*7594170eSAndroid Build Coastguard Worker    return prev_version, version
230*7594170eSAndroid Build Coastguard Worker
231*7594170eSAndroid Build Coastguard Workerdef create_abi_diff(ctx, dump_file):
232*7594170eSAndroid Build Coastguard Worker    prev_version, version = find_abi_config(ctx)
233*7594170eSAndroid Build Coastguard Worker
234*7594170eSAndroid Build Coastguard Worker    arch = platforms.get_target_arch(ctx.attr._platform_utils)
235*7594170eSAndroid Build Coastguard Worker    bitness = platforms.get_target_bitness(ctx.attr._platform_utils)
236*7594170eSAndroid Build Coastguard Worker    abi_class = _ABI_CLASS_PLATFORM
237*7594170eSAndroid Build Coastguard Worker
238*7594170eSAndroid Build Coastguard Worker    # The logic below comes from:
239*7594170eSAndroid Build Coastguard Worker    # https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/library.go;l=1891;drc=c645853ab73ac8c5889b42f4ce7dc9353ee8fd35
240*7594170eSAndroid Build Coastguard Worker    abi_reference_file = None
241*7594170eSAndroid Build Coastguard Worker    if not platform_versions.platform_sdk_final:
242*7594170eSAndroid Build Coastguard Worker        abi_reference_file = _find_abi_ref_file(ctx, prev_version, arch, bitness, abi_class, dump_file.basename)
243*7594170eSAndroid Build Coastguard Worker        if not abi_reference_file:
244*7594170eSAndroid Build Coastguard Worker            prev_version -= 1
245*7594170eSAndroid Build Coastguard Worker
246*7594170eSAndroid Build Coastguard Worker    diff_files = []
247*7594170eSAndroid Build Coastguard Worker
248*7594170eSAndroid Build Coastguard Worker    # We need to do the abi check for the previous version and current version if the reference
249*7594170eSAndroid Build Coastguard Worker    # abi dump files are available. If the current previous version doesn't have the reference
250*7594170eSAndroid Build Coastguard Worker    # abi dump file we will check against one version earlier.
251*7594170eSAndroid Build Coastguard Worker    if not abi_reference_file:
252*7594170eSAndroid Build Coastguard Worker        abi_reference_file = _find_abi_ref_file(ctx, prev_version, arch, bitness, abi_class, dump_file.basename)
253*7594170eSAndroid Build Coastguard Worker    if abi_reference_file:
254*7594170eSAndroid Build Coastguard Worker        diff_files.append(_run_abi_diff(ctx, arch, prev_version, dump_file, abi_reference_file, True))
255*7594170eSAndroid Build Coastguard Worker
256*7594170eSAndroid Build Coastguard Worker    abi_reference_file = _find_abi_ref_file(ctx, version, arch, bitness, abi_class, dump_file.basename)
257*7594170eSAndroid Build Coastguard Worker    if abi_reference_file:
258*7594170eSAndroid Build Coastguard Worker        diff_files.append(_run_abi_diff(ctx, arch, version, dump_file, abi_reference_file, False))
259*7594170eSAndroid Build Coastguard Worker
260*7594170eSAndroid Build Coastguard Worker    return diff_files
261*7594170eSAndroid Build Coastguard Worker
262*7594170eSAndroid Build Coastguard Workerdef _run_abi_diff(ctx, arch, version, dump_file, abi_reference_file, prev_version_diff):
263*7594170eSAndroid Build Coastguard Worker    lib_name = ctx.attr.soname.removesuffix(".so")
264*7594170eSAndroid Build Coastguard Worker
265*7594170eSAndroid Build Coastguard Worker    args = ctx.actions.args()
266*7594170eSAndroid Build Coastguard Worker
267*7594170eSAndroid Build Coastguard Worker    if ctx.attr.check_all_apis:
268*7594170eSAndroid Build Coastguard Worker        args.add("-check-all-apis")
269*7594170eSAndroid Build Coastguard Worker    else:
270*7594170eSAndroid Build Coastguard Worker        args.add_all(["-allow-unreferenced-changes", "-allow-unreferenced-elf-symbol-changes"])
271*7594170eSAndroid Build Coastguard Worker
272*7594170eSAndroid Build Coastguard Worker    if prev_version_diff:
273*7594170eSAndroid Build Coastguard Worker        args.add("-target-version", version + 1)
274*7594170eSAndroid Build Coastguard Worker        diff_file_name = ctx.attr.soname + "." + str(version) + ".abidiff"
275*7594170eSAndroid Build Coastguard Worker    else:
276*7594170eSAndroid Build Coastguard Worker        args.add("-target-version", "current")
277*7594170eSAndroid Build Coastguard Worker        diff_file_name = ctx.attr.soname + ".abidiff"
278*7594170eSAndroid Build Coastguard Worker
279*7594170eSAndroid Build Coastguard Worker    args.add("-allow-extensions")
280*7594170eSAndroid Build Coastguard Worker
281*7594170eSAndroid Build Coastguard Worker    if len(ctx.attr.diff_flags) > 0:
282*7594170eSAndroid Build Coastguard Worker        args.add_all(ctx.attr.diff_flags)
283*7594170eSAndroid Build Coastguard Worker
284*7594170eSAndroid Build Coastguard Worker    args.add("-lib", lib_name)
285*7594170eSAndroid Build Coastguard Worker    args.add("-arch", arch)
286*7594170eSAndroid Build Coastguard Worker
287*7594170eSAndroid Build Coastguard Worker    diff_file = ctx.actions.declare_file(diff_file_name)
288*7594170eSAndroid Build Coastguard Worker    args.add("-o", diff_file)
289*7594170eSAndroid Build Coastguard Worker    args.add("-new", dump_file)
290*7594170eSAndroid Build Coastguard Worker    args.add("-old", abi_reference_file)
291*7594170eSAndroid Build Coastguard Worker
292*7594170eSAndroid Build Coastguard Worker    ctx.actions.run(
293*7594170eSAndroid Build Coastguard Worker        inputs = [dump_file, abi_reference_file],
294*7594170eSAndroid Build Coastguard Worker        executable = ctx.executable._abi_diff,
295*7594170eSAndroid Build Coastguard Worker        outputs = [diff_file],
296*7594170eSAndroid Build Coastguard Worker        arguments = [args],
297*7594170eSAndroid Build Coastguard Worker        execution_requirements = {
298*7594170eSAndroid Build Coastguard Worker            "no-sandbox": "1",
299*7594170eSAndroid Build Coastguard Worker        },
300*7594170eSAndroid Build Coastguard Worker        mnemonic = "AbiDiff",
301*7594170eSAndroid Build Coastguard Worker    )
302*7594170eSAndroid Build Coastguard Worker
303*7594170eSAndroid Build Coastguard Worker    return diff_file
304*7594170eSAndroid Build Coastguard Worker
305*7594170eSAndroid Build Coastguard Workerdef _find_abi_ref_file(ctx, version, arch, bitness, abi_class, lsdump_name):
306*7594170eSAndroid Build Coastguard Worker    # Currently we only support platform.
307*7594170eSAndroid Build Coastguard Worker    if abi_class == _ABI_CLASS_PLATFORM:
308*7594170eSAndroid Build Coastguard Worker        abi_ref_dumps = ctx.attr.abi_ref_dumps_platform
309*7594170eSAndroid Build Coastguard Worker    else:
310*7594170eSAndroid Build Coastguard Worker        fail("Unsupported ABI class: %s" % abi_class)
311*7594170eSAndroid Build Coastguard Worker
312*7594170eSAndroid Build Coastguard Worker    # The expected reference abi dump file
313*7594170eSAndroid Build Coastguard Worker    ref_dump_file = paths.join(
314*7594170eSAndroid Build Coastguard Worker        ctx.attr.ref_dumps_home,
315*7594170eSAndroid Build Coastguard Worker        abi_class,
316*7594170eSAndroid Build Coastguard Worker        str(version),
317*7594170eSAndroid Build Coastguard Worker        str(bitness),
318*7594170eSAndroid Build Coastguard Worker        arch,
319*7594170eSAndroid Build Coastguard Worker        "source-based",
320*7594170eSAndroid Build Coastguard Worker        lsdump_name,
321*7594170eSAndroid Build Coastguard Worker    )
322*7594170eSAndroid Build Coastguard Worker
323*7594170eSAndroid Build Coastguard Worker    ref_file = None
324*7594170eSAndroid Build Coastguard Worker
325*7594170eSAndroid Build Coastguard Worker    for file in abi_ref_dumps.files.to_list():
326*7594170eSAndroid Build Coastguard Worker        if ref_dump_file == file.path:
327*7594170eSAndroid Build Coastguard Worker            ref_file = file
328*7594170eSAndroid Build Coastguard Worker            break
329*7594170eSAndroid Build Coastguard Worker
330*7594170eSAndroid Build Coastguard Worker    return ref_file
331*7594170eSAndroid Build Coastguard Worker
332*7594170eSAndroid Build Coastguard Workerdef _abi_diff_enabled(ctx, lib_name, is_aspect):
333*7594170eSAndroid Build Coastguard Worker    # The logic here is based on:
334*7594170eSAndroid Build Coastguard Worker    # https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/sabi.go;l=103;drc=cb0ac95bde896fa2aa59193a37ceb580758c322c
335*7594170eSAndroid Build Coastguard Worker
336*7594170eSAndroid Build Coastguard Worker    if ctx.attr._skip_abi_checks[BuildSettingInfo].value:
337*7594170eSAndroid Build Coastguard Worker        return False
338*7594170eSAndroid Build Coastguard Worker    if not platforms.is_target_android(ctx.attr._platform_utils):
339*7594170eSAndroid Build Coastguard Worker        return False
340*7594170eSAndroid Build Coastguard Worker    if ctx.coverage_instrumented():
341*7594170eSAndroid Build Coastguard Worker        return False
342*7594170eSAndroid Build Coastguard Worker    if ctx.attr._within_apex[BuildSettingInfo].value:
343*7594170eSAndroid Build Coastguard Worker        if not is_aspect and not ctx.attr.has_stubs:
344*7594170eSAndroid Build Coastguard Worker            return False
345*7594170eSAndroid Build Coastguard Worker
346*7594170eSAndroid Build Coastguard Worker        # Logic comes from here:
347*7594170eSAndroid Build Coastguard Worker        # https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/sabi.go;l=158;drc=cb0ac95bde896fa2aa59193a37ceb580758c322c
348*7594170eSAndroid Build Coastguard Worker
349*7594170eSAndroid Build Coastguard Worker    elif is_bionic_lib(lib_name) or is_bootstrap_lib(lib_name):
350*7594170eSAndroid Build Coastguard Worker        return False
351*7594170eSAndroid Build Coastguard Worker
352*7594170eSAndroid Build Coastguard Worker    # TODO(b/260611960): handle all the other checks in sabi.go
353*7594170eSAndroid Build Coastguard Worker    return True
354*7594170eSAndroid Build Coastguard Worker
355*7594170eSAndroid Build Coastguard Workerdef _abi_dump_impl(ctx):
356*7594170eSAndroid Build Coastguard Worker    diff_files = depset()
357*7594170eSAndroid Build Coastguard Worker    if _abi_diff_enabled(ctx, ctx.attr.soname.removesuffix(".so"), False) and ctx.attr.root != None:
358*7594170eSAndroid Build Coastguard Worker        dump_files = ctx.attr.root[AbiDumpInfo].dump_files.to_list()
359*7594170eSAndroid Build Coastguard Worker        linked_dump_file = create_linked_abi_dump(ctx, dump_files)
360*7594170eSAndroid Build Coastguard Worker        diff_files = depset(create_abi_diff(ctx, linked_dump_file))
361*7594170eSAndroid Build Coastguard Worker
362*7594170eSAndroid Build Coastguard Worker    return ([
363*7594170eSAndroid Build Coastguard Worker        DefaultInfo(files = diff_files),
364*7594170eSAndroid Build Coastguard Worker        AbiDiffInfo(diff_files = diff_files),
365*7594170eSAndroid Build Coastguard Worker    ])
366*7594170eSAndroid Build Coastguard Worker
367*7594170eSAndroid Build Coastguard Workerabi_dump = rule(
368*7594170eSAndroid Build Coastguard Worker    implementation = _abi_dump_impl,
369*7594170eSAndroid Build Coastguard Worker    attrs = {
370*7594170eSAndroid Build Coastguard Worker        "shared": attr.label(mandatory = True, providers = [CcSharedLibraryInfo]),
371*7594170eSAndroid Build Coastguard Worker        "root": attr.label(providers = [CcInfo], aspects = [abi_dump_aspect]),
372*7594170eSAndroid Build Coastguard Worker        "soname": attr.string(mandatory = True),
373*7594170eSAndroid Build Coastguard Worker        "has_stubs": attr.bool(default = False),
374*7594170eSAndroid Build Coastguard Worker        "enabled": attr.bool(default = False),
375*7594170eSAndroid Build Coastguard Worker        "explicitly_disabled": attr.bool(default = False),
376*7594170eSAndroid Build Coastguard Worker        "symbol_file": attr.label(allow_single_file = True),
377*7594170eSAndroid Build Coastguard Worker        "exclude_symbol_versions": attr.string_list(default = []),
378*7594170eSAndroid Build Coastguard Worker        "exclude_symbol_tags": attr.string_list(default = []),
379*7594170eSAndroid Build Coastguard Worker        "check_all_apis": attr.bool(default = False),
380*7594170eSAndroid Build Coastguard Worker        "diff_flags": attr.string_list(default = []),
381*7594170eSAndroid Build Coastguard Worker        "abi_ref_dumps_platform": attr.label(default = "//prebuilts/abi-dumps/platform:bp2build_all_srcs"),
382*7594170eSAndroid Build Coastguard Worker        "ref_dumps_home": attr.string(default = "prebuilts/abi-dumps"),
383*7594170eSAndroid Build Coastguard Worker        "_skip_abi_checks": attr.label(
384*7594170eSAndroid Build Coastguard Worker            default = "//build/bazel/flags/cc/abi:skip_abi_checks",
385*7594170eSAndroid Build Coastguard Worker        ),
386*7594170eSAndroid Build Coastguard Worker        "_within_apex": attr.label(
387*7594170eSAndroid Build Coastguard Worker            default = "//build/bazel/rules/apex:within_apex",
388*7594170eSAndroid Build Coastguard Worker        ),
389*7594170eSAndroid Build Coastguard Worker        # TODO(b/254625084): For the following tools we need to support darwin as well.
390*7594170eSAndroid Build Coastguard Worker        "_abi_dumper": attr.label(
391*7594170eSAndroid Build Coastguard Worker            allow_files = True,
392*7594170eSAndroid Build Coastguard Worker            executable = True,
393*7594170eSAndroid Build Coastguard Worker            cfg = "exec",
394*7594170eSAndroid Build Coastguard Worker            default = Label("//prebuilts/clang-tools:linux-x86/bin/header-abi-dumper"),
395*7594170eSAndroid Build Coastguard Worker        ),
396*7594170eSAndroid Build Coastguard Worker        "_abi_linker": attr.label(
397*7594170eSAndroid Build Coastguard Worker            allow_files = True,
398*7594170eSAndroid Build Coastguard Worker            executable = True,
399*7594170eSAndroid Build Coastguard Worker            cfg = "exec",
400*7594170eSAndroid Build Coastguard Worker            default = Label("//prebuilts/clang-tools:linux-x86/bin/header-abi-linker"),
401*7594170eSAndroid Build Coastguard Worker        ),
402*7594170eSAndroid Build Coastguard Worker        "_abi_diff": attr.label(
403*7594170eSAndroid Build Coastguard Worker            allow_files = True,
404*7594170eSAndroid Build Coastguard Worker            executable = True,
405*7594170eSAndroid Build Coastguard Worker            cfg = "exec",
406*7594170eSAndroid Build Coastguard Worker            default = Label("//prebuilts/clang-tools:linux-x86/bin/header-abi-diff"),
407*7594170eSAndroid Build Coastguard Worker        ),
408*7594170eSAndroid Build Coastguard Worker        "_platform_utils": attr.label(default = Label("//build/bazel/platforms:platform_utils")),
409*7594170eSAndroid Build Coastguard Worker    },
410*7594170eSAndroid Build Coastguard Worker    fragments = ["cpp"],
411*7594170eSAndroid Build Coastguard Worker    toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
412*7594170eSAndroid Build Coastguard Worker)
413