xref: /aosp_15_r20/external/bazelbuild-rules_android/rules/dex.bzl (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1*9e965d6fSRomain Jobredeaux# Copyright 2023 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 Dex Commands."""
16*9e965d6fSRomain Jobredeaux
17*9e965d6fSRomain Jobredeauxload("//rules:attrs.bzl", _attrs = "attrs")
18*9e965d6fSRomain Jobredeauxload("//rules:common.bzl", _common = "common")
19*9e965d6fSRomain Jobredeauxload("//rules:java.bzl", _java = "java")
20*9e965d6fSRomain Jobredeauxload("@bazel_skylib//lib:collections.bzl", "collections")
21*9e965d6fSRomain Jobredeauxload(":providers.bzl", "StarlarkAndroidDexInfo")
22*9e965d6fSRomain Jobredeauxload(":utils.bzl", "ANDROID_TOOLCHAIN_TYPE", "get_android_toolchain", "utils")
23*9e965d6fSRomain Jobredeaux
24*9e965d6fSRomain Jobredeaux_DEX_MEMORY = 4096
25*9e965d6fSRomain Jobredeaux_DEX_THREADS = 5
26*9e965d6fSRomain Jobredeaux
27*9e965d6fSRomain Jobredeaux_tristate = _attrs.tristate
28*9e965d6fSRomain Jobredeaux
29*9e965d6fSRomain Jobredeauxdef _resource_set_for_monolithic_dexing():
30*9e965d6fSRomain Jobredeaux    return {"cpu": _DEX_THREADS, "memory": _DEX_MEMORY}
31*9e965d6fSRomain Jobredeaux
32*9e965d6fSRomain Jobredeauxdef _process_incremental_dexing(
33*9e965d6fSRomain Jobredeaux        ctx,
34*9e965d6fSRomain Jobredeaux        output,
35*9e965d6fSRomain Jobredeaux        deps = [],
36*9e965d6fSRomain Jobredeaux        runtime_jars = [],
37*9e965d6fSRomain Jobredeaux        dexopts = [],
38*9e965d6fSRomain Jobredeaux        main_dex_list = None,
39*9e965d6fSRomain Jobredeaux        min_sdk_version = 0,
40*9e965d6fSRomain Jobredeaux        proguarded_jar = None,
41*9e965d6fSRomain Jobredeaux        java_info = None,
42*9e965d6fSRomain Jobredeaux        desugar_dict = {},
43*9e965d6fSRomain Jobredeaux        shuffle_jars = None,
44*9e965d6fSRomain Jobredeaux        dexbuilder = None,
45*9e965d6fSRomain Jobredeaux        dexbuilder_after_proguard = None,
46*9e965d6fSRomain Jobredeaux        dexmerger = None,
47*9e965d6fSRomain Jobredeaux        dexsharder = None,
48*9e965d6fSRomain Jobredeaux        toolchain_type = None):
49*9e965d6fSRomain Jobredeaux    info = _merge_infos(utils.collect_providers(StarlarkAndroidDexInfo, deps))
50*9e965d6fSRomain Jobredeaux    incremental_dexopts = _filter_dexopts(dexopts, ctx.fragments.android.get_dexopts_supported_in_incremental_dexing)
51*9e965d6fSRomain Jobredeaux    inclusion_filter_jar = proguarded_jar
52*9e965d6fSRomain Jobredeaux    if not proguarded_jar:
53*9e965d6fSRomain Jobredeaux        dex_archives = []
54*9e965d6fSRomain Jobredeaux        for jar in runtime_jars:
55*9e965d6fSRomain Jobredeaux            dex_archive = _get_dx_artifact(ctx, jar.basename + ".dex.zip")
56*9e965d6fSRomain Jobredeaux            _dex(
57*9e965d6fSRomain Jobredeaux                ctx,
58*9e965d6fSRomain Jobredeaux                input = desugar_dict[jar] if jar in desugar_dict else jar,
59*9e965d6fSRomain Jobredeaux                output = dex_archive,
60*9e965d6fSRomain Jobredeaux                incremental_dexopts = incremental_dexopts,
61*9e965d6fSRomain Jobredeaux                min_sdk_version = min_sdk_version,
62*9e965d6fSRomain Jobredeaux                dex_exec = dexbuilder,
63*9e965d6fSRomain Jobredeaux                toolchain_type = toolchain_type,
64*9e965d6fSRomain Jobredeaux            )
65*9e965d6fSRomain Jobredeaux            dex_archives.append(dex_archive)
66*9e965d6fSRomain Jobredeaux        dex_archives += _to_dexed_classpath(
67*9e965d6fSRomain Jobredeaux            dex_archives_dict = {d.jar: d.dex for d in info.dex_archives_dict.get("".join(incremental_dexopts), depset()).to_list()},
68*9e965d6fSRomain Jobredeaux            classpath = _filter(java_info.transitive_runtime_jars.to_list(), excludes = _get_library_r_jars(deps)),
69*9e965d6fSRomain Jobredeaux            runtime_jars = runtime_jars,
70*9e965d6fSRomain Jobredeaux        )
71*9e965d6fSRomain Jobredeaux    else:
72*9e965d6fSRomain Jobredeaux        java_resource_jar = ctx.actions.declare_file(ctx.label.name + "_files/java_resources.jar")
73*9e965d6fSRomain Jobredeaux        if ctx.fragments.android.incremental_dexing_shards_after_proguard > 1:
74*9e965d6fSRomain Jobredeaux            dex_archives = _shard_proguarded_jar_and_dex(
75*9e965d6fSRomain Jobredeaux                ctx,
76*9e965d6fSRomain Jobredeaux                java_resource_jar = java_resource_jar,
77*9e965d6fSRomain Jobredeaux                num_shards = ctx.fragments.android.incremental_dexing_shards_after_proguard,
78*9e965d6fSRomain Jobredeaux                dexopts = incremental_dexopts,
79*9e965d6fSRomain Jobredeaux                proguarded_jar = proguarded_jar,
80*9e965d6fSRomain Jobredeaux                main_dex_list = main_dex_list,
81*9e965d6fSRomain Jobredeaux                min_sdk_version = min_sdk_version,
82*9e965d6fSRomain Jobredeaux                shuffle_jars = shuffle_jars,
83*9e965d6fSRomain Jobredeaux                dexbuilder_after_proguard = dexbuilder_after_proguard,
84*9e965d6fSRomain Jobredeaux                toolchain_type = toolchain_type,
85*9e965d6fSRomain Jobredeaux            )
86*9e965d6fSRomain Jobredeaux            inclusion_filter_jar = None
87*9e965d6fSRomain Jobredeaux        else:
88*9e965d6fSRomain Jobredeaux            # No need to shuffle if there is only one shard
89*9e965d6fSRomain Jobredeaux            dex_archive = _get_dx_artifact(ctx, "classes.jar")
90*9e965d6fSRomain Jobredeaux            _dex(
91*9e965d6fSRomain Jobredeaux                ctx,
92*9e965d6fSRomain Jobredeaux                input = proguarded_jar,
93*9e965d6fSRomain Jobredeaux                output = dex_archive,
94*9e965d6fSRomain Jobredeaux                incremental_dexopts = incremental_dexopts,
95*9e965d6fSRomain Jobredeaux                min_sdk_version = min_sdk_version,
96*9e965d6fSRomain Jobredeaux                dex_exec = dexbuilder_after_proguard,
97*9e965d6fSRomain Jobredeaux                toolchain_type = toolchain_type,
98*9e965d6fSRomain Jobredeaux            )
99*9e965d6fSRomain Jobredeaux            dex_archives = [dex_archive]
100*9e965d6fSRomain Jobredeaux
101*9e965d6fSRomain Jobredeaux    if len(dex_archives) == 1:
102*9e965d6fSRomain Jobredeaux        _dex_merge(
103*9e965d6fSRomain Jobredeaux            ctx,
104*9e965d6fSRomain Jobredeaux            output = output,
105*9e965d6fSRomain Jobredeaux            inputs = dex_archives,
106*9e965d6fSRomain Jobredeaux            multidex_strategy = "minimal",
107*9e965d6fSRomain Jobredeaux            main_dex_list = main_dex_list,
108*9e965d6fSRomain Jobredeaux            dexopts = _filter_dexopts(dexopts, ctx.fragments.android.get_dexopts_supported_in_dex_merger),
109*9e965d6fSRomain Jobredeaux            dexmerger = dexmerger,
110*9e965d6fSRomain Jobredeaux            toolchain_type = toolchain_type,
111*9e965d6fSRomain Jobredeaux        )
112*9e965d6fSRomain Jobredeaux    else:
113*9e965d6fSRomain Jobredeaux        shards = ctx.actions.declare_directory("dexsplits/" + ctx.label.name)
114*9e965d6fSRomain Jobredeaux        dexes = ctx.actions.declare_directory("dexfiles/" + ctx.label.name)
115*9e965d6fSRomain Jobredeaux        _shard_dexes(
116*9e965d6fSRomain Jobredeaux            ctx,
117*9e965d6fSRomain Jobredeaux            output = shards,
118*9e965d6fSRomain Jobredeaux            inputs = dex_archives,
119*9e965d6fSRomain Jobredeaux            dexopts = _filter_dexopts(dexopts, ctx.fragments.android.get_dexopts_supported_in_dex_sharder),
120*9e965d6fSRomain Jobredeaux            main_dex_list = main_dex_list,
121*9e965d6fSRomain Jobredeaux            inclusion_filter_jar = inclusion_filter_jar,
122*9e965d6fSRomain Jobredeaux            dexsharder = dexsharder,
123*9e965d6fSRomain Jobredeaux            toolchain_type = toolchain_type,
124*9e965d6fSRomain Jobredeaux        )
125*9e965d6fSRomain Jobredeaux
126*9e965d6fSRomain Jobredeaux        # TODO(b/130571505): Implement this after SpawnActionTemplate is supported in Starlark
127*9e965d6fSRomain Jobredeaux        android_common.create_dex_merger_actions(
128*9e965d6fSRomain Jobredeaux            ctx,
129*9e965d6fSRomain Jobredeaux            output = dexes,
130*9e965d6fSRomain Jobredeaux            input = shards,
131*9e965d6fSRomain Jobredeaux            dexopts = dexopts,
132*9e965d6fSRomain Jobredeaux            dexmerger = dexmerger,
133*9e965d6fSRomain Jobredeaux        )
134*9e965d6fSRomain Jobredeaux        _java.singlejar(
135*9e965d6fSRomain Jobredeaux            ctx,
136*9e965d6fSRomain Jobredeaux            output = output,
137*9e965d6fSRomain Jobredeaux            inputs = [dexes],
138*9e965d6fSRomain Jobredeaux            mnemonic = "MergeDexZips",
139*9e965d6fSRomain Jobredeaux            progress_message = "Merging dex shards for %s." % ctx.label,
140*9e965d6fSRomain Jobredeaux            java_toolchain = _common.get_java_toolchain(ctx),
141*9e965d6fSRomain Jobredeaux        )
142*9e965d6fSRomain Jobredeaux
143*9e965d6fSRomain Jobredeauxdef _process_optimized_dexing(
144*9e965d6fSRomain Jobredeaux        ctx,
145*9e965d6fSRomain Jobredeaux        output,
146*9e965d6fSRomain Jobredeaux        input = None,
147*9e965d6fSRomain Jobredeaux        proguard_output_map = None,
148*9e965d6fSRomain Jobredeaux        postprocessing_output_map = None,
149*9e965d6fSRomain Jobredeaux        dexopts = [],
150*9e965d6fSRomain Jobredeaux        native_multidex = True,
151*9e965d6fSRomain Jobredeaux        min_sdk_version = 0,
152*9e965d6fSRomain Jobredeaux        main_dex_list = None,
153*9e965d6fSRomain Jobredeaux        library_jar = None,
154*9e965d6fSRomain Jobredeaux        startup_profile = None,
155*9e965d6fSRomain Jobredeaux        optimizing_dexer = None,
156*9e965d6fSRomain Jobredeaux        toolchain_type = None):
157*9e965d6fSRomain Jobredeaux    inputs = [input]
158*9e965d6fSRomain Jobredeaux    outputs = [output]
159*9e965d6fSRomain Jobredeaux
160*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
161*9e965d6fSRomain Jobredeaux    args.add(input)
162*9e965d6fSRomain Jobredeaux    args.add("--release")
163*9e965d6fSRomain Jobredeaux    args.add("--no-desugaring")
164*9e965d6fSRomain Jobredeaux    args.add("--output", output)
165*9e965d6fSRomain Jobredeaux    args.add_all(dexopts)
166*9e965d6fSRomain Jobredeaux
167*9e965d6fSRomain Jobredeaux    if proguard_output_map:
168*9e965d6fSRomain Jobredeaux        args.add("--pg-map", proguard_output_map)
169*9e965d6fSRomain Jobredeaux        args.add("--pg-map-output", postprocessing_output_map)
170*9e965d6fSRomain Jobredeaux        inputs.append(proguard_output_map)
171*9e965d6fSRomain Jobredeaux        outputs.append(postprocessing_output_map)
172*9e965d6fSRomain Jobredeaux
173*9e965d6fSRomain Jobredeaux    if startup_profile and native_multidex:
174*9e965d6fSRomain Jobredeaux        args.add("--startup-profile", startup_profile)
175*9e965d6fSRomain Jobredeaux        inputs.append(startup_profile)
176*9e965d6fSRomain Jobredeaux
177*9e965d6fSRomain Jobredeaux    # TODO(b/261110876): Pass min SDK through here based on the value in the merged manifest. The
178*9e965d6fSRomain Jobredeaux    # current value is statically defined for the entire depot.
179*9e965d6fSRomain Jobredeaux    # We currently set the minimum SDK version to 21 if you are doing native multidex as that is
180*9e965d6fSRomain Jobredeaux    # required for native multidex to work in the first place and as a result is required for
181*9e965d6fSRomain Jobredeaux    # correct behavior from the dexer.
182*9e965d6fSRomain Jobredeaux    sdk = max(min_sdk_version, 21) if native_multidex else min_sdk_version
183*9e965d6fSRomain Jobredeaux    if sdk != 0:
184*9e965d6fSRomain Jobredeaux        args.add("--min-api", sdk)
185*9e965d6fSRomain Jobredeaux    if main_dex_list:
186*9e965d6fSRomain Jobredeaux        args.add("--main-dex-list", main_dex_list)
187*9e965d6fSRomain Jobredeaux        inputs.append(main_dex_list)
188*9e965d6fSRomain Jobredeaux    if library_jar:
189*9e965d6fSRomain Jobredeaux        args.add("--lib", library_jar)
190*9e965d6fSRomain Jobredeaux        inputs.append(library_jar)
191*9e965d6fSRomain Jobredeaux
192*9e965d6fSRomain Jobredeaux    ctx.actions.run(
193*9e965d6fSRomain Jobredeaux        outputs = outputs,
194*9e965d6fSRomain Jobredeaux        executable = optimizing_dexer,
195*9e965d6fSRomain Jobredeaux        inputs = inputs,
196*9e965d6fSRomain Jobredeaux        arguments = [args],
197*9e965d6fSRomain Jobredeaux        mnemonic = "OptimizingDex",
198*9e965d6fSRomain Jobredeaux        progress_message = "Optimized dexing for " + str(ctx.label),
199*9e965d6fSRomain Jobredeaux        use_default_shell_env = True,
200*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
201*9e965d6fSRomain Jobredeaux    )
202*9e965d6fSRomain Jobredeaux
203*9e965d6fSRomain Jobredeauxdef _process_monolithic_dexing(
204*9e965d6fSRomain Jobredeaux        ctx,
205*9e965d6fSRomain Jobredeaux        output,
206*9e965d6fSRomain Jobredeaux        input,
207*9e965d6fSRomain Jobredeaux        dexopts = [],
208*9e965d6fSRomain Jobredeaux        min_sdk_version = 0,
209*9e965d6fSRomain Jobredeaux        main_dex_list = None,
210*9e965d6fSRomain Jobredeaux        dexbuilder = None,
211*9e965d6fSRomain Jobredeaux        toolchain_type = None):
212*9e965d6fSRomain Jobredeaux    # Create an artifact for the intermediate zip output generated by AndroidDexer that includes
213*9e965d6fSRomain Jobredeaux    # non-.dex files. A subsequent TrimDexZip action will filter out all non-.dex files.
214*9e965d6fSRomain Jobredeaux    classes_dex_intermediate = _get_dx_artifact(ctx, "intermediate_classes.dex.zip")
215*9e965d6fSRomain Jobredeaux    inputs = [input]
216*9e965d6fSRomain Jobredeaux
217*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
218*9e965d6fSRomain Jobredeaux    args.add("--dex")
219*9e965d6fSRomain Jobredeaux    args.add_all(dexopts)
220*9e965d6fSRomain Jobredeaux    if min_sdk_version > 0:
221*9e965d6fSRomain Jobredeaux        args.add("--min_sdk_version", min_sdk_version)
222*9e965d6fSRomain Jobredeaux    args.add("--multi-dex")
223*9e965d6fSRomain Jobredeaux    if main_dex_list:
224*9e965d6fSRomain Jobredeaux        args.add(main_dex_list, format = "--main-dex-list=%s")
225*9e965d6fSRomain Jobredeaux        inputs.append(main_dex_list)
226*9e965d6fSRomain Jobredeaux    args.add(classes_dex_intermediate, format = "--output=%s")
227*9e965d6fSRomain Jobredeaux    args.add(input)
228*9e965d6fSRomain Jobredeaux
229*9e965d6fSRomain Jobredeaux    ctx.actions.run(
230*9e965d6fSRomain Jobredeaux        executable = dexbuilder,
231*9e965d6fSRomain Jobredeaux        inputs = inputs,
232*9e965d6fSRomain Jobredeaux        outputs = [classes_dex_intermediate],
233*9e965d6fSRomain Jobredeaux        arguments = [args],
234*9e965d6fSRomain Jobredeaux        progress_message = "Converting %s to dex format" % input.short_path,
235*9e965d6fSRomain Jobredeaux        mnemonic = "AndroidDexer",
236*9e965d6fSRomain Jobredeaux        use_default_shell_env = True,
237*9e965d6fSRomain Jobredeaux        resource_set = _resource_set_for_monolithic_dexing,
238*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
239*9e965d6fSRomain Jobredeaux    )
240*9e965d6fSRomain Jobredeaux
241*9e965d6fSRomain Jobredeaux    # Because the dexer also places resources into this zip, we also need to create a cleanup
242*9e965d6fSRomain Jobredeaux    # action that removes all non-.dex files before staging for apk building.
243*9e965d6fSRomain Jobredeaux    _java.singlejar(
244*9e965d6fSRomain Jobredeaux        ctx,
245*9e965d6fSRomain Jobredeaux        inputs = [classes_dex_intermediate],
246*9e965d6fSRomain Jobredeaux        output = output,
247*9e965d6fSRomain Jobredeaux        include_prefixes = ["classes"],
248*9e965d6fSRomain Jobredeaux        java_toolchain = _common.get_java_toolchain(ctx),
249*9e965d6fSRomain Jobredeaux        mnemonic = "TrimDexZip",
250*9e965d6fSRomain Jobredeaux        progress_message = "Trimming %s." % classes_dex_intermediate.short_path,
251*9e965d6fSRomain Jobredeaux    )
252*9e965d6fSRomain Jobredeaux
253*9e965d6fSRomain Jobredeauxdef _shard_proguarded_jar_and_dex(
254*9e965d6fSRomain Jobredeaux        ctx,
255*9e965d6fSRomain Jobredeaux        java_resource_jar,
256*9e965d6fSRomain Jobredeaux        num_shards = 50,
257*9e965d6fSRomain Jobredeaux        dexopts = [],
258*9e965d6fSRomain Jobredeaux        proguarded_jar = None,
259*9e965d6fSRomain Jobredeaux        main_dex_list = None,
260*9e965d6fSRomain Jobredeaux        min_sdk_version = 0,
261*9e965d6fSRomain Jobredeaux        shuffle_jars = None,
262*9e965d6fSRomain Jobredeaux        dexbuilder_after_proguard = None,
263*9e965d6fSRomain Jobredeaux        toolchain_type = None):
264*9e965d6fSRomain Jobredeaux    if num_shards <= 1:
265*9e965d6fSRomain Jobredeaux        fail("num_shards expects to be larger than 1.")
266*9e965d6fSRomain Jobredeaux
267*9e965d6fSRomain Jobredeaux    shards = _make_shard_artifacts(ctx, num_shards, ".jar.dex.zip")
268*9e965d6fSRomain Jobredeaux    shuffle_outputs = _make_shard_artifacts(ctx, num_shards, ".jar")
269*9e965d6fSRomain Jobredeaux    inputs = []
270*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
271*9e965d6fSRomain Jobredeaux    args.add_all(shuffle_outputs, before_each = "--output_jar")
272*9e965d6fSRomain Jobredeaux    args.add("--output_resources", java_resource_jar)
273*9e965d6fSRomain Jobredeaux
274*9e965d6fSRomain Jobredeaux    if main_dex_list:
275*9e965d6fSRomain Jobredeaux        args.add("--main_dex_filter", main_dex_list)
276*9e965d6fSRomain Jobredeaux        inputs.append(main_dex_list)
277*9e965d6fSRomain Jobredeaux
278*9e965d6fSRomain Jobredeaux    # If we need to run Proguard, all the class files will be in the Proguarded jar, which has to
279*9e965d6fSRomain Jobredeaux    # be converted to dex.
280*9e965d6fSRomain Jobredeaux    args.add("--input_jar", proguarded_jar)
281*9e965d6fSRomain Jobredeaux    inputs.append(proguarded_jar)
282*9e965d6fSRomain Jobredeaux
283*9e965d6fSRomain Jobredeaux    ctx.actions.run(
284*9e965d6fSRomain Jobredeaux        executable = shuffle_jars,
285*9e965d6fSRomain Jobredeaux        outputs = shuffle_outputs + [java_resource_jar],
286*9e965d6fSRomain Jobredeaux        inputs = inputs,
287*9e965d6fSRomain Jobredeaux        arguments = [args],
288*9e965d6fSRomain Jobredeaux        mnemonic = "ShardClassesToDex",
289*9e965d6fSRomain Jobredeaux        progress_message = "Sharding classes for dexing for " + str(ctx.label),
290*9e965d6fSRomain Jobredeaux        use_default_shell_env = True,
291*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
292*9e965d6fSRomain Jobredeaux    )
293*9e965d6fSRomain Jobredeaux
294*9e965d6fSRomain Jobredeaux    for i in range(len(shards)):
295*9e965d6fSRomain Jobredeaux        _dex(
296*9e965d6fSRomain Jobredeaux            ctx,
297*9e965d6fSRomain Jobredeaux            input = shuffle_outputs[i],
298*9e965d6fSRomain Jobredeaux            output = shards[i],
299*9e965d6fSRomain Jobredeaux            incremental_dexopts = dexopts,
300*9e965d6fSRomain Jobredeaux            min_sdk_version = min_sdk_version,
301*9e965d6fSRomain Jobredeaux            dex_exec = dexbuilder_after_proguard,
302*9e965d6fSRomain Jobredeaux            toolchain_type = toolchain_type,
303*9e965d6fSRomain Jobredeaux        )
304*9e965d6fSRomain Jobredeaux    return shards
305*9e965d6fSRomain Jobredeaux
306*9e965d6fSRomain Jobredeauxdef _make_shard_artifacts(ctx, n, suffix):
307*9e965d6fSRomain Jobredeaux    return [_get_dx_artifact(ctx, "shard" + str(i) + suffix) for i in range(1, n + 1)]
308*9e965d6fSRomain Jobredeaux
309*9e965d6fSRomain Jobredeauxdef _shard_dexes(
310*9e965d6fSRomain Jobredeaux        ctx,
311*9e965d6fSRomain Jobredeaux        output,
312*9e965d6fSRomain Jobredeaux        inputs = [],
313*9e965d6fSRomain Jobredeaux        dexopts = [],
314*9e965d6fSRomain Jobredeaux        main_dex_list = None,
315*9e965d6fSRomain Jobredeaux        inclusion_filter_jar = None,
316*9e965d6fSRomain Jobredeaux        dexsharder = None,
317*9e965d6fSRomain Jobredeaux        toolchain_type = None):
318*9e965d6fSRomain Jobredeaux    args = ctx.actions.args().use_param_file(param_file_arg = "@%s")
319*9e965d6fSRomain Jobredeaux    args.add_all(inputs, before_each = "--input")
320*9e965d6fSRomain Jobredeaux    args.add("--output", output.path)
321*9e965d6fSRomain Jobredeaux    if main_dex_list:
322*9e965d6fSRomain Jobredeaux        inputs.append(main_dex_list)
323*9e965d6fSRomain Jobredeaux        args.add("--main-dex-list", main_dex_list)
324*9e965d6fSRomain Jobredeaux    if inclusion_filter_jar:
325*9e965d6fSRomain Jobredeaux        inputs.append(inclusion_filter_jar)
326*9e965d6fSRomain Jobredeaux        args.add("--inclusion_filter_jar", inclusion_filter_jar)
327*9e965d6fSRomain Jobredeaux
328*9e965d6fSRomain Jobredeaux    args.add_all(dexopts)
329*9e965d6fSRomain Jobredeaux
330*9e965d6fSRomain Jobredeaux    ctx.actions.run(
331*9e965d6fSRomain Jobredeaux        executable = dexsharder,
332*9e965d6fSRomain Jobredeaux        outputs = [output],
333*9e965d6fSRomain Jobredeaux        inputs = inputs,
334*9e965d6fSRomain Jobredeaux        arguments = [args],
335*9e965d6fSRomain Jobredeaux        mnemonic = "ShardForMultidex",
336*9e965d6fSRomain Jobredeaux        progress_message = "Assembling dex files for " + ctx.label.name,
337*9e965d6fSRomain Jobredeaux        use_default_shell_env = True,
338*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
339*9e965d6fSRomain Jobredeaux    )
340*9e965d6fSRomain Jobredeaux
341*9e965d6fSRomain Jobredeaux    return output
342*9e965d6fSRomain Jobredeaux
343*9e965d6fSRomain Jobredeauxdef _append_java8_legacy_dex(
344*9e965d6fSRomain Jobredeaux        ctx,
345*9e965d6fSRomain Jobredeaux        output = None,
346*9e965d6fSRomain Jobredeaux        input = None,
347*9e965d6fSRomain Jobredeaux        java8_legacy_dex = None,
348*9e965d6fSRomain Jobredeaux        dex_zips_merger = None):
349*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
350*9e965d6fSRomain Jobredeaux
351*9e965d6fSRomain Jobredeaux    # Order matters here: we want java8_legacy_dex to be the highest-numbered classesN.dex
352*9e965d6fSRomain Jobredeaux    args.add("--input_zip", input)
353*9e965d6fSRomain Jobredeaux    args.add("--input_zip", java8_legacy_dex)
354*9e965d6fSRomain Jobredeaux    args.add("--output_zip", output)
355*9e965d6fSRomain Jobredeaux
356*9e965d6fSRomain Jobredeaux    ctx.actions.run(
357*9e965d6fSRomain Jobredeaux        executable = dex_zips_merger,
358*9e965d6fSRomain Jobredeaux        inputs = [input, java8_legacy_dex],
359*9e965d6fSRomain Jobredeaux        outputs = [output],
360*9e965d6fSRomain Jobredeaux        arguments = [args],
361*9e965d6fSRomain Jobredeaux        mnemonic = "AppendJava8LegacyDex",
362*9e965d6fSRomain Jobredeaux        use_default_shell_env = True,
363*9e965d6fSRomain Jobredeaux        progress_message = "Adding Java8 legacy library for %s" % ctx.label,
364*9e965d6fSRomain Jobredeaux        toolchain = ANDROID_TOOLCHAIN_TYPE,
365*9e965d6fSRomain Jobredeaux    )
366*9e965d6fSRomain Jobredeaux
367*9e965d6fSRomain Jobredeauxdef _to_dexed_classpath(dex_archives_dict = {}, classpath = [], runtime_jars = []):
368*9e965d6fSRomain Jobredeaux    dexed_classpath = []
369*9e965d6fSRomain Jobredeaux    for jar in classpath:
370*9e965d6fSRomain Jobredeaux        if jar not in dex_archives_dict:
371*9e965d6fSRomain Jobredeaux            if jar not in runtime_jars:
372*9e965d6fSRomain Jobredeaux                fail("Dependencies on .jar artifacts are not allowed in Android binaries, please use " +
373*9e965d6fSRomain Jobredeaux                     "a java_import to depend on " + jar.short_path +
374*9e965d6fSRomain Jobredeaux                     ". If this is an implicit dependency then the rule that " +
375*9e965d6fSRomain Jobredeaux                     "introduces it will need to be fixed to account for it correctly.")
376*9e965d6fSRomain Jobredeaux        else:
377*9e965d6fSRomain Jobredeaux            dexed_classpath.append(dex_archives_dict[jar])
378*9e965d6fSRomain Jobredeaux    return dexed_classpath
379*9e965d6fSRomain Jobredeaux
380*9e965d6fSRomain Jobredeauxdef _dex(
381*9e965d6fSRomain Jobredeaux        ctx,
382*9e965d6fSRomain Jobredeaux        input,
383*9e965d6fSRomain Jobredeaux        output = None,
384*9e965d6fSRomain Jobredeaux        incremental_dexopts = [],
385*9e965d6fSRomain Jobredeaux        min_sdk_version = 0,
386*9e965d6fSRomain Jobredeaux        dex_exec = None,
387*9e965d6fSRomain Jobredeaux        toolchain_type = None):
388*9e965d6fSRomain Jobredeaux    """Dexes a JAR.
389*9e965d6fSRomain Jobredeaux
390*9e965d6fSRomain Jobredeaux    Args:
391*9e965d6fSRomain Jobredeaux        ctx: The context.
392*9e965d6fSRomain Jobredeaux        input: File. The jar to be dexed.
393*9e965d6fSRomain Jobredeaux        output: File. The archive file containing all of the dexes.
394*9e965d6fSRomain Jobredeaux        incremental_dexopts: List of strings. Additional command-line flags for the dexing tool when building dexes.
395*9e965d6fSRomain Jobredeaux        min_sdk_version: Integer. The minimum targeted sdk version.
396*9e965d6fSRomain Jobredeaux        dex_exec: File. The executable dex builder file.
397*9e965d6fSRomain Jobredeaux    """
398*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
399*9e965d6fSRomain Jobredeaux    args.use_param_file("@%s", use_always = True)  # Required for workers.
400*9e965d6fSRomain Jobredeaux    args.set_param_file_format("multiline")
401*9e965d6fSRomain Jobredeaux
402*9e965d6fSRomain Jobredeaux    args.add("--input_jar", input)
403*9e965d6fSRomain Jobredeaux    args.add("--output_zip", output)
404*9e965d6fSRomain Jobredeaux    args.add_all(incremental_dexopts)
405*9e965d6fSRomain Jobredeaux
406*9e965d6fSRomain Jobredeaux    if min_sdk_version > 0:
407*9e965d6fSRomain Jobredeaux        args.add("--min_sdk_version", min_sdk_version)
408*9e965d6fSRomain Jobredeaux
409*9e965d6fSRomain Jobredeaux    execution_requirements = {}
410*9e965d6fSRomain Jobredeaux    if ctx.fragments.android.persistent_android_dex_desugar:
411*9e965d6fSRomain Jobredeaux        execution_requirements["supports-workers"] = "1"
412*9e965d6fSRomain Jobredeaux        if ctx.fragments.android.persistent_multiplex_android_dex_desugar:
413*9e965d6fSRomain Jobredeaux            execution_requirements["supports-multiplex-workers"] = "1"
414*9e965d6fSRomain Jobredeaux
415*9e965d6fSRomain Jobredeaux    ctx.actions.run(
416*9e965d6fSRomain Jobredeaux        executable = dex_exec,
417*9e965d6fSRomain Jobredeaux        arguments = [args],
418*9e965d6fSRomain Jobredeaux        inputs = [input],
419*9e965d6fSRomain Jobredeaux        outputs = [output],
420*9e965d6fSRomain Jobredeaux        mnemonic = "DexBuilder",
421*9e965d6fSRomain Jobredeaux        progress_message = "Dexing " + input.path + " with applicable dexopts " + str(incremental_dexopts),
422*9e965d6fSRomain Jobredeaux        execution_requirements = execution_requirements,
423*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
424*9e965d6fSRomain Jobredeaux    )
425*9e965d6fSRomain Jobredeaux
426*9e965d6fSRomain Jobredeauxdef _get_dx_artifact(ctx, basename):
427*9e965d6fSRomain Jobredeaux    return ctx.actions.declare_file("_dx_migrated/" + ctx.label.name + "/" + basename)
428*9e965d6fSRomain Jobredeaux
429*9e965d6fSRomain Jobredeauxdef _get_effective_incremental_dexing(
430*9e965d6fSRomain Jobredeaux        force_incremental_dexing = _tristate.auto,
431*9e965d6fSRomain Jobredeaux        has_forbidden_dexopts = False,
432*9e965d6fSRomain Jobredeaux        incremental_dexing_after_proguard_by_default = True,
433*9e965d6fSRomain Jobredeaux        incremental_dexing_shards_after_proguard = True,
434*9e965d6fSRomain Jobredeaux        is_binary_optimized = False,
435*9e965d6fSRomain Jobredeaux        use_incremental_dexing = True):
436*9e965d6fSRomain Jobredeaux    if (is_binary_optimized and
437*9e965d6fSRomain Jobredeaux        force_incremental_dexing == _tristate.yes and incremental_dexing_shards_after_proguard <= 0):
438*9e965d6fSRomain Jobredeaux        fail("Target cannot be incrementally dexed because it uses Proguard")
439*9e965d6fSRomain Jobredeaux
440*9e965d6fSRomain Jobredeaux    if force_incremental_dexing == _tristate.yes:
441*9e965d6fSRomain Jobredeaux        return True
442*9e965d6fSRomain Jobredeaux
443*9e965d6fSRomain Jobredeaux    if force_incremental_dexing == _tristate.no:
444*9e965d6fSRomain Jobredeaux        return False
445*9e965d6fSRomain Jobredeaux
446*9e965d6fSRomain Jobredeaux    # If there are incompatible dexopts and the incremental_dexing attr is not set, we silently don't run
447*9e965d6fSRomain Jobredeaux    # incremental dexing.
448*9e965d6fSRomain Jobredeaux    if has_forbidden_dexopts or (is_binary_optimized and not incremental_dexing_after_proguard_by_default):
449*9e965d6fSRomain Jobredeaux        return False
450*9e965d6fSRomain Jobredeaux
451*9e965d6fSRomain Jobredeaux    # use_incremental_dexing config flag will take effect if incremental_dexing attr is not set
452*9e965d6fSRomain Jobredeaux    return use_incremental_dexing
453*9e965d6fSRomain Jobredeaux
454*9e965d6fSRomain Jobredeauxdef _get_java8_legacy_dex_and_map(ctx, build_customized_files = False, binary_jar = None, android_jar = None):
455*9e965d6fSRomain Jobredeaux    if not build_customized_files:
456*9e965d6fSRomain Jobredeaux        return utils.only(get_android_toolchain(ctx).java8_legacy_dex.files.to_list()), None
457*9e965d6fSRomain Jobredeaux    else:
458*9e965d6fSRomain Jobredeaux        java8_legacy_dex_rules = _get_dx_artifact(ctx, "_java8_legacy.dex.pgcfg")
459*9e965d6fSRomain Jobredeaux        java8_legacy_dex_map = _get_dx_artifact(ctx, "_java8_legacy.dex.map")
460*9e965d6fSRomain Jobredeaux        java8_legacy_dex = _get_dx_artifact(ctx, "_java8_legacy.dex.zip")
461*9e965d6fSRomain Jobredeaux
462*9e965d6fSRomain Jobredeaux        args = ctx.actions.args()
463*9e965d6fSRomain Jobredeaux        args.add("--rules", java8_legacy_dex_rules)
464*9e965d6fSRomain Jobredeaux        args.add("--binary", binary_jar)
465*9e965d6fSRomain Jobredeaux        args.add("--android_jar", android_jar)
466*9e965d6fSRomain Jobredeaux        args.add("--output", java8_legacy_dex)
467*9e965d6fSRomain Jobredeaux        args.add("--output_map", java8_legacy_dex_map)
468*9e965d6fSRomain Jobredeaux
469*9e965d6fSRomain Jobredeaux        ctx.actions.run(
470*9e965d6fSRomain Jobredeaux            executable = get_android_toolchain(ctx).build_java8_legacy_dex.files_to_run,
471*9e965d6fSRomain Jobredeaux            inputs = [binary_jar, android_jar],
472*9e965d6fSRomain Jobredeaux            outputs = [java8_legacy_dex_rules, java8_legacy_dex_map, java8_legacy_dex],
473*9e965d6fSRomain Jobredeaux            arguments = [args],
474*9e965d6fSRomain Jobredeaux            mnemonic = "BuildLegacyDex",
475*9e965d6fSRomain Jobredeaux            progress_message = "Building Java8 legacy library for %s" % ctx.label,
476*9e965d6fSRomain Jobredeaux            toolchain = ANDROID_TOOLCHAIN_TYPE,
477*9e965d6fSRomain Jobredeaux        )
478*9e965d6fSRomain Jobredeaux
479*9e965d6fSRomain Jobredeaux        return java8_legacy_dex, java8_legacy_dex_map
480*9e965d6fSRomain Jobredeaux
481*9e965d6fSRomain Jobredeauxdef _get_library_r_jars(deps):
482*9e965d6fSRomain Jobredeaux    transitive_resource_jars = []
483*9e965d6fSRomain Jobredeaux    for dep in utils.collect_providers(AndroidLibraryResourceClassJarProvider, deps):
484*9e965d6fSRomain Jobredeaux        transitive_resource_jars += dep.jars.to_list()
485*9e965d6fSRomain Jobredeaux    return transitive_resource_jars
486*9e965d6fSRomain Jobredeaux
487*9e965d6fSRomain Jobredeauxdef _dex_merge(
488*9e965d6fSRomain Jobredeaux        ctx,
489*9e965d6fSRomain Jobredeaux        output = None,
490*9e965d6fSRomain Jobredeaux        inputs = [],
491*9e965d6fSRomain Jobredeaux        multidex_strategy = "minimal",
492*9e965d6fSRomain Jobredeaux        main_dex_list = None,
493*9e965d6fSRomain Jobredeaux        dexopts = [],
494*9e965d6fSRomain Jobredeaux        dexmerger = None,
495*9e965d6fSRomain Jobredeaux        toolchain_type = None):
496*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
497*9e965d6fSRomain Jobredeaux    args.add("--multidex", multidex_strategy)
498*9e965d6fSRomain Jobredeaux    args.add_all(inputs, before_each = "--input")
499*9e965d6fSRomain Jobredeaux    args.add("--output", output)
500*9e965d6fSRomain Jobredeaux    args.add_all(dexopts)
501*9e965d6fSRomain Jobredeaux
502*9e965d6fSRomain Jobredeaux    if main_dex_list:
503*9e965d6fSRomain Jobredeaux        inputs.append(main_dex_list)
504*9e965d6fSRomain Jobredeaux        args.add("--main-dex-list", main_dex_list)
505*9e965d6fSRomain Jobredeaux
506*9e965d6fSRomain Jobredeaux    ctx.actions.run(
507*9e965d6fSRomain Jobredeaux        executable = dexmerger,
508*9e965d6fSRomain Jobredeaux        arguments = [args],
509*9e965d6fSRomain Jobredeaux        inputs = inputs,
510*9e965d6fSRomain Jobredeaux        outputs = [output],
511*9e965d6fSRomain Jobredeaux        mnemonic = "DexMerger",
512*9e965d6fSRomain Jobredeaux        progress_message = "Assembling dex files into " + output.short_path,
513*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
514*9e965d6fSRomain Jobredeaux    )
515*9e965d6fSRomain Jobredeaux
516*9e965d6fSRomain Jobredeauxdef _merge_infos(infos):
517*9e965d6fSRomain Jobredeaux    dex_archives_dict = {}
518*9e965d6fSRomain Jobredeaux    for info in infos:
519*9e965d6fSRomain Jobredeaux        for dexopts in info.dex_archives_dict:
520*9e965d6fSRomain Jobredeaux            if dexopts not in dex_archives_dict:
521*9e965d6fSRomain Jobredeaux                dex_archives_dict[dexopts] = [info.dex_archives_dict[dexopts]]
522*9e965d6fSRomain Jobredeaux            else:
523*9e965d6fSRomain Jobredeaux                dex_archives_dict[dexopts].append(info.dex_archives_dict[dexopts])
524*9e965d6fSRomain Jobredeaux    return StarlarkAndroidDexInfo(
525*9e965d6fSRomain Jobredeaux        dex_archives_dict =
526*9e965d6fSRomain Jobredeaux            {dexopts: depset(direct = [], transitive = dex_archives) for dexopts, dex_archives in dex_archives_dict.items()},
527*9e965d6fSRomain Jobredeaux    )
528*9e965d6fSRomain Jobredeaux
529*9e965d6fSRomain Jobredeauxdef _filter_dexopts(tokenized_dexopts, includes):
530*9e965d6fSRomain Jobredeaux    return _normalize_dexopts(_filter(tokenized_dexopts, includes = includes))
531*9e965d6fSRomain Jobredeaux
532*9e965d6fSRomain Jobredeauxdef _filter(candidates, includes = [], excludes = []):
533*9e965d6fSRomain Jobredeaux    if excludes and includes:
534*9e965d6fSRomain Jobredeaux        fail("Only one of excludes list and includes list can be set.")
535*9e965d6fSRomain Jobredeaux    if includes:
536*9e965d6fSRomain Jobredeaux        return [c for c in candidates if c in includes]
537*9e965d6fSRomain Jobredeaux    if excludes:
538*9e965d6fSRomain Jobredeaux        return [c for c in candidates if c not in excludes]
539*9e965d6fSRomain Jobredeaux    return candidates
540*9e965d6fSRomain Jobredeaux
541*9e965d6fSRomain Jobredeauxdef _normalize_dexopts(tokenized_dexopts):
542*9e965d6fSRomain Jobredeaux    def _dx_to_dexbuilder(opt):
543*9e965d6fSRomain Jobredeaux        return opt.replace("--no-", "--no")
544*9e965d6fSRomain Jobredeaux
545*9e965d6fSRomain Jobredeaux    return collections.uniq(sorted([_dx_to_dexbuilder(token) for token in tokenized_dexopts]))
546*9e965d6fSRomain Jobredeaux
547*9e965d6fSRomain Jobredeauxdef _generate_main_dex_list(
548*9e965d6fSRomain Jobredeaux        ctx,
549*9e965d6fSRomain Jobredeaux        jar,
550*9e965d6fSRomain Jobredeaux        android_jar = None,
551*9e965d6fSRomain Jobredeaux        desugar_java8_libs = True,
552*9e965d6fSRomain Jobredeaux        main_dex_classes = None,
553*9e965d6fSRomain Jobredeaux        main_dex_list_opts = [],
554*9e965d6fSRomain Jobredeaux        main_dex_proguard_spec = None,
555*9e965d6fSRomain Jobredeaux        proguard_specs = [],
556*9e965d6fSRomain Jobredeaux        legacy_apis = [],
557*9e965d6fSRomain Jobredeaux        shrinked_android_jar = None,
558*9e965d6fSRomain Jobredeaux        toolchain_type = None,
559*9e965d6fSRomain Jobredeaux        main_dex_list_creator = None,
560*9e965d6fSRomain Jobredeaux        legacy_main_dex_list_generator = None,
561*9e965d6fSRomain Jobredeaux        proguard_tool = None):
562*9e965d6fSRomain Jobredeaux    main_dex_list = _get_dx_artifact(ctx, "main_dex_list.txt")
563*9e965d6fSRomain Jobredeaux    if not proguard_specs:
564*9e965d6fSRomain Jobredeaux        proguard_specs.append(main_dex_classes)
565*9e965d6fSRomain Jobredeaux    if main_dex_proguard_spec:
566*9e965d6fSRomain Jobredeaux        proguard_specs.append(main_dex_proguard_spec)
567*9e965d6fSRomain Jobredeaux
568*9e965d6fSRomain Jobredeaux    #  If legacy_main_dex_list_generator is not set by either the SDK or the flag, use ProGuard and
569*9e965d6fSRomain Jobredeaux    #  the main dext list creator specified by the android_sdk rule. If
570*9e965d6fSRomain Jobredeaux    #  legacy_main_dex_list_generator is provided, use that tool instead.
571*9e965d6fSRomain Jobredeaux    #  TODO(b/147692286): Remove the old main-dex list generation that relied on ProGuard.
572*9e965d6fSRomain Jobredeaux    if not legacy_main_dex_list_generator:
573*9e965d6fSRomain Jobredeaux        if not shrinked_android_jar:
574*9e965d6fSRomain Jobredeaux            fail("In \"legacy\" multidex mode, either legacy_main_dex_list_generator or " +
575*9e965d6fSRomain Jobredeaux                 "shrinked_android_jar must be set in the android_sdk.")
576*9e965d6fSRomain Jobredeaux
577*9e965d6fSRomain Jobredeaux        # Process the input jar through Proguard into an intermediate, streamlined jar.
578*9e965d6fSRomain Jobredeaux        stripped_jar = _get_dx_artifact(ctx, "main_dex_intermediate.jar")
579*9e965d6fSRomain Jobredeaux        args = ctx.actions.args()
580*9e965d6fSRomain Jobredeaux        args.add("-forceprocessing")
581*9e965d6fSRomain Jobredeaux        args.add("-injars", jar)
582*9e965d6fSRomain Jobredeaux        args.add("-libraryjars", shrinked_android_jar)
583*9e965d6fSRomain Jobredeaux        args.add("-outjars", stripped_jar)
584*9e965d6fSRomain Jobredeaux        args.add("-dontwarn")
585*9e965d6fSRomain Jobredeaux        args.add("-dontnote")
586*9e965d6fSRomain Jobredeaux        args.add("-dontoptimize")
587*9e965d6fSRomain Jobredeaux        args.add("-dontobfuscate")
588*9e965d6fSRomain Jobredeaux        ctx.actions.run(
589*9e965d6fSRomain Jobredeaux            outputs = [stripped_jar],
590*9e965d6fSRomain Jobredeaux            executable = proguard_tool,
591*9e965d6fSRomain Jobredeaux            args = [args],
592*9e965d6fSRomain Jobredeaux            inputs = [jar, shrinked_android_jar],
593*9e965d6fSRomain Jobredeaux            mnemonic = "MainDexClassesIntermediate",
594*9e965d6fSRomain Jobredeaux            progress_message = "Generating streamlined input jar for main dex classes list",
595*9e965d6fSRomain Jobredeaux            use_default_shell_dev = True,
596*9e965d6fSRomain Jobredeaux            toolchain = toolchain_type,
597*9e965d6fSRomain Jobredeaux        )
598*9e965d6fSRomain Jobredeaux
599*9e965d6fSRomain Jobredeaux        args = ctx.actions.args()
600*9e965d6fSRomain Jobredeaux        args.add_all([main_dex_list, stripped_jar, jar])
601*9e965d6fSRomain Jobredeaux        args.add_all(main_dex_list_opts)
602*9e965d6fSRomain Jobredeaux
603*9e965d6fSRomain Jobredeaux        ctx.actions.run(
604*9e965d6fSRomain Jobredeaux            outputs = [main_dex_list],
605*9e965d6fSRomain Jobredeaux            executable = main_dex_list_creator,
606*9e965d6fSRomain Jobredeaux            arguments = [args],
607*9e965d6fSRomain Jobredeaux            inputs = [jar, stripped_jar],
608*9e965d6fSRomain Jobredeaux            mnemonic = "MainDexClasses",
609*9e965d6fSRomain Jobredeaux            progress_message = "Generating main dex classes list",
610*9e965d6fSRomain Jobredeaux            toolchain = toolchain_type,
611*9e965d6fSRomain Jobredeaux        )
612*9e965d6fSRomain Jobredeaux    else:
613*9e965d6fSRomain Jobredeaux        inputs = [jar, android_jar] + proguard_specs
614*9e965d6fSRomain Jobredeaux
615*9e965d6fSRomain Jobredeaux        args = ctx.actions.args()
616*9e965d6fSRomain Jobredeaux        args.add("--main-dex-list-output", main_dex_list)
617*9e965d6fSRomain Jobredeaux        args.add("--lib", android_jar)
618*9e965d6fSRomain Jobredeaux        if desugar_java8_libs:
619*9e965d6fSRomain Jobredeaux            args.add_all(legacy_apis, before_each = "--lib")
620*9e965d6fSRomain Jobredeaux            inputs += legacy_apis
621*9e965d6fSRomain Jobredeaux        args.add_all(proguard_specs, before_each = "--main-dex-rules")
622*9e965d6fSRomain Jobredeaux        args.add(jar)
623*9e965d6fSRomain Jobredeaux        ctx.actions.run(
624*9e965d6fSRomain Jobredeaux            executable = legacy_main_dex_list_generator,
625*9e965d6fSRomain Jobredeaux            arguments = [args],
626*9e965d6fSRomain Jobredeaux            outputs = [main_dex_list],
627*9e965d6fSRomain Jobredeaux            inputs = inputs,
628*9e965d6fSRomain Jobredeaux            mnemonic = "MainDexClasses",
629*9e965d6fSRomain Jobredeaux            progress_message = "Generating main dex classes list",
630*9e965d6fSRomain Jobredeaux            toolchain = toolchain_type,
631*9e965d6fSRomain Jobredeaux        )
632*9e965d6fSRomain Jobredeaux    return main_dex_list
633*9e965d6fSRomain Jobredeaux
634*9e965d6fSRomain Jobredeauxdef _transform_dex_list_through_proguard_map(
635*9e965d6fSRomain Jobredeaux        ctx,
636*9e965d6fSRomain Jobredeaux        proguard_output_map = None,
637*9e965d6fSRomain Jobredeaux        main_dex_list = None,
638*9e965d6fSRomain Jobredeaux        toolchain_type = None,
639*9e965d6fSRomain Jobredeaux        dex_list_obfuscator = None):
640*9e965d6fSRomain Jobredeaux    if not proguard_output_map:
641*9e965d6fSRomain Jobredeaux        return main_dex_list
642*9e965d6fSRomain Jobredeaux
643*9e965d6fSRomain Jobredeaux    obfuscated_main_dex_list = _get_dx_artifact(ctx, "main_dex_list_obfuscated.txt")
644*9e965d6fSRomain Jobredeaux
645*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
646*9e965d6fSRomain Jobredeaux    args.add("--input", main_dex_list)
647*9e965d6fSRomain Jobredeaux    args.add("--output", obfuscated_main_dex_list)
648*9e965d6fSRomain Jobredeaux    args.add("--obfuscation_map", proguard_output_map)
649*9e965d6fSRomain Jobredeaux    ctx.actions.run(
650*9e965d6fSRomain Jobredeaux        executable = dex_list_obfuscator,
651*9e965d6fSRomain Jobredeaux        arguments = [args],
652*9e965d6fSRomain Jobredeaux        outputs = [obfuscated_main_dex_list],
653*9e965d6fSRomain Jobredeaux        inputs = [main_dex_list],
654*9e965d6fSRomain Jobredeaux        mnemonic = "MainDexProguardClasses",
655*9e965d6fSRomain Jobredeaux        progress_message = "Obfuscating main dex classes list",
656*9e965d6fSRomain Jobredeaux        toolchain = toolchain_type,
657*9e965d6fSRomain Jobredeaux    )
658*9e965d6fSRomain Jobredeaux
659*9e965d6fSRomain Jobredeaux    return obfuscated_main_dex_list
660*9e965d6fSRomain Jobredeaux
661*9e965d6fSRomain Jobredeauxdex = struct(
662*9e965d6fSRomain Jobredeaux    append_java8_legacy_dex = _append_java8_legacy_dex,
663*9e965d6fSRomain Jobredeaux    dex = _dex,
664*9e965d6fSRomain Jobredeaux    dex_merge = _dex_merge,
665*9e965d6fSRomain Jobredeaux    generate_main_dex_list = _generate_main_dex_list,
666*9e965d6fSRomain Jobredeaux    get_dx_artifact = _get_dx_artifact,
667*9e965d6fSRomain Jobredeaux    get_effective_incremental_dexing = _get_effective_incremental_dexing,
668*9e965d6fSRomain Jobredeaux    get_java8_legacy_dex_and_map = _get_java8_legacy_dex_and_map,
669*9e965d6fSRomain Jobredeaux    filter_dexopts = _filter_dexopts,
670*9e965d6fSRomain Jobredeaux    merge_infos = _merge_infos,
671*9e965d6fSRomain Jobredeaux    normalize_dexopts = _normalize_dexopts,
672*9e965d6fSRomain Jobredeaux    process_monolithic_dexing = _process_monolithic_dexing,
673*9e965d6fSRomain Jobredeaux    process_incremental_dexing = _process_incremental_dexing,
674*9e965d6fSRomain Jobredeaux    process_optimized_dexing = _process_optimized_dexing,
675*9e965d6fSRomain Jobredeaux    transform_dex_list_through_proguard_map = _transform_dex_list_through_proguard_map,
676*9e965d6fSRomain Jobredeaux)
677