xref: /aosp_15_r20/build/bazel/rules/cc/stripped_cc_common.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
1*7594170eSAndroid Build Coastguard Worker# Copyright (C) 2021 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 Worker"""A macro to handle shared library stripping."""
16*7594170eSAndroid Build Coastguard Worker
17*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:paths.bzl", "paths")
18*7594170eSAndroid Build Coastguard Workerload(":cc_library_common.bzl", "CcAndroidMkInfo", "check_valid_ldlibs")
19*7594170eSAndroid Build Coastguard Workerload(":clang_tidy.bzl", "collect_deps_clang_tidy_info")
20*7594170eSAndroid Build Coastguard Workerload(
21*7594170eSAndroid Build Coastguard Worker    ":composed_transitions.bzl",
22*7594170eSAndroid Build Coastguard Worker    "drop_lto_and_sanitizer_transition",
23*7594170eSAndroid Build Coastguard Worker    "lto_and_sanitizer_deps_transition",
24*7594170eSAndroid Build Coastguard Worker)
25*7594170eSAndroid Build Coastguard Worker
26*7594170eSAndroid Build Coastguard WorkerCcUnstrippedInfo = provider(
27*7594170eSAndroid Build Coastguard Worker    "Provides unstripped binary/shared library",
28*7594170eSAndroid Build Coastguard Worker    fields = {
29*7594170eSAndroid Build Coastguard Worker        "unstripped": "unstripped target",
30*7594170eSAndroid Build Coastguard Worker    },
31*7594170eSAndroid Build Coastguard Worker)
32*7594170eSAndroid Build Coastguard Worker
33*7594170eSAndroid Build Coastguard Worker# Keep this consistent with soong/cc/strip.go#NeedsStrip.
34*7594170eSAndroid Build Coastguard Workerdef _needs_strip(ctx):
35*7594170eSAndroid Build Coastguard Worker    if ctx.attr.none:
36*7594170eSAndroid Build Coastguard Worker        return False
37*7594170eSAndroid Build Coastguard Worker    if ctx.target_platform_has_constraint(ctx.attr._android_constraint[platform_common.ConstraintValueInfo]):
38*7594170eSAndroid Build Coastguard Worker        return True
39*7594170eSAndroid Build Coastguard Worker    return (ctx.attr.all or ctx.attr.keep_symbols or
40*7594170eSAndroid Build Coastguard Worker            ctx.attr.keep_symbols_and_debug_frame or ctx.attr.keep_symbols_list)
41*7594170eSAndroid Build Coastguard Worker
42*7594170eSAndroid Build Coastguard Worker# Keep this consistent with soong/cc/strip.go#strip and soong/cc/builder.go#transformStrip.
43*7594170eSAndroid Build Coastguard Workerdef _get_strip_args(attrs):
44*7594170eSAndroid Build Coastguard Worker    strip_args = []
45*7594170eSAndroid Build Coastguard Worker    keep_mini_debug_info = False
46*7594170eSAndroid Build Coastguard Worker    if attrs.keep_symbols:
47*7594170eSAndroid Build Coastguard Worker        strip_args.append("--keep-symbols")
48*7594170eSAndroid Build Coastguard Worker    elif attrs.keep_symbols_and_debug_frame:
49*7594170eSAndroid Build Coastguard Worker        strip_args.append("--keep-symbols-and-debug-frame")
50*7594170eSAndroid Build Coastguard Worker    elif attrs.keep_symbols_list:
51*7594170eSAndroid Build Coastguard Worker        strip_args.append("-k" + ",".join(attrs.keep_symbols_list))
52*7594170eSAndroid Build Coastguard Worker    elif not attrs.all:
53*7594170eSAndroid Build Coastguard Worker        strip_args.append("--keep-mini-debug-info")
54*7594170eSAndroid Build Coastguard Worker        keep_mini_debug_info = True
55*7594170eSAndroid Build Coastguard Worker
56*7594170eSAndroid Build Coastguard Worker    if not keep_mini_debug_info:
57*7594170eSAndroid Build Coastguard Worker        strip_args.append("--add-gnu-debuglink")
58*7594170eSAndroid Build Coastguard Worker
59*7594170eSAndroid Build Coastguard Worker    return strip_args
60*7594170eSAndroid Build Coastguard Worker
61*7594170eSAndroid Build Coastguard Worker# https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/builder.go;l=131-146;drc=master
62*7594170eSAndroid Build Coastguard Workerdef stripped_impl(ctx, file, prefix = "", stem = "", suffix = "", extension = "", subdir = ""):
63*7594170eSAndroid Build Coastguard Worker    filename_stem = stem or ctx.attr.name
64*7594170eSAndroid Build Coastguard Worker    filename = prefix + filename_stem + suffix + extension
65*7594170eSAndroid Build Coastguard Worker    out_file = ctx.actions.declare_file(
66*7594170eSAndroid Build Coastguard Worker        paths.join(
67*7594170eSAndroid Build Coastguard Worker            subdir,  # Prevent name collision by generating in a directory unique to the target
68*7594170eSAndroid Build Coastguard Worker            filename,
69*7594170eSAndroid Build Coastguard Worker        ),
70*7594170eSAndroid Build Coastguard Worker    )
71*7594170eSAndroid Build Coastguard Worker    if not _needs_strip(ctx):
72*7594170eSAndroid Build Coastguard Worker        ctx.actions.symlink(
73*7594170eSAndroid Build Coastguard Worker            output = out_file,
74*7594170eSAndroid Build Coastguard Worker            target_file = file,
75*7594170eSAndroid Build Coastguard Worker        )
76*7594170eSAndroid Build Coastguard Worker        return out_file
77*7594170eSAndroid Build Coastguard Worker    d_file = ctx.actions.declare_file(
78*7594170eSAndroid Build Coastguard Worker        paths.join(
79*7594170eSAndroid Build Coastguard Worker            subdir,
80*7594170eSAndroid Build Coastguard Worker            filename + ".d",
81*7594170eSAndroid Build Coastguard Worker        ),
82*7594170eSAndroid Build Coastguard Worker    )
83*7594170eSAndroid Build Coastguard Worker
84*7594170eSAndroid Build Coastguard Worker    ctx.actions.run(
85*7594170eSAndroid Build Coastguard Worker        env = {
86*7594170eSAndroid Build Coastguard Worker            "CREATE_MINIDEBUGINFO": ctx.executable._create_minidebuginfo.path,
87*7594170eSAndroid Build Coastguard Worker            "XZ": ctx.executable._xz.path,
88*7594170eSAndroid Build Coastguard Worker            "CLANG_BIN": ctx.executable._ar.dirname,
89*7594170eSAndroid Build Coastguard Worker        },
90*7594170eSAndroid Build Coastguard Worker        inputs = [file],
91*7594170eSAndroid Build Coastguard Worker        tools = [
92*7594170eSAndroid Build Coastguard Worker            ctx.executable._ar,
93*7594170eSAndroid Build Coastguard Worker            ctx.executable._create_minidebuginfo,
94*7594170eSAndroid Build Coastguard Worker            ctx.executable._objcopy,
95*7594170eSAndroid Build Coastguard Worker            ctx.executable._readelf,
96*7594170eSAndroid Build Coastguard Worker            ctx.executable._strip,
97*7594170eSAndroid Build Coastguard Worker            ctx.executable._strip_script,
98*7594170eSAndroid Build Coastguard Worker            ctx.executable._xz,
99*7594170eSAndroid Build Coastguard Worker        ],
100*7594170eSAndroid Build Coastguard Worker        outputs = [out_file, d_file],
101*7594170eSAndroid Build Coastguard Worker        executable = ctx.executable._strip_script,
102*7594170eSAndroid Build Coastguard Worker        arguments = _get_strip_args(ctx.attr) + [
103*7594170eSAndroid Build Coastguard Worker            "-i",
104*7594170eSAndroid Build Coastguard Worker            file.path,
105*7594170eSAndroid Build Coastguard Worker            "-o",
106*7594170eSAndroid Build Coastguard Worker            out_file.path,
107*7594170eSAndroid Build Coastguard Worker            "-d",
108*7594170eSAndroid Build Coastguard Worker            d_file.path,
109*7594170eSAndroid Build Coastguard Worker        ],
110*7594170eSAndroid Build Coastguard Worker        mnemonic = "CcStrip",
111*7594170eSAndroid Build Coastguard Worker    )
112*7594170eSAndroid Build Coastguard Worker    return out_file
113*7594170eSAndroid Build Coastguard Worker
114*7594170eSAndroid Build Coastguard Workerstrip_attrs = dict(
115*7594170eSAndroid Build Coastguard Worker    keep_symbols = attr.bool(default = False),
116*7594170eSAndroid Build Coastguard Worker    keep_symbols_and_debug_frame = attr.bool(default = False),
117*7594170eSAndroid Build Coastguard Worker    all = attr.bool(default = False),
118*7594170eSAndroid Build Coastguard Worker    none = attr.bool(default = False),
119*7594170eSAndroid Build Coastguard Worker    keep_symbols_list = attr.string_list(default = []),
120*7594170eSAndroid Build Coastguard Worker)
121*7594170eSAndroid Build Coastguard Workercommon_strip_attrs = dict(
122*7594170eSAndroid Build Coastguard Worker    strip_attrs,
123*7594170eSAndroid Build Coastguard Worker    _xz = attr.label(
124*7594170eSAndroid Build Coastguard Worker        cfg = "exec",
125*7594170eSAndroid Build Coastguard Worker        executable = True,
126*7594170eSAndroid Build Coastguard Worker        allow_single_file = True,
127*7594170eSAndroid Build Coastguard Worker        default = "//prebuilts/build-tools:linux-x86/bin/xz",
128*7594170eSAndroid Build Coastguard Worker    ),
129*7594170eSAndroid Build Coastguard Worker    _create_minidebuginfo = attr.label(
130*7594170eSAndroid Build Coastguard Worker        cfg = "exec",
131*7594170eSAndroid Build Coastguard Worker        executable = True,
132*7594170eSAndroid Build Coastguard Worker        allow_single_file = True,
133*7594170eSAndroid Build Coastguard Worker        default = "//prebuilts/build-tools:linux-x86/bin/create_minidebuginfo",
134*7594170eSAndroid Build Coastguard Worker    ),
135*7594170eSAndroid Build Coastguard Worker    _strip_script = attr.label(
136*7594170eSAndroid Build Coastguard Worker        cfg = "exec",
137*7594170eSAndroid Build Coastguard Worker        executable = True,
138*7594170eSAndroid Build Coastguard Worker        allow_single_file = True,
139*7594170eSAndroid Build Coastguard Worker        default = "//build/soong/scripts:strip.sh",
140*7594170eSAndroid Build Coastguard Worker    ),
141*7594170eSAndroid Build Coastguard Worker    _ar = attr.label(
142*7594170eSAndroid Build Coastguard Worker        cfg = "exec",
143*7594170eSAndroid Build Coastguard Worker        executable = True,
144*7594170eSAndroid Build Coastguard Worker        allow_single_file = True,
145*7594170eSAndroid Build Coastguard Worker        default = "//prebuilts/clang/host/linux-x86:llvm-ar",
146*7594170eSAndroid Build Coastguard Worker    ),
147*7594170eSAndroid Build Coastguard Worker    _strip = attr.label(
148*7594170eSAndroid Build Coastguard Worker        cfg = "exec",
149*7594170eSAndroid Build Coastguard Worker        executable = True,
150*7594170eSAndroid Build Coastguard Worker        allow_single_file = True,
151*7594170eSAndroid Build Coastguard Worker        default = "//prebuilts/clang/host/linux-x86:llvm-strip",
152*7594170eSAndroid Build Coastguard Worker    ),
153*7594170eSAndroid Build Coastguard Worker    _readelf = attr.label(
154*7594170eSAndroid Build Coastguard Worker        cfg = "exec",
155*7594170eSAndroid Build Coastguard Worker        executable = True,
156*7594170eSAndroid Build Coastguard Worker        allow_single_file = True,
157*7594170eSAndroid Build Coastguard Worker        default = "//prebuilts/clang/host/linux-x86:llvm-readelf",
158*7594170eSAndroid Build Coastguard Worker    ),
159*7594170eSAndroid Build Coastguard Worker    _objcopy = attr.label(
160*7594170eSAndroid Build Coastguard Worker        cfg = "exec",
161*7594170eSAndroid Build Coastguard Worker        executable = True,
162*7594170eSAndroid Build Coastguard Worker        allow_single_file = True,
163*7594170eSAndroid Build Coastguard Worker        default = "//prebuilts/clang/host/linux-x86:llvm-objcopy",
164*7594170eSAndroid Build Coastguard Worker    ),
165*7594170eSAndroid Build Coastguard Worker    _cc_toolchain = attr.label(
166*7594170eSAndroid Build Coastguard Worker        default = Label("@local_config_cc//:toolchain"),
167*7594170eSAndroid Build Coastguard Worker        providers = [cc_common.CcToolchainInfo],
168*7594170eSAndroid Build Coastguard Worker    ),
169*7594170eSAndroid Build Coastguard Worker    _android_constraint = attr.label(
170*7594170eSAndroid Build Coastguard Worker        default = Label("//build/bazel_common_rules/platforms/os:android"),
171*7594170eSAndroid Build Coastguard Worker    ),
172*7594170eSAndroid Build Coastguard Worker    _darwin_constraint = attr.label(
173*7594170eSAndroid Build Coastguard Worker        default = Label("//build/bazel_common_rules/platforms/os:darwin"),
174*7594170eSAndroid Build Coastguard Worker    ),
175*7594170eSAndroid Build Coastguard Worker    _linux_constraint = attr.label(
176*7594170eSAndroid Build Coastguard Worker        default = Label("//build/bazel_common_rules/platforms/os:linux"),
177*7594170eSAndroid Build Coastguard Worker    ),
178*7594170eSAndroid Build Coastguard Worker    _windows_constraint = attr.label(
179*7594170eSAndroid Build Coastguard Worker        default = Label("//build/bazel_common_rules/platforms/os:windows"),
180*7594170eSAndroid Build Coastguard Worker    ),
181*7594170eSAndroid Build Coastguard Worker)
182*7594170eSAndroid Build Coastguard Worker
183*7594170eSAndroid Build Coastguard Workerdef _stripped_shared_library_impl(ctx):
184*7594170eSAndroid Build Coastguard Worker    check_valid_ldlibs(ctx, ctx.attr.linkopts)
185*7594170eSAndroid Build Coastguard Worker
186*7594170eSAndroid Build Coastguard Worker    out_file = stripped_impl(ctx, ctx.file.src, prefix = "lib", extension = ".so", subdir = ctx.attr.name)
187*7594170eSAndroid Build Coastguard Worker
188*7594170eSAndroid Build Coastguard Worker    return [
189*7594170eSAndroid Build Coastguard Worker        DefaultInfo(files = depset([out_file])),
190*7594170eSAndroid Build Coastguard Worker        ctx.attr.src[CcSharedLibraryInfo],
191*7594170eSAndroid Build Coastguard Worker        ctx.attr.src[OutputGroupInfo],
192*7594170eSAndroid Build Coastguard Worker    ]
193*7594170eSAndroid Build Coastguard Worker
194*7594170eSAndroid Build Coastguard Workerstripped_shared_library = rule(
195*7594170eSAndroid Build Coastguard Worker    implementation = _stripped_shared_library_impl,
196*7594170eSAndroid Build Coastguard Worker    attrs = dict(
197*7594170eSAndroid Build Coastguard Worker        common_strip_attrs,
198*7594170eSAndroid Build Coastguard Worker        src = attr.label(
199*7594170eSAndroid Build Coastguard Worker            mandatory = True,
200*7594170eSAndroid Build Coastguard Worker            providers = [CcSharedLibraryInfo],
201*7594170eSAndroid Build Coastguard Worker            allow_single_file = True,
202*7594170eSAndroid Build Coastguard Worker        ),
203*7594170eSAndroid Build Coastguard Worker        linkopts = attr.string_list(default = []),  # Used for validation
204*7594170eSAndroid Build Coastguard Worker    ),
205*7594170eSAndroid Build Coastguard Worker    toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
206*7594170eSAndroid Build Coastguard Worker)
207*7594170eSAndroid Build Coastguard Worker
208*7594170eSAndroid Build Coastguard Worker# A marker provider to distinguish a cc_binary from everything else that exports
209*7594170eSAndroid Build Coastguard Worker# a CcInfo.
210*7594170eSAndroid Build Coastguard WorkerStrippedCcBinaryInfo = provider()
211*7594170eSAndroid Build Coastguard Worker
212*7594170eSAndroid Build Coastguard Workerdef _stripped_binary_impl(ctx):
213*7594170eSAndroid Build Coastguard Worker    check_valid_ldlibs(ctx, ctx.attr.linkopts)
214*7594170eSAndroid Build Coastguard Worker
215*7594170eSAndroid Build Coastguard Worker    common_providers = [
216*7594170eSAndroid Build Coastguard Worker        ctx.attr.src[0][CcInfo],
217*7594170eSAndroid Build Coastguard Worker        ctx.attr.src[0][InstrumentedFilesInfo],
218*7594170eSAndroid Build Coastguard Worker        ctx.attr.src[0][DebugPackageInfo],
219*7594170eSAndroid Build Coastguard Worker        ctx.attr.src[0][OutputGroupInfo],
220*7594170eSAndroid Build Coastguard Worker        StrippedCcBinaryInfo(),  # a marker for dependents
221*7594170eSAndroid Build Coastguard Worker        CcUnstrippedInfo(
222*7594170eSAndroid Build Coastguard Worker            unstripped = ctx.attr.unstripped,
223*7594170eSAndroid Build Coastguard Worker        ),
224*7594170eSAndroid Build Coastguard Worker        collect_deps_clang_tidy_info(ctx),
225*7594170eSAndroid Build Coastguard Worker    ] + [
226*7594170eSAndroid Build Coastguard Worker        d[CcAndroidMkInfo]
227*7594170eSAndroid Build Coastguard Worker        for d in ctx.attr.androidmk_deps
228*7594170eSAndroid Build Coastguard Worker    ]
229*7594170eSAndroid Build Coastguard Worker
230*7594170eSAndroid Build Coastguard Worker    # Generate binary in a directory unique to this target to prevent possible collisions due to common `stem`
231*7594170eSAndroid Build Coastguard Worker    # Generate in `bin` to prevent incrementality issues for mixed builds where <package>/<name> could be a file and not a dir
232*7594170eSAndroid Build Coastguard Worker    subdir = paths.join("bin", ctx.attr.name)
233*7594170eSAndroid Build Coastguard Worker    out_file = stripped_impl(ctx, ctx.file.src, stem = ctx.attr.stem, suffix = ctx.attr.suffix, subdir = subdir)
234*7594170eSAndroid Build Coastguard Worker
235*7594170eSAndroid Build Coastguard Worker    return [
236*7594170eSAndroid Build Coastguard Worker        DefaultInfo(
237*7594170eSAndroid Build Coastguard Worker            files = depset([out_file]),
238*7594170eSAndroid Build Coastguard Worker            executable = out_file,
239*7594170eSAndroid Build Coastguard Worker            runfiles = ctx.attr.src[0][DefaultInfo].default_runfiles,
240*7594170eSAndroid Build Coastguard Worker        ),
241*7594170eSAndroid Build Coastguard Worker    ] + common_providers
242*7594170eSAndroid Build Coastguard Worker
243*7594170eSAndroid Build Coastguard Worker_rule_attrs = dict(
244*7594170eSAndroid Build Coastguard Worker    common_strip_attrs,
245*7594170eSAndroid Build Coastguard Worker    src = attr.label(
246*7594170eSAndroid Build Coastguard Worker        mandatory = True,
247*7594170eSAndroid Build Coastguard Worker        allow_single_file = True,
248*7594170eSAndroid Build Coastguard Worker        providers = [CcInfo],
249*7594170eSAndroid Build Coastguard Worker        cfg = lto_and_sanitizer_deps_transition,
250*7594170eSAndroid Build Coastguard Worker    ),
251*7594170eSAndroid Build Coastguard Worker    linkopts = attr.string_list(default = []),  # Used for validation
252*7594170eSAndroid Build Coastguard Worker    runtime_deps = attr.label_list(
253*7594170eSAndroid Build Coastguard Worker        providers = [CcInfo],
254*7594170eSAndroid Build Coastguard Worker        doc = "Deps that should be installed along with this target. Read by the apex cc aspect.",
255*7594170eSAndroid Build Coastguard Worker    ),
256*7594170eSAndroid Build Coastguard Worker    androidmk_deps = attr.label_list(
257*7594170eSAndroid Build Coastguard Worker        providers = [CcAndroidMkInfo],
258*7594170eSAndroid Build Coastguard Worker        cfg = lto_and_sanitizer_deps_transition,
259*7594170eSAndroid Build Coastguard Worker    ),
260*7594170eSAndroid Build Coastguard Worker    stem = attr.string(),
261*7594170eSAndroid Build Coastguard Worker    suffix = attr.string(),
262*7594170eSAndroid Build Coastguard Worker    unstripped = attr.label(
263*7594170eSAndroid Build Coastguard Worker        mandatory = True,
264*7594170eSAndroid Build Coastguard Worker        allow_single_file = True,
265*7594170eSAndroid Build Coastguard Worker        cfg = lto_and_sanitizer_deps_transition,
266*7594170eSAndroid Build Coastguard Worker        doc = "Unstripped binary to be returned by ",
267*7594170eSAndroid Build Coastguard Worker    ),
268*7594170eSAndroid Build Coastguard Worker    package_name = attr.string(
269*7594170eSAndroid Build Coastguard Worker        mandatory = True,
270*7594170eSAndroid Build Coastguard Worker        doc = "Just the path to the target package. Used by transitions.",
271*7594170eSAndroid Build Coastguard Worker    ),
272*7594170eSAndroid Build Coastguard Worker    _allowlist_function_transition = attr.label(
273*7594170eSAndroid Build Coastguard Worker        default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
274*7594170eSAndroid Build Coastguard Worker    ),
275*7594170eSAndroid Build Coastguard Worker)
276*7594170eSAndroid Build Coastguard Worker
277*7594170eSAndroid Build Coastguard Workerstripped_binary = rule(
278*7594170eSAndroid Build Coastguard Worker    implementation = _stripped_binary_impl,
279*7594170eSAndroid Build Coastguard Worker    cfg = drop_lto_and_sanitizer_transition,
280*7594170eSAndroid Build Coastguard Worker    attrs = _rule_attrs,
281*7594170eSAndroid Build Coastguard Worker    executable = True,
282*7594170eSAndroid Build Coastguard Worker    toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
283*7594170eSAndroid Build Coastguard Worker)
284*7594170eSAndroid Build Coastguard Worker
285*7594170eSAndroid Build Coastguard Workerstripped_test = rule(
286*7594170eSAndroid Build Coastguard Worker    implementation = _stripped_binary_impl,
287*7594170eSAndroid Build Coastguard Worker    cfg = drop_lto_and_sanitizer_transition,
288*7594170eSAndroid Build Coastguard Worker    attrs = _rule_attrs,
289*7594170eSAndroid Build Coastguard Worker    test = True,
290*7594170eSAndroid Build Coastguard Worker    toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
291*7594170eSAndroid Build Coastguard Worker)
292