• 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
15"""A macro to handle shared library stripping."""
16
17load(":cc_library_common.bzl", "CcAndroidMkInfo")
18load(":clang_tidy.bzl", "collect_deps_clang_tidy_info")
19load(
20    ":lto_transitions.bzl",
21    "drop_lto_transition",
22    "lto_deps_transition",
23)
24
25CcUnstrippedInfo = provider(
26    "Provides unstripped binary/shared library",
27    fields = {
28        "unstripped": "unstripped target",
29    },
30)
31
32# Keep this consistent with soong/cc/strip.go#NeedsStrip.
33def _needs_strip(ctx):
34    if ctx.attr.none:
35        return False
36    if ctx.target_platform_has_constraint(ctx.attr._android_constraint[platform_common.ConstraintValueInfo]):
37        return True
38    return (ctx.attr.all or ctx.attr.keep_symbols or
39            ctx.attr.keep_symbols_and_debug_frame or ctx.attr.keep_symbols_list)
40
41# Keep this consistent with soong/cc/strip.go#strip and soong/cc/builder.go#transformStrip.
42def _get_strip_args(attrs):
43    strip_args = []
44    keep_mini_debug_info = False
45    if attrs.keep_symbols:
46        strip_args.append("--keep-symbols")
47    elif attrs.keep_symbols_and_debug_frame:
48        strip_args.append("--keep-symbols-and-debug-frame")
49    elif attrs.keep_symbols_list:
50        strip_args.append("-k" + ",".join(attrs.keep_symbols_list))
51    elif not attrs.all:
52        strip_args.append("--keep-mini-debug-info")
53        keep_mini_debug_info = True
54
55    if not keep_mini_debug_info:
56        strip_args.append("--add-gnu-debuglink")
57
58    return strip_args
59
60# https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/builder.go;l=131-146;drc=master
61def stripped_impl(ctx, prefix = "", suffix = "", extension = ""):
62    out_file = ctx.actions.declare_file(prefix + ctx.attr.name + suffix + extension)
63    if not _needs_strip(ctx):
64        ctx.actions.symlink(
65            output = out_file,
66            target_file = ctx.files.src[0],
67        )
68        return out_file
69    d_file = ctx.actions.declare_file(ctx.attr.name + ".d")
70    ctx.actions.run(
71        env = {
72            "CREATE_MINIDEBUGINFO": ctx.executable._create_minidebuginfo.path,
73            "XZ": ctx.executable._xz.path,
74            "CLANG_BIN": ctx.executable._ar.dirname,
75        },
76        inputs = ctx.files.src,
77        tools = [
78            ctx.executable._ar,
79            ctx.executable._create_minidebuginfo,
80            ctx.executable._objcopy,
81            ctx.executable._readelf,
82            ctx.executable._strip,
83            ctx.executable._strip_script,
84            ctx.executable._xz,
85        ],
86        outputs = [out_file, d_file],
87        executable = ctx.executable._strip_script,
88        arguments = _get_strip_args(ctx.attr) + [
89            "-i",
90            ctx.files.src[0].path,
91            "-o",
92            out_file.path,
93            "-d",
94            d_file.path,
95        ],
96        mnemonic = "CcStrip",
97    )
98    return out_file
99
100strip_attrs = dict(
101    keep_symbols = attr.bool(default = False),
102    keep_symbols_and_debug_frame = attr.bool(default = False),
103    all = attr.bool(default = False),
104    none = attr.bool(default = False),
105    keep_symbols_list = attr.string_list(default = []),
106)
107common_strip_attrs = dict(
108    strip_attrs,
109    _xz = attr.label(
110        cfg = "exec",
111        executable = True,
112        allow_single_file = True,
113        default = "//prebuilts/build-tools:linux-x86/bin/xz",
114    ),
115    _create_minidebuginfo = attr.label(
116        cfg = "exec",
117        executable = True,
118        allow_single_file = True,
119        default = "//prebuilts/build-tools:linux-x86/bin/create_minidebuginfo",
120    ),
121    _strip_script = attr.label(
122        cfg = "exec",
123        executable = True,
124        allow_single_file = True,
125        default = "//build/soong/scripts:strip.sh",
126    ),
127    _ar = attr.label(
128        cfg = "exec",
129        executable = True,
130        allow_single_file = True,
131        default = "//prebuilts/clang/host/linux-x86:llvm-ar",
132    ),
133    _strip = attr.label(
134        cfg = "exec",
135        executable = True,
136        allow_single_file = True,
137        default = "//prebuilts/clang/host/linux-x86:llvm-strip",
138    ),
139    _readelf = attr.label(
140        cfg = "exec",
141        executable = True,
142        allow_single_file = True,
143        default = "//prebuilts/clang/host/linux-x86:llvm-readelf",
144    ),
145    _objcopy = attr.label(
146        cfg = "exec",
147        executable = True,
148        allow_single_file = True,
149        default = "//prebuilts/clang/host/linux-x86:llvm-objcopy",
150    ),
151    _cc_toolchain = attr.label(
152        default = Label("@local_config_cc//:toolchain"),
153        providers = [cc_common.CcToolchainInfo],
154    ),
155    _android_constraint = attr.label(
156        default = Label("//build/bazel/platforms/os:android"),
157    ),
158)
159
160def _stripped_shared_library_impl(ctx):
161    out_file = stripped_impl(ctx, prefix = "lib", extension = ".so")
162
163    return [
164        DefaultInfo(files = depset([out_file])),
165        ctx.attr.src[CcSharedLibraryInfo],
166        ctx.attr.src[OutputGroupInfo],
167    ]
168
169stripped_shared_library = rule(
170    implementation = _stripped_shared_library_impl,
171    attrs = dict(
172        common_strip_attrs,
173        src = attr.label(
174            mandatory = True,
175            # TODO(b/217908237): reenable allow_single_file
176            # allow_single_file = True,
177            providers = [CcSharedLibraryInfo],
178        ),
179    ),
180    toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
181)
182
183# A marker provider to distinguish a cc_binary from everything else that exports
184# a CcInfo.
185StrippedCcBinaryInfo = provider()
186
187def _stripped_binary_impl(ctx):
188    common_providers = [
189        ctx.attr.src[0][CcInfo],
190        ctx.attr.src[0][InstrumentedFilesInfo],
191        ctx.attr.src[0][DebugPackageInfo],
192        ctx.attr.src[0][OutputGroupInfo],
193        StrippedCcBinaryInfo(),  # a marker for dependents
194        CcUnstrippedInfo(
195            unstripped = ctx.attr.unstripped,
196        ),
197        collect_deps_clang_tidy_info(ctx),
198    ] + [
199        d[CcAndroidMkInfo]
200        for d in ctx.attr.androidmk_deps
201    ]
202
203    out_file = stripped_impl(ctx, suffix = ctx.attr.suffix)
204
205    return [
206        DefaultInfo(
207            files = depset([out_file]),
208            executable = out_file,
209        ),
210    ] + common_providers
211
212_rule_attrs = dict(
213    common_strip_attrs,
214    src = attr.label(
215        mandatory = True,
216        allow_single_file = True,
217        providers = [CcInfo],
218        cfg = lto_deps_transition,
219    ),
220    runtime_deps = attr.label_list(
221        providers = [CcInfo],
222        doc = "Deps that should be installed along with this target. Read by the apex cc aspect.",
223    ),
224    androidmk_deps = attr.label_list(
225        providers = [CcAndroidMkInfo],
226    ),
227    suffix = attr.string(),
228    unstripped = attr.label(
229        mandatory = True,
230        allow_single_file = True,
231        cfg = lto_deps_transition,
232        doc = "Unstripped binary to be returned by ",
233    ),
234    _allowlist_function_transition = attr.label(
235        default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
236    ),
237)
238
239stripped_binary = rule(
240    implementation = _stripped_binary_impl,
241    cfg = drop_lto_transition,
242    attrs = _rule_attrs,
243    executable = True,
244    toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
245)
246
247stripped_test = rule(
248    implementation = _stripped_binary_impl,
249    cfg = drop_lto_transition,
250    attrs = _rule_attrs,
251    test = True,
252    toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
253)
254