xref: /aosp_15_r20/external/bazelbuild-rules_android/rules/proguard.bzl (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1*9e965d6fSRomain Jobredeaux# Copyright 2020 The Bazel Authors. All rights reserved.
2*9e965d6fSRomain Jobredeaux#
3*9e965d6fSRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License");
4*9e965d6fSRomain Jobredeaux# you may not use this file except in compliance with the License.
5*9e965d6fSRomain Jobredeaux# You may obtain a copy of the License at
6*9e965d6fSRomain Jobredeaux#
7*9e965d6fSRomain Jobredeaux#    http://www.apache.org/licenses/LICENSE-2.0
8*9e965d6fSRomain Jobredeaux#
9*9e965d6fSRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software
10*9e965d6fSRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS,
11*9e965d6fSRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9e965d6fSRomain Jobredeaux# See the License for the specific language governing permissions and
13*9e965d6fSRomain Jobredeaux# limitations under the License.
14*9e965d6fSRomain Jobredeaux
15*9e965d6fSRomain Jobredeaux"""Bazel Android Proguard library for the Android rules."""
16*9e965d6fSRomain Jobredeaux
17*9e965d6fSRomain Jobredeauxload(":android_neverlink_aspect.bzl", "StarlarkAndroidNeverlinkInfo")
18*9e965d6fSRomain Jobredeauxload(":baseline_profiles.bzl", _baseline_profiles = "baseline_profiles")
19*9e965d6fSRomain Jobredeauxload(":common.bzl", "common")
20*9e965d6fSRomain Jobredeauxload(":java.bzl", "java")
21*9e965d6fSRomain Jobredeauxload(":utils.bzl", "ANDROID_TOOLCHAIN_TYPE", "get_android_sdk", "utils")
22*9e965d6fSRomain Jobredeaux
23*9e965d6fSRomain Jobredeaux_ProguardSpecContextInfo = provider(
24*9e965d6fSRomain Jobredeaux    doc = "Contains data from processing Proguard specs.",
25*9e965d6fSRomain Jobredeaux    fields = dict(
26*9e965d6fSRomain Jobredeaux        proguard_configs = "The direct proguard configs",
27*9e965d6fSRomain Jobredeaux        transitive_proguard_configs =
28*9e965d6fSRomain Jobredeaux            "The proguard configs within the transitive closure of the target",
29*9e965d6fSRomain Jobredeaux        providers = "The list of all providers to propagate.",
30*9e965d6fSRomain Jobredeaux    ),
31*9e965d6fSRomain Jobredeaux)
32*9e965d6fSRomain Jobredeaux
33*9e965d6fSRomain Jobredeauxdef _validate_proguard_spec(
34*9e965d6fSRomain Jobredeaux        ctx,
35*9e965d6fSRomain Jobredeaux        out_validated_proguard_spec,
36*9e965d6fSRomain Jobredeaux        proguard_spec,
37*9e965d6fSRomain Jobredeaux        proguard_allowlister):
38*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
39*9e965d6fSRomain Jobredeaux    args.add("--path", proguard_spec)
40*9e965d6fSRomain Jobredeaux    args.add("--output", out_validated_proguard_spec)
41*9e965d6fSRomain Jobredeaux
42*9e965d6fSRomain Jobredeaux    ctx.actions.run(
43*9e965d6fSRomain Jobredeaux        executable = proguard_allowlister,
44*9e965d6fSRomain Jobredeaux        arguments = [args],
45*9e965d6fSRomain Jobredeaux        inputs = [proguard_spec],
46*9e965d6fSRomain Jobredeaux        outputs = [out_validated_proguard_spec],
47*9e965d6fSRomain Jobredeaux        mnemonic = "ValidateProguard",
48*9e965d6fSRomain Jobredeaux        progress_message = (
49*9e965d6fSRomain Jobredeaux            "Validating proguard configuration %s" % proguard_spec.short_path
50*9e965d6fSRomain Jobredeaux        ),
51*9e965d6fSRomain Jobredeaux        toolchain = ANDROID_TOOLCHAIN_TYPE,
52*9e965d6fSRomain Jobredeaux    )
53*9e965d6fSRomain Jobredeaux
54*9e965d6fSRomain Jobredeauxdef _process_specs(
55*9e965d6fSRomain Jobredeaux        ctx,
56*9e965d6fSRomain Jobredeaux        proguard_configs = [],
57*9e965d6fSRomain Jobredeaux        proguard_spec_providers = [],
58*9e965d6fSRomain Jobredeaux        proguard_allowlister = None):
59*9e965d6fSRomain Jobredeaux    """Processes Proguard Specs
60*9e965d6fSRomain Jobredeaux
61*9e965d6fSRomain Jobredeaux    Args:
62*9e965d6fSRomain Jobredeaux      ctx: The context.
63*9e965d6fSRomain Jobredeaux      proguard_configs: sequence of Files. A list of proguard config files to be
64*9e965d6fSRomain Jobredeaux        processed. Optional.
65*9e965d6fSRomain Jobredeaux      proguard_spec_providers: sequence of ProguardSpecProvider providers. A
66*9e965d6fSRomain Jobredeaux        list of providers from the dependencies, exports, plugins,
67*9e965d6fSRomain Jobredeaux        exported_plugins, etc. Optional.
68*9e965d6fSRomain Jobredeaux      proguard_allowlister: The proguard_allowlister exeutable provider.
69*9e965d6fSRomain Jobredeaux
70*9e965d6fSRomain Jobredeaux    Returns:
71*9e965d6fSRomain Jobredeaux      A _ProguardSpecContextInfo provider.
72*9e965d6fSRomain Jobredeaux    """
73*9e965d6fSRomain Jobredeaux
74*9e965d6fSRomain Jobredeaux    # TODO(djwhang): Look to see if this can be just a validation action and the
75*9e965d6fSRomain Jobredeaux    # proguard_spec provided by the rule can be propagated.
76*9e965d6fSRomain Jobredeaux    validated_proguard_configs = []
77*9e965d6fSRomain Jobredeaux    for proguard_spec in proguard_configs:
78*9e965d6fSRomain Jobredeaux        validated_proguard_spec = ctx.actions.declare_file(
79*9e965d6fSRomain Jobredeaux            "validated_proguard/%s/%s_valid" %
80*9e965d6fSRomain Jobredeaux            (ctx.label.name, proguard_spec.path),
81*9e965d6fSRomain Jobredeaux        )
82*9e965d6fSRomain Jobredeaux        _validate_proguard_spec(
83*9e965d6fSRomain Jobredeaux            ctx,
84*9e965d6fSRomain Jobredeaux            validated_proguard_spec,
85*9e965d6fSRomain Jobredeaux            proguard_spec,
86*9e965d6fSRomain Jobredeaux            proguard_allowlister,
87*9e965d6fSRomain Jobredeaux        )
88*9e965d6fSRomain Jobredeaux        validated_proguard_configs.append(validated_proguard_spec)
89*9e965d6fSRomain Jobredeaux
90*9e965d6fSRomain Jobredeaux    transitive_validated_proguard_configs = []
91*9e965d6fSRomain Jobredeaux    for info in proguard_spec_providers:
92*9e965d6fSRomain Jobredeaux        transitive_validated_proguard_configs.append(info.specs)
93*9e965d6fSRomain Jobredeaux
94*9e965d6fSRomain Jobredeaux    transitive_proguard_configs = depset(
95*9e965d6fSRomain Jobredeaux        validated_proguard_configs,
96*9e965d6fSRomain Jobredeaux        transitive = transitive_validated_proguard_configs,
97*9e965d6fSRomain Jobredeaux        order = "preorder",
98*9e965d6fSRomain Jobredeaux    )
99*9e965d6fSRomain Jobredeaux    return _ProguardSpecContextInfo(
100*9e965d6fSRomain Jobredeaux        proguard_configs = proguard_configs,
101*9e965d6fSRomain Jobredeaux        transitive_proguard_configs = transitive_proguard_configs,
102*9e965d6fSRomain Jobredeaux        providers = [
103*9e965d6fSRomain Jobredeaux            ProguardSpecProvider(transitive_proguard_configs),
104*9e965d6fSRomain Jobredeaux            # TODO(b/152659272): Remove this once the android_archive rule is
105*9e965d6fSRomain Jobredeaux            # able to process a transitive closure of deps to produce an aar.
106*9e965d6fSRomain Jobredeaux            AndroidProguardInfo(proguard_configs),
107*9e965d6fSRomain Jobredeaux        ],
108*9e965d6fSRomain Jobredeaux    )
109*9e965d6fSRomain Jobredeaux
110*9e965d6fSRomain Jobredeauxdef _collect_transitive_proguard_specs(
111*9e965d6fSRomain Jobredeaux        specs_to_include,
112*9e965d6fSRomain Jobredeaux        local_proguard_specs,
113*9e965d6fSRomain Jobredeaux        proguard_deps):
114*9e965d6fSRomain Jobredeaux    if len(local_proguard_specs) == 0:
115*9e965d6fSRomain Jobredeaux        return []
116*9e965d6fSRomain Jobredeaux
117*9e965d6fSRomain Jobredeaux    proguard_specs = depset(
118*9e965d6fSRomain Jobredeaux        local_proguard_specs + specs_to_include,
119*9e965d6fSRomain Jobredeaux        transitive = [dep.specs for dep in proguard_deps],
120*9e965d6fSRomain Jobredeaux    )
121*9e965d6fSRomain Jobredeaux    return sorted(proguard_specs.to_list())
122*9e965d6fSRomain Jobredeaux
123*9e965d6fSRomain Jobredeauxdef _get_proguard_specs(
124*9e965d6fSRomain Jobredeaux        ctx,
125*9e965d6fSRomain Jobredeaux        resource_proguard_config,
126*9e965d6fSRomain Jobredeaux        proguard_specs_for_manifest = []):
127*9e965d6fSRomain Jobredeaux    proguard_deps = utils.collect_providers(ProguardSpecProvider, utils.dedupe_split_attr(ctx.split_attr.deps))
128*9e965d6fSRomain Jobredeaux    if ctx.configuration.coverage_enabled and hasattr(ctx.attr, "_jacoco_runtime"):
129*9e965d6fSRomain Jobredeaux        proguard_deps.append(ctx.attr._jacoco_runtime[ProguardSpecProvider])
130*9e965d6fSRomain Jobredeaux
131*9e965d6fSRomain Jobredeaux    local_proguard_specs = []
132*9e965d6fSRomain Jobredeaux    if ctx.files.proguard_specs:
133*9e965d6fSRomain Jobredeaux        local_proguard_specs = ctx.files.proguard_specs
134*9e965d6fSRomain Jobredeaux    proguard_specs = _collect_transitive_proguard_specs(
135*9e965d6fSRomain Jobredeaux        [resource_proguard_config],
136*9e965d6fSRomain Jobredeaux        local_proguard_specs,
137*9e965d6fSRomain Jobredeaux        proguard_deps,
138*9e965d6fSRomain Jobredeaux    )
139*9e965d6fSRomain Jobredeaux
140*9e965d6fSRomain Jobredeaux    if len(proguard_specs) > 0 and ctx.fragments.android.assume_min_sdk_version:
141*9e965d6fSRomain Jobredeaux        # NB: Order here is important. We're including generated Proguard specs before the user's
142*9e965d6fSRomain Jobredeaux        # specs so that they can override values.
143*9e965d6fSRomain Jobredeaux        proguard_specs = proguard_specs_for_manifest + proguard_specs
144*9e965d6fSRomain Jobredeaux
145*9e965d6fSRomain Jobredeaux    return proguard_specs
146*9e965d6fSRomain Jobredeaux
147*9e965d6fSRomain Jobredeauxdef _generate_min_sdk_version_assumevalues(
148*9e965d6fSRomain Jobredeaux        ctx,
149*9e965d6fSRomain Jobredeaux        output = None,
150*9e965d6fSRomain Jobredeaux        manifest = None,
151*9e965d6fSRomain Jobredeaux        generate_exec = None):
152*9e965d6fSRomain Jobredeaux    """Reads the minSdkVersion from an AndroidManifest to generate Proguard specs."""
153*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
154*9e965d6fSRomain Jobredeaux    inputs = []
155*9e965d6fSRomain Jobredeaux    outputs = []
156*9e965d6fSRomain Jobredeaux
157*9e965d6fSRomain Jobredeaux    args.add("--manifest", manifest)
158*9e965d6fSRomain Jobredeaux    inputs.append(manifest)
159*9e965d6fSRomain Jobredeaux
160*9e965d6fSRomain Jobredeaux    args.add("--output", output)
161*9e965d6fSRomain Jobredeaux    outputs.append(output)
162*9e965d6fSRomain Jobredeaux
163*9e965d6fSRomain Jobredeaux    ctx.actions.run(
164*9e965d6fSRomain Jobredeaux        inputs = inputs,
165*9e965d6fSRomain Jobredeaux        outputs = outputs,
166*9e965d6fSRomain Jobredeaux        executable = generate_exec,
167*9e965d6fSRomain Jobredeaux        arguments = [args],
168*9e965d6fSRomain Jobredeaux        mnemonic = "MinSdkVersionAssumeValuesProguardSpecGenerator",
169*9e965d6fSRomain Jobredeaux        progress_message = "Adding -assumevalues spec for minSdkVersion",
170*9e965d6fSRomain Jobredeaux    )
171*9e965d6fSRomain Jobredeaux
172*9e965d6fSRomain Jobredeauxdef _optimization_action(
173*9e965d6fSRomain Jobredeaux        ctx,
174*9e965d6fSRomain Jobredeaux        output_jar,
175*9e965d6fSRomain Jobredeaux        program_jar,
176*9e965d6fSRomain Jobredeaux        library_jar,
177*9e965d6fSRomain Jobredeaux        proguard_specs,
178*9e965d6fSRomain Jobredeaux        proguard_mapping = None,
179*9e965d6fSRomain Jobredeaux        proguard_output_map = None,
180*9e965d6fSRomain Jobredeaux        proguard_seeds = None,
181*9e965d6fSRomain Jobredeaux        proguard_usage = None,
182*9e965d6fSRomain Jobredeaux        proguard_config_output = None,
183*9e965d6fSRomain Jobredeaux        startup_profile = None,
184*9e965d6fSRomain Jobredeaux        startup_profile_rewritten = None,
185*9e965d6fSRomain Jobredeaux        baseline_profile = None,
186*9e965d6fSRomain Jobredeaux        baseline_profile_rewritten = None,
187*9e965d6fSRomain Jobredeaux        runtype = None,
188*9e965d6fSRomain Jobredeaux        last_stage_output = None,
189*9e965d6fSRomain Jobredeaux        next_stage_output = None,
190*9e965d6fSRomain Jobredeaux        final = False,
191*9e965d6fSRomain Jobredeaux        mnemonic = None,
192*9e965d6fSRomain Jobredeaux        progress_message = None,
193*9e965d6fSRomain Jobredeaux        proguard_tool = None):
194*9e965d6fSRomain Jobredeaux    """Creates a Proguard optimization action.
195*9e965d6fSRomain Jobredeaux
196*9e965d6fSRomain Jobredeaux    This method is expected to be called one or more times to create Proguard optimization actions.
197*9e965d6fSRomain Jobredeaux    Most outputs will only be generated by the final optimization action, and should otherwise be
198*9e965d6fSRomain Jobredeaux    set to None. For the final action set `final = True` which will register the output_jar as an
199*9e965d6fSRomain Jobredeaux    output of the action.
200*9e965d6fSRomain Jobredeaux
201*9e965d6fSRomain Jobredeaux    TODO(b/286955442): Support baseline profiles.
202*9e965d6fSRomain Jobredeaux
203*9e965d6fSRomain Jobredeaux    Args:
204*9e965d6fSRomain Jobredeaux      ctx: The context.
205*9e965d6fSRomain Jobredeaux      output_jar: File. The final output jar.
206*9e965d6fSRomain Jobredeaux      program_jar: File. The jar to be optimized.
207*9e965d6fSRomain Jobredeaux      library_jar: File. The merged library jar. While the underlying tooling supports multiple
208*9e965d6fSRomain Jobredeaux        library jars, we merge these into a single jar before processing.
209*9e965d6fSRomain Jobredeaux      proguard_specs: Sequence of files. A list of proguard specs to use for the optimization.
210*9e965d6fSRomain Jobredeaux      proguard_mapping: File. Optional file to be used as a mapping for proguard. A mapping file
211*9e965d6fSRomain Jobredeaux        generated by proguard_generate_mapping to be re-used to apply the same map to a new build.
212*9e965d6fSRomain Jobredeaux      proguard_output_map: File. Optional file to be used to write the output map of obfuscated
213*9e965d6fSRomain Jobredeaux        class and member names.
214*9e965d6fSRomain Jobredeaux      proguard_seeds: File. Optional file used to write the "seeds", which is a list of all
215*9e965d6fSRomain Jobredeaux        classes and members which match a keep rule.
216*9e965d6fSRomain Jobredeaux      proguard_usage: File. Optional file used to write all classes and members that are removed
217*9e965d6fSRomain Jobredeaux        during shrinking (i.e. unused code).
218*9e965d6fSRomain Jobredeaux      proguard_config_output: File. Optional file used to write the entire configuration that has
219*9e965d6fSRomain Jobredeaux        been parsed, included files and replaced variables. Useful for debugging.
220*9e965d6fSRomain Jobredeaux      startup_profile: File. Optional. The merged startup profile to be optimized.
221*9e965d6fSRomain Jobredeaux      startup_profile_rewritten: File. Optional file used to write the optimized startup profile.
222*9e965d6fSRomain Jobredeaux      baseline_profile: File. Optional. The merged baseline profile to be optimized.
223*9e965d6fSRomain Jobredeaux      baseline_profile_rewritten: File. Optional file used to write the optimized profile rules.
224*9e965d6fSRomain Jobredeaux      runtype: String. Optional string identifying this run. One of [INITIAL, OPTIMIZATION, FINAL]
225*9e965d6fSRomain Jobredeaux      last_stage_output: File. Optional input file to this optimization stage, which was output by
226*9e965d6fSRomain Jobredeaux        the previous optimization stage.
227*9e965d6fSRomain Jobredeaux      next_stage_output: File. Optional output file from this optimization stage, which will be
228*9e965d6fSRomain Jobredeaux        consunmed by the next optimization stage.
229*9e965d6fSRomain Jobredeaux      final: Boolean. Whether this is the final optimization stage, which will register output_jar
230*9e965d6fSRomain Jobredeaux        as an output of this action.
231*9e965d6fSRomain Jobredeaux      mnemonic: String. Action mnemonic.
232*9e965d6fSRomain Jobredeaux      progress_message: String. Action progress message.
233*9e965d6fSRomain Jobredeaux      proguard_tool: FilesToRunProvider. The proguard tool to execute.
234*9e965d6fSRomain Jobredeaux
235*9e965d6fSRomain Jobredeaux    Returns:
236*9e965d6fSRomain Jobredeaux      None
237*9e965d6fSRomain Jobredeaux    """
238*9e965d6fSRomain Jobredeaux
239*9e965d6fSRomain Jobredeaux    inputs = []
240*9e965d6fSRomain Jobredeaux    outputs = []
241*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
242*9e965d6fSRomain Jobredeaux
243*9e965d6fSRomain Jobredeaux    args.add("-forceprocessing")
244*9e965d6fSRomain Jobredeaux
245*9e965d6fSRomain Jobredeaux    args.add("-injars", program_jar)
246*9e965d6fSRomain Jobredeaux    inputs.append(program_jar)
247*9e965d6fSRomain Jobredeaux
248*9e965d6fSRomain Jobredeaux    args.add("-outjars", output_jar)
249*9e965d6fSRomain Jobredeaux    if final:
250*9e965d6fSRomain Jobredeaux        outputs.append(output_jar)
251*9e965d6fSRomain Jobredeaux
252*9e965d6fSRomain Jobredeaux    args.add("-libraryjars", library_jar)
253*9e965d6fSRomain Jobredeaux    inputs.append(library_jar)
254*9e965d6fSRomain Jobredeaux
255*9e965d6fSRomain Jobredeaux    if proguard_mapping:
256*9e965d6fSRomain Jobredeaux        args.add("-applymapping", proguard_mapping)
257*9e965d6fSRomain Jobredeaux        inputs.append(proguard_mapping)
258*9e965d6fSRomain Jobredeaux
259*9e965d6fSRomain Jobredeaux    args.add_all(proguard_specs, format_each = "@%s")
260*9e965d6fSRomain Jobredeaux    inputs.extend(proguard_specs)
261*9e965d6fSRomain Jobredeaux
262*9e965d6fSRomain Jobredeaux    if proguard_output_map:
263*9e965d6fSRomain Jobredeaux        args.add("-printmapping", proguard_output_map)
264*9e965d6fSRomain Jobredeaux        outputs.append(proguard_output_map)
265*9e965d6fSRomain Jobredeaux
266*9e965d6fSRomain Jobredeaux    if proguard_seeds:
267*9e965d6fSRomain Jobredeaux        args.add("-printseeds", proguard_seeds)
268*9e965d6fSRomain Jobredeaux        outputs.append(proguard_seeds)
269*9e965d6fSRomain Jobredeaux
270*9e965d6fSRomain Jobredeaux    if proguard_usage:
271*9e965d6fSRomain Jobredeaux        args.add("-printusage", proguard_usage)
272*9e965d6fSRomain Jobredeaux        outputs.append(proguard_usage)
273*9e965d6fSRomain Jobredeaux
274*9e965d6fSRomain Jobredeaux    if proguard_config_output:
275*9e965d6fSRomain Jobredeaux        args.add("-printconfiguration", proguard_config_output)
276*9e965d6fSRomain Jobredeaux        outputs.append(proguard_config_output)
277*9e965d6fSRomain Jobredeaux
278*9e965d6fSRomain Jobredeaux    if startup_profile:
279*9e965d6fSRomain Jobredeaux        args.add("-startupprofile", startup_profile)
280*9e965d6fSRomain Jobredeaux        inputs.append(startup_profile)
281*9e965d6fSRomain Jobredeaux
282*9e965d6fSRomain Jobredeaux    if startup_profile_rewritten:
283*9e965d6fSRomain Jobredeaux        args.add("-printstartupprofile", startup_profile)
284*9e965d6fSRomain Jobredeaux        outputs.append(startup_profile_rewritten)
285*9e965d6fSRomain Jobredeaux
286*9e965d6fSRomain Jobredeaux    if baseline_profile:
287*9e965d6fSRomain Jobredeaux        args.add("-baselineprofile", baseline_profile)
288*9e965d6fSRomain Jobredeaux        inputs.append(baseline_profile)
289*9e965d6fSRomain Jobredeaux
290*9e965d6fSRomain Jobredeaux    if baseline_profile_rewritten:
291*9e965d6fSRomain Jobredeaux        args.add("-printbaselineprofile", baseline_profile_rewritten)
292*9e965d6fSRomain Jobredeaux        outputs.append(baseline_profile_rewritten)
293*9e965d6fSRomain Jobredeaux
294*9e965d6fSRomain Jobredeaux    if runtype:
295*9e965d6fSRomain Jobredeaux        args.add("-runtype " + runtype)
296*9e965d6fSRomain Jobredeaux
297*9e965d6fSRomain Jobredeaux    if last_stage_output:
298*9e965d6fSRomain Jobredeaux        args.add("-laststageoutput", last_stage_output)
299*9e965d6fSRomain Jobredeaux        inputs.append(last_stage_output)
300*9e965d6fSRomain Jobredeaux
301*9e965d6fSRomain Jobredeaux    if next_stage_output:
302*9e965d6fSRomain Jobredeaux        args.add("-nextstageoutput", next_stage_output)
303*9e965d6fSRomain Jobredeaux        outputs.append(next_stage_output)
304*9e965d6fSRomain Jobredeaux
305*9e965d6fSRomain Jobredeaux    ctx.actions.run(
306*9e965d6fSRomain Jobredeaux        outputs = outputs,
307*9e965d6fSRomain Jobredeaux        inputs = inputs,
308*9e965d6fSRomain Jobredeaux        executable = proguard_tool,
309*9e965d6fSRomain Jobredeaux        arguments = [args],
310*9e965d6fSRomain Jobredeaux        mnemonic = mnemonic,
311*9e965d6fSRomain Jobredeaux        progress_message = progress_message,
312*9e965d6fSRomain Jobredeaux        toolchain = None,  # TODO(timpeut): correctly set this based off which optimizer is selected
313*9e965d6fSRomain Jobredeaux    )
314*9e965d6fSRomain Jobredeaux
315*9e965d6fSRomain Jobredeauxdef _get_proguard_temp_artifact_with_prefix(ctx, label, prefix, name):
316*9e965d6fSRomain Jobredeaux    native_label_name = label.name.removesuffix(common.PACKAGED_RESOURCES_SUFFIX)
317*9e965d6fSRomain Jobredeaux    return ctx.actions.declare_file("proguard/" + native_label_name + "/" + prefix + "_" + native_label_name + "_" + name)
318*9e965d6fSRomain Jobredeaux
319*9e965d6fSRomain Jobredeauxdef _get_proguard_temp_artifact(ctx, name):
320*9e965d6fSRomain Jobredeaux    return _get_proguard_temp_artifact_with_prefix(ctx, ctx.label, "MIGRATED", name)
321*9e965d6fSRomain Jobredeaux
322*9e965d6fSRomain Jobredeauxdef _get_proguard_output_map(ctx):
323*9e965d6fSRomain Jobredeaux    return ctx.actions.declare_file(ctx.label.name.removesuffix(common.PACKAGED_RESOURCES_SUFFIX) + "_proguard_MIGRATED_.map")
324*9e965d6fSRomain Jobredeaux
325*9e965d6fSRomain Jobredeauxdef _apply_proguard(
326*9e965d6fSRomain Jobredeaux        ctx,
327*9e965d6fSRomain Jobredeaux        input_jar = None,
328*9e965d6fSRomain Jobredeaux        proguard_specs = [],
329*9e965d6fSRomain Jobredeaux        proguard_optimization_passes = None,
330*9e965d6fSRomain Jobredeaux        proguard_mapping = None,
331*9e965d6fSRomain Jobredeaux        proguard_output_jar = None,
332*9e965d6fSRomain Jobredeaux        proguard_output_map = None,
333*9e965d6fSRomain Jobredeaux        proguard_seeds = None,
334*9e965d6fSRomain Jobredeaux        proguard_usage = None,
335*9e965d6fSRomain Jobredeaux        startup_profile = None,
336*9e965d6fSRomain Jobredeaux        baseline_profile = None,
337*9e965d6fSRomain Jobredeaux        proguard_tool = None):
338*9e965d6fSRomain Jobredeaux    """Top-level method to apply proguard to a jar.
339*9e965d6fSRomain Jobredeaux
340*9e965d6fSRomain Jobredeaux    Args:
341*9e965d6fSRomain Jobredeaux      ctx: The context
342*9e965d6fSRomain Jobredeaux      input_jar: File. The input jar to optimized.
343*9e965d6fSRomain Jobredeaux      proguard_specs: List of Files. The proguard specs to use for optimization.
344*9e965d6fSRomain Jobredeaux      proguard_optimization_passes: Integer. The number of proguard passes to apply.
345*9e965d6fSRomain Jobredeaux      proguard_mapping: File. The proguard mapping to apply.
346*9e965d6fSRomain Jobredeaux      proguard_output_jar: File. The output optimized jar.
347*9e965d6fSRomain Jobredeaux      proguard_output_map: File. The output proguard map.
348*9e965d6fSRomain Jobredeaux      proguard_seeds: File. The output proguard seeds.
349*9e965d6fSRomain Jobredeaux      proguard_usage: File. The output proguard usage.
350*9e965d6fSRomain Jobredeaux      startup_profile: File. The input merged startup profile to be optimized.
351*9e965d6fSRomain Jobredeaux      baseline_profile: File. The input merged baseline profile to be optimized.
352*9e965d6fSRomain Jobredeaux      proguard_tool: FilesToRun. The proguard executable.
353*9e965d6fSRomain Jobredeaux
354*9e965d6fSRomain Jobredeaux    Returns:
355*9e965d6fSRomain Jobredeaux      A struct of proguard outputs.
356*9e965d6fSRomain Jobredeaux    """
357*9e965d6fSRomain Jobredeaux    if not proguard_specs:
358*9e965d6fSRomain Jobredeaux        outputs = _get_proguard_output(
359*9e965d6fSRomain Jobredeaux            ctx,
360*9e965d6fSRomain Jobredeaux            proguard_output_jar = proguard_output_jar,
361*9e965d6fSRomain Jobredeaux            proguard_seeds = None,
362*9e965d6fSRomain Jobredeaux            proguard_usage = None,
363*9e965d6fSRomain Jobredeaux            proguard_output_map = proguard_output_map,
364*9e965d6fSRomain Jobredeaux            combined_library_jar = None,
365*9e965d6fSRomain Jobredeaux            startup_profile_rewritten = None,
366*9e965d6fSRomain Jobredeaux            baseline_profile_rewritten = None,
367*9e965d6fSRomain Jobredeaux        )
368*9e965d6fSRomain Jobredeaux
369*9e965d6fSRomain Jobredeaux        # Fail at execution time if these artifacts are requested, to avoid issue where outputs are
370*9e965d6fSRomain Jobredeaux        # declared without having any proguard specs. This can happen if specs is a select() that
371*9e965d6fSRomain Jobredeaux        # resolves to an empty list.
372*9e965d6fSRomain Jobredeaux        _fail_action(
373*9e965d6fSRomain Jobredeaux            ctx,
374*9e965d6fSRomain Jobredeaux            outputs.output_jar,
375*9e965d6fSRomain Jobredeaux            outputs.mapping,
376*9e965d6fSRomain Jobredeaux            outputs.config,
377*9e965d6fSRomain Jobredeaux            proguard_seeds,
378*9e965d6fSRomain Jobredeaux            proguard_usage,
379*9e965d6fSRomain Jobredeaux        )
380*9e965d6fSRomain Jobredeaux        return outputs
381*9e965d6fSRomain Jobredeaux
382*9e965d6fSRomain Jobredeaux    library_jar_list = [get_android_sdk(ctx).android_jar]
383*9e965d6fSRomain Jobredeaux    if ctx.fragments.android.desugar_java8:
384*9e965d6fSRomain Jobredeaux        library_jar_list.append(ctx.file._desugared_java8_legacy_apis)
385*9e965d6fSRomain Jobredeaux    neverlink_infos = utils.collect_providers(StarlarkAndroidNeverlinkInfo, ctx.attr.deps)
386*9e965d6fSRomain Jobredeaux    library_jars = depset(library_jar_list, transitive = [info.transitive_neverlink_libraries for info in neverlink_infos])
387*9e965d6fSRomain Jobredeaux
388*9e965d6fSRomain Jobredeaux    return _create_optimization_actions(
389*9e965d6fSRomain Jobredeaux        ctx,
390*9e965d6fSRomain Jobredeaux        proguard_specs,
391*9e965d6fSRomain Jobredeaux        proguard_seeds,
392*9e965d6fSRomain Jobredeaux        proguard_usage,
393*9e965d6fSRomain Jobredeaux        proguard_mapping,
394*9e965d6fSRomain Jobredeaux        proguard_output_jar,
395*9e965d6fSRomain Jobredeaux        proguard_optimization_passes,
396*9e965d6fSRomain Jobredeaux        proguard_output_map,
397*9e965d6fSRomain Jobredeaux        input_jar,
398*9e965d6fSRomain Jobredeaux        library_jars,
399*9e965d6fSRomain Jobredeaux        startup_profile,
400*9e965d6fSRomain Jobredeaux        baseline_profile,
401*9e965d6fSRomain Jobredeaux        proguard_tool,
402*9e965d6fSRomain Jobredeaux    )
403*9e965d6fSRomain Jobredeaux
404*9e965d6fSRomain Jobredeauxdef _get_proguard_output(
405*9e965d6fSRomain Jobredeaux        ctx,
406*9e965d6fSRomain Jobredeaux        proguard_output_jar,
407*9e965d6fSRomain Jobredeaux        proguard_seeds,
408*9e965d6fSRomain Jobredeaux        proguard_usage,
409*9e965d6fSRomain Jobredeaux        proguard_output_map,
410*9e965d6fSRomain Jobredeaux        combined_library_jar,
411*9e965d6fSRomain Jobredeaux        startup_profile_rewritten,
412*9e965d6fSRomain Jobredeaux        baseline_profile_rewritten):
413*9e965d6fSRomain Jobredeaux    """Helper method to get a struct of all proguard outputs."""
414*9e965d6fSRomain Jobredeaux
415*9e965d6fSRomain Jobredeaux    # Proto Output Map is currently empty from ProGuard.
416*9e965d6fSRomain Jobredeaux    proguard_output_proto_map = None
417*9e965d6fSRomain Jobredeaux    if proguard_output_map:
418*9e965d6fSRomain Jobredeaux        proguard_output_proto_map = _get_proguard_temp_artifact(ctx, "_proguard.pbmap")
419*9e965d6fSRomain Jobredeaux        ctx.actions.write(proguard_output_proto_map, content = "")
420*9e965d6fSRomain Jobredeaux
421*9e965d6fSRomain Jobredeaux    config_output = _get_proguard_temp_artifact(ctx, "_proguard.config")
422*9e965d6fSRomain Jobredeaux
423*9e965d6fSRomain Jobredeaux    return struct(
424*9e965d6fSRomain Jobredeaux        output_jar = proguard_output_jar,
425*9e965d6fSRomain Jobredeaux        mapping = proguard_output_map,
426*9e965d6fSRomain Jobredeaux        proto_mapping = proguard_output_proto_map,
427*9e965d6fSRomain Jobredeaux        seeds = proguard_seeds,
428*9e965d6fSRomain Jobredeaux        usage = proguard_usage,
429*9e965d6fSRomain Jobredeaux        library_jar = combined_library_jar,
430*9e965d6fSRomain Jobredeaux        config = config_output,
431*9e965d6fSRomain Jobredeaux        startup_profile_rewritten = startup_profile_rewritten,
432*9e965d6fSRomain Jobredeaux        baseline_profile_rewritten = baseline_profile_rewritten,
433*9e965d6fSRomain Jobredeaux    )
434*9e965d6fSRomain Jobredeaux
435*9e965d6fSRomain Jobredeauxdef _create_optimization_actions(
436*9e965d6fSRomain Jobredeaux        ctx,
437*9e965d6fSRomain Jobredeaux        proguard_specs = None,
438*9e965d6fSRomain Jobredeaux        proguard_seeds = None,
439*9e965d6fSRomain Jobredeaux        proguard_usage = None,
440*9e965d6fSRomain Jobredeaux        proguard_mapping = None,
441*9e965d6fSRomain Jobredeaux        proguard_output_jar = None,
442*9e965d6fSRomain Jobredeaux        num_passes = None,
443*9e965d6fSRomain Jobredeaux        proguard_output_map = None,
444*9e965d6fSRomain Jobredeaux        input_jar = None,
445*9e965d6fSRomain Jobredeaux        library_jars = depset(),
446*9e965d6fSRomain Jobredeaux        startup_profile = None,
447*9e965d6fSRomain Jobredeaux        baseline_profile = None,
448*9e965d6fSRomain Jobredeaux        proguard_tool = None):
449*9e965d6fSRomain Jobredeaux    """Helper method to create all optimizaction actions based on the target configuration."""
450*9e965d6fSRomain Jobredeaux    if not proguard_specs:
451*9e965d6fSRomain Jobredeaux        fail("Missing proguard_specs in create_optimization_actions")
452*9e965d6fSRomain Jobredeaux
453*9e965d6fSRomain Jobredeaux    # Merge all library jars into a single jar
454*9e965d6fSRomain Jobredeaux    combined_library_jar = _get_proguard_temp_artifact(ctx, "_migrated_combined_library_jars.jar")
455*9e965d6fSRomain Jobredeaux    java.singlejar(
456*9e965d6fSRomain Jobredeaux        ctx,
457*9e965d6fSRomain Jobredeaux        library_jars,
458*9e965d6fSRomain Jobredeaux        combined_library_jar,
459*9e965d6fSRomain Jobredeaux        java_toolchain = common.get_java_toolchain(ctx),
460*9e965d6fSRomain Jobredeaux    )
461*9e965d6fSRomain Jobredeaux
462*9e965d6fSRomain Jobredeaux    # Filter library jar with program jar
463*9e965d6fSRomain Jobredeaux    filtered_library_jar = _get_proguard_temp_artifact(ctx, "_migrated_combined_library_jars_filtered.jar")
464*9e965d6fSRomain Jobredeaux    common.filter_zip_exclude(
465*9e965d6fSRomain Jobredeaux        ctx,
466*9e965d6fSRomain Jobredeaux        filtered_library_jar,
467*9e965d6fSRomain Jobredeaux        combined_library_jar,
468*9e965d6fSRomain Jobredeaux        filter_zips = [input_jar],
469*9e965d6fSRomain Jobredeaux    )
470*9e965d6fSRomain Jobredeaux
471*9e965d6fSRomain Jobredeaux    startup_profile_rewritten = None
472*9e965d6fSRomain Jobredeaux    baseline_profile_rewritten = None
473*9e965d6fSRomain Jobredeaux    if startup_profile:
474*9e965d6fSRomain Jobredeaux        startup_profile_rewritten = _baseline_profiles.get_profile_artifact(ctx, "rewritten-startup-prof.txt")
475*9e965d6fSRomain Jobredeaux    if baseline_profile and startup_profile:
476*9e965d6fSRomain Jobredeaux        baseline_profile_rewritten = _baseline_profiles.get_profile_artifact(ctx, "rewritten-merged-prof.txt")
477*9e965d6fSRomain Jobredeaux
478*9e965d6fSRomain Jobredeaux    outputs = _get_proguard_output(
479*9e965d6fSRomain Jobredeaux        ctx,
480*9e965d6fSRomain Jobredeaux        proguard_output_jar,
481*9e965d6fSRomain Jobredeaux        proguard_seeds,
482*9e965d6fSRomain Jobredeaux        proguard_usage,
483*9e965d6fSRomain Jobredeaux        proguard_output_map,
484*9e965d6fSRomain Jobredeaux        combined_library_jar,
485*9e965d6fSRomain Jobredeaux        startup_profile_rewritten,
486*9e965d6fSRomain Jobredeaux        baseline_profile_rewritten,
487*9e965d6fSRomain Jobredeaux    )
488*9e965d6fSRomain Jobredeaux
489*9e965d6fSRomain Jobredeaux    # TODO(timpeut): Validate that optimizer target selection is correct
490*9e965d6fSRomain Jobredeaux    mnemonic = ctx.fragments.java.bytecode_optimizer_mnemonic
491*9e965d6fSRomain Jobredeaux    optimizer_target = ctx.executable._bytecode_optimizer
492*9e965d6fSRomain Jobredeaux
493*9e965d6fSRomain Jobredeaux    # If num_passes is not specified run a single optimization action
494*9e965d6fSRomain Jobredeaux    if not num_passes:
495*9e965d6fSRomain Jobredeaux        _optimization_action(
496*9e965d6fSRomain Jobredeaux            ctx,
497*9e965d6fSRomain Jobredeaux            outputs.output_jar,
498*9e965d6fSRomain Jobredeaux            input_jar,
499*9e965d6fSRomain Jobredeaux            filtered_library_jar,
500*9e965d6fSRomain Jobredeaux            proguard_specs,
501*9e965d6fSRomain Jobredeaux            proguard_mapping = proguard_mapping,
502*9e965d6fSRomain Jobredeaux            proguard_output_map = outputs.mapping,
503*9e965d6fSRomain Jobredeaux            proguard_seeds = outputs.seeds,
504*9e965d6fSRomain Jobredeaux            proguard_usage = outputs.usage,
505*9e965d6fSRomain Jobredeaux            proguard_config_output = outputs.config,
506*9e965d6fSRomain Jobredeaux            startup_profile = startup_profile,
507*9e965d6fSRomain Jobredeaux            startup_profile_rewritten = outputs.startup_profile_rewritten,
508*9e965d6fSRomain Jobredeaux            baseline_profile = baseline_profile,
509*9e965d6fSRomain Jobredeaux            baseline_profile_rewritten = outputs.baseline_profile_rewritten,
510*9e965d6fSRomain Jobredeaux            final = True,
511*9e965d6fSRomain Jobredeaux            mnemonic = mnemonic,
512*9e965d6fSRomain Jobredeaux            progress_message = "Trimming binary with %s: %s" % (mnemonic, ctx.label),
513*9e965d6fSRomain Jobredeaux            proguard_tool = proguard_tool,
514*9e965d6fSRomain Jobredeaux        )
515*9e965d6fSRomain Jobredeaux        return outputs
516*9e965d6fSRomain Jobredeaux
517*9e965d6fSRomain Jobredeaux    # num_passes has been specified, create multiple proguard actions
518*9e965d6fSRomain Jobredeaux    split_bytecode_optimization_passes = ctx.fragments.java.split_bytecode_optimization_pass
519*9e965d6fSRomain Jobredeaux    bytecode_optimization_pass_actions = ctx.fragments.java.bytecode_optimization_pass_actions
520*9e965d6fSRomain Jobredeaux    last_stage_output = _get_proguard_temp_artifact(ctx, "_proguard_preoptimization.jar")
521*9e965d6fSRomain Jobredeaux    _optimization_action(
522*9e965d6fSRomain Jobredeaux        ctx,
523*9e965d6fSRomain Jobredeaux        outputs.output_jar,
524*9e965d6fSRomain Jobredeaux        input_jar,
525*9e965d6fSRomain Jobredeaux        filtered_library_jar,
526*9e965d6fSRomain Jobredeaux        proguard_specs,
527*9e965d6fSRomain Jobredeaux        proguard_mapping = proguard_mapping,
528*9e965d6fSRomain Jobredeaux        proguard_output_map = None,
529*9e965d6fSRomain Jobredeaux        proguard_seeds = outputs.seeds,
530*9e965d6fSRomain Jobredeaux        proguard_usage = None,
531*9e965d6fSRomain Jobredeaux        proguard_config_output = None,
532*9e965d6fSRomain Jobredeaux        startup_profile = startup_profile,
533*9e965d6fSRomain Jobredeaux        startup_profile_rewritten = None,
534*9e965d6fSRomain Jobredeaux        baseline_profile = baseline_profile,
535*9e965d6fSRomain Jobredeaux        baseline_profile_rewritten = None,
536*9e965d6fSRomain Jobredeaux        final = False,
537*9e965d6fSRomain Jobredeaux        runtype = "INITIAL",
538*9e965d6fSRomain Jobredeaux        next_stage_output = last_stage_output,
539*9e965d6fSRomain Jobredeaux        mnemonic = mnemonic,
540*9e965d6fSRomain Jobredeaux        progress_message = "Trimming binary with %s: Verification/Shrinking Pass" % mnemonic,
541*9e965d6fSRomain Jobredeaux        proguard_tool = proguard_tool,
542*9e965d6fSRomain Jobredeaux    )
543*9e965d6fSRomain Jobredeaux    for i in range(1, num_passes + 1):
544*9e965d6fSRomain Jobredeaux        if split_bytecode_optimization_passes and bytecode_optimization_pass_actions < 2:
545*9e965d6fSRomain Jobredeaux            last_stage_output = _create_single_optimization_action(
546*9e965d6fSRomain Jobredeaux                ctx,
547*9e965d6fSRomain Jobredeaux                outputs.output_jar,
548*9e965d6fSRomain Jobredeaux                input_jar,
549*9e965d6fSRomain Jobredeaux                filtered_library_jar,
550*9e965d6fSRomain Jobredeaux                proguard_specs,
551*9e965d6fSRomain Jobredeaux                proguard_mapping,
552*9e965d6fSRomain Jobredeaux                i,
553*9e965d6fSRomain Jobredeaux                "_INITIAL",
554*9e965d6fSRomain Jobredeaux                mnemonic,
555*9e965d6fSRomain Jobredeaux                last_stage_output,
556*9e965d6fSRomain Jobredeaux                optimizer_target,
557*9e965d6fSRomain Jobredeaux            )
558*9e965d6fSRomain Jobredeaux            last_stage_output = _create_single_optimization_action(
559*9e965d6fSRomain Jobredeaux                ctx,
560*9e965d6fSRomain Jobredeaux                outputs.output_jar,
561*9e965d6fSRomain Jobredeaux                input_jar,
562*9e965d6fSRomain Jobredeaux                filtered_library_jar,
563*9e965d6fSRomain Jobredeaux                proguard_specs,
564*9e965d6fSRomain Jobredeaux                proguard_mapping,
565*9e965d6fSRomain Jobredeaux                i,
566*9e965d6fSRomain Jobredeaux                "_FINAL",
567*9e965d6fSRomain Jobredeaux                mnemonic,
568*9e965d6fSRomain Jobredeaux                last_stage_output,
569*9e965d6fSRomain Jobredeaux                optimizer_target,
570*9e965d6fSRomain Jobredeaux            )
571*9e965d6fSRomain Jobredeaux        else:
572*9e965d6fSRomain Jobredeaux            for j in range(1, bytecode_optimization_pass_actions + 1):
573*9e965d6fSRomain Jobredeaux                last_stage_output = _create_single_optimization_action(
574*9e965d6fSRomain Jobredeaux                    ctx,
575*9e965d6fSRomain Jobredeaux                    outputs.output_jar,
576*9e965d6fSRomain Jobredeaux                    input_jar,
577*9e965d6fSRomain Jobredeaux                    filtered_library_jar,
578*9e965d6fSRomain Jobredeaux                    proguard_specs,
579*9e965d6fSRomain Jobredeaux                    proguard_mapping,
580*9e965d6fSRomain Jobredeaux                    i,
581*9e965d6fSRomain Jobredeaux                    "_ACTION_%s_OF_%s" % (j, bytecode_optimization_pass_actions),
582*9e965d6fSRomain Jobredeaux                    mnemonic,
583*9e965d6fSRomain Jobredeaux                    last_stage_output,
584*9e965d6fSRomain Jobredeaux                    optimizer_target,
585*9e965d6fSRomain Jobredeaux                )
586*9e965d6fSRomain Jobredeaux
587*9e965d6fSRomain Jobredeaux    _optimization_action(
588*9e965d6fSRomain Jobredeaux        ctx,
589*9e965d6fSRomain Jobredeaux        outputs.output_jar,
590*9e965d6fSRomain Jobredeaux        input_jar,
591*9e965d6fSRomain Jobredeaux        filtered_library_jar,
592*9e965d6fSRomain Jobredeaux        proguard_specs,
593*9e965d6fSRomain Jobredeaux        proguard_mapping = proguard_mapping,
594*9e965d6fSRomain Jobredeaux        proguard_output_map = outputs.mapping,
595*9e965d6fSRomain Jobredeaux        proguard_seeds = None,
596*9e965d6fSRomain Jobredeaux        proguard_usage = outputs.usage,
597*9e965d6fSRomain Jobredeaux        proguard_config_output = outputs.config,
598*9e965d6fSRomain Jobredeaux        startup_profile = None,
599*9e965d6fSRomain Jobredeaux        startup_profile_rewritten = outputs.startup_profile_rewritten,
600*9e965d6fSRomain Jobredeaux        baseline_profile = None,
601*9e965d6fSRomain Jobredeaux        baseline_profile_rewritten = outputs.baseline_profile_rewritten,
602*9e965d6fSRomain Jobredeaux        final = True,
603*9e965d6fSRomain Jobredeaux        runtype = "FINAL",
604*9e965d6fSRomain Jobredeaux        last_stage_output = last_stage_output,
605*9e965d6fSRomain Jobredeaux        mnemonic = mnemonic,
606*9e965d6fSRomain Jobredeaux        progress_message = "Trimming binary with %s: Obfuscation and Final Output Pass" % mnemonic,
607*9e965d6fSRomain Jobredeaux        proguard_tool = proguard_tool,
608*9e965d6fSRomain Jobredeaux    )
609*9e965d6fSRomain Jobredeaux    return outputs
610*9e965d6fSRomain Jobredeaux
611*9e965d6fSRomain Jobredeauxdef _create_single_optimization_action(
612*9e965d6fSRomain Jobredeaux        ctx,
613*9e965d6fSRomain Jobredeaux        output_jar,
614*9e965d6fSRomain Jobredeaux        program_jar,
615*9e965d6fSRomain Jobredeaux        library_jar,
616*9e965d6fSRomain Jobredeaux        proguard_specs,
617*9e965d6fSRomain Jobredeaux        proguard_mapping,
618*9e965d6fSRomain Jobredeaux        optimization_pass_num,
619*9e965d6fSRomain Jobredeaux        runtype_suffix,
620*9e965d6fSRomain Jobredeaux        mnemonic,
621*9e965d6fSRomain Jobredeaux        last_stage_output,
622*9e965d6fSRomain Jobredeaux        proguard_tool):
623*9e965d6fSRomain Jobredeaux    next_stage_output = _get_proguard_temp_artifact(ctx, "_%s_optimization%s_%s.jar" % (mnemonic, runtype_suffix, optimization_pass_num))
624*9e965d6fSRomain Jobredeaux    _optimization_action(
625*9e965d6fSRomain Jobredeaux        ctx,
626*9e965d6fSRomain Jobredeaux        output_jar,
627*9e965d6fSRomain Jobredeaux        program_jar,
628*9e965d6fSRomain Jobredeaux        library_jar,
629*9e965d6fSRomain Jobredeaux        proguard_specs,
630*9e965d6fSRomain Jobredeaux        proguard_mapping = proguard_mapping,
631*9e965d6fSRomain Jobredeaux        mnemonic = mnemonic,
632*9e965d6fSRomain Jobredeaux        final = False,
633*9e965d6fSRomain Jobredeaux        runtype = "OPTIMIZATION" + runtype_suffix,
634*9e965d6fSRomain Jobredeaux        last_stage_output = last_stage_output,
635*9e965d6fSRomain Jobredeaux        next_stage_output = next_stage_output,
636*9e965d6fSRomain Jobredeaux        progress_message = "Trimming binary with %s: Optimization%s Pass %d" % (mnemonic, runtype_suffix, optimization_pass_num),
637*9e965d6fSRomain Jobredeaux        proguard_tool = proguard_tool,
638*9e965d6fSRomain Jobredeaux    )
639*9e965d6fSRomain Jobredeaux    return next_stage_output
640*9e965d6fSRomain Jobredeaux
641*9e965d6fSRomain Jobredeauxdef _merge_proguard_maps(
642*9e965d6fSRomain Jobredeaux        ctx,
643*9e965d6fSRomain Jobredeaux        output,
644*9e965d6fSRomain Jobredeaux        inputs = [],
645*9e965d6fSRomain Jobredeaux        proguard_maps_merger = None,
646*9e965d6fSRomain Jobredeaux        toolchain_type = None):
647*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
648*9e965d6fSRomain Jobredeaux    args.add_all(inputs, before_each = "--pg-map")
649*9e965d6fSRomain Jobredeaux    args.add("--pg-map-output", output)
650*9e965d6fSRomain Jobredeaux
651*9e965d6fSRomain Jobredeaux    ctx.actions.run(
652*9e965d6fSRomain Jobredeaux        outputs = [output],
653*9e965d6fSRomain Jobredeaux        executable = proguard_maps_merger,
654*9e965d6fSRomain Jobredeaux        inputs = inputs,
655*9e965d6fSRomain Jobredeaux        arguments = [args],
656*9e965d6fSRomain Jobredeaux        mnemonic = "MergeProguardMaps",
657*9e965d6fSRomain Jobredeaux        progress_message = "Merging app and desugared library Proguard maps for %s" % ctx.label,
658*9e965d6fSRomain Jobredeaux        use_default_shell_env = True,
659*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
660*9e965d6fSRomain Jobredeaux    )
661*9e965d6fSRomain Jobredeaux
662*9e965d6fSRomain Jobredeauxdef _fail_action(ctx, *outputs):
663*9e965d6fSRomain Jobredeaux    ctx.actions.run_shell(
664*9e965d6fSRomain Jobredeaux        outputs = [output for output in outputs if output != None],
665*9e965d6fSRomain Jobredeaux        command = "echo \"Unable to run proguard without `proguard_specs`\"; exit 1;",
666*9e965d6fSRomain Jobredeaux    )
667*9e965d6fSRomain Jobredeaux
668*9e965d6fSRomain Jobredeauxproguard = struct(
669*9e965d6fSRomain Jobredeaux    apply_proguard = _apply_proguard,
670*9e965d6fSRomain Jobredeaux    process_specs = _process_specs,
671*9e965d6fSRomain Jobredeaux    generate_min_sdk_version_assumevalues = _generate_min_sdk_version_assumevalues,
672*9e965d6fSRomain Jobredeaux    get_proguard_output_map = _get_proguard_output_map,
673*9e965d6fSRomain Jobredeaux    get_proguard_specs = _get_proguard_specs,
674*9e965d6fSRomain Jobredeaux    get_proguard_temp_artifact = _get_proguard_temp_artifact,
675*9e965d6fSRomain Jobredeaux    get_proguard_temp_artifact_with_prefix = _get_proguard_temp_artifact_with_prefix,
676*9e965d6fSRomain Jobredeaux    merge_proguard_maps = _merge_proguard_maps,
677*9e965d6fSRomain Jobredeaux)
678*9e965d6fSRomain Jobredeaux
679*9e965d6fSRomain Jobredeauxtesting = struct(
680*9e965d6fSRomain Jobredeaux    validate_proguard_spec = _validate_proguard_spec,
681*9e965d6fSRomain Jobredeaux    collect_transitive_proguard_specs = _collect_transitive_proguard_specs,
682*9e965d6fSRomain Jobredeaux    optimization_action = _optimization_action,
683*9e965d6fSRomain Jobredeaux    ProguardSpecContextInfo = _ProguardSpecContextInfo,
684*9e965d6fSRomain Jobredeaux)
685