xref: /aosp_15_r20/external/angle/build/android/gyp/dex.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*8975f5c5SAndroid Build Coastguard Worker#
3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2013 The Chromium Authors
4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file.
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Workerimport argparse
8*8975f5c5SAndroid Build Coastguard Workerimport collections
9*8975f5c5SAndroid Build Coastguard Workerimport logging
10*8975f5c5SAndroid Build Coastguard Workerimport os
11*8975f5c5SAndroid Build Coastguard Workerimport re
12*8975f5c5SAndroid Build Coastguard Workerimport shutil
13*8975f5c5SAndroid Build Coastguard Workerimport shlex
14*8975f5c5SAndroid Build Coastguard Workerimport sys
15*8975f5c5SAndroid Build Coastguard Workerimport tempfile
16*8975f5c5SAndroid Build Coastguard Workerimport zipfile
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Workerfrom util import build_utils
19*8975f5c5SAndroid Build Coastguard Workerfrom util import md5_check
20*8975f5c5SAndroid Build Coastguard Workerimport action_helpers  # build_utils adds //build to sys.path.
21*8975f5c5SAndroid Build Coastguard Workerimport zip_helpers
22*8975f5c5SAndroid Build Coastguard Worker
23*8975f5c5SAndroid Build Coastguard Worker
24*8975f5c5SAndroid Build Coastguard Worker_DEX_XMX = '2G'  # Increase this when __final_dex OOMs.
25*8975f5c5SAndroid Build Coastguard Worker
26*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_IGNORE_WARNINGS = (
27*8975f5c5SAndroid Build Coastguard Worker    # Warning: Running R8 version main (build engineering), which cannot be
28*8975f5c5SAndroid Build Coastguard Worker    # represented as a semantic version. Using an artificial version newer than
29*8975f5c5SAndroid Build Coastguard Worker    # any known version for selecting Proguard configurations embedded under
30*8975f5c5SAndroid Build Coastguard Worker    # META-INF/. This means that all rules with a '-upto-' qualifier will be
31*8975f5c5SAndroid Build Coastguard Worker    # excluded and all rules with a -from- qualifier will be included.
32*8975f5c5SAndroid Build Coastguard Worker    r'Running R8 version main', )
33*8975f5c5SAndroid Build Coastguard Worker
34*8975f5c5SAndroid Build Coastguard Worker_IGNORE_SERVICE_ENTRIES = (
35*8975f5c5SAndroid Build Coastguard Worker    # ServiceLoader call is used only for ProtoBuf full (non-lite).
36*8975f5c5SAndroid Build Coastguard Worker    # BaseGeneratedExtensionRegistryLite$Loader conflicts with
37*8975f5c5SAndroid Build Coastguard Worker    # ChromeGeneratedExtensionRegistryLite$Loader.
38*8975f5c5SAndroid Build Coastguard Worker    'META-INF/services/com.google.protobuf.GeneratedExtensionRegistryLoader',
39*8975f5c5SAndroid Build Coastguard Worker    # Uses ServiceLoader to find all implementing classes, so multiple are
40*8975f5c5SAndroid Build Coastguard Worker    # expected.
41*8975f5c5SAndroid Build Coastguard Worker    'META-INF/services/androidx.appsearch.app.AppSearchDocumentClassMap',
42*8975f5c5SAndroid Build Coastguard Worker)
43*8975f5c5SAndroid Build Coastguard Worker
44*8975f5c5SAndroid Build Coastguard WorkerINTERFACE_DESUGARING_WARNINGS = (r'default or static interface methods', )
45*8975f5c5SAndroid Build Coastguard Worker
46*8975f5c5SAndroid Build Coastguard Worker_SKIPPED_CLASS_FILE_NAMES = (
47*8975f5c5SAndroid Build Coastguard Worker    'module-info.class',  # Explicitly skipped by r8/utils/FileUtils#isClassFile
48*8975f5c5SAndroid Build Coastguard Worker)
49*8975f5c5SAndroid Build Coastguard Worker
50*8975f5c5SAndroid Build Coastguard Worker
51*8975f5c5SAndroid Build Coastguard Workerdef _ParseArgs(args):
52*8975f5c5SAndroid Build Coastguard Worker  args = build_utils.ExpandFileArgs(args)
53*8975f5c5SAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
54*8975f5c5SAndroid Build Coastguard Worker
55*8975f5c5SAndroid Build Coastguard Worker  action_helpers.add_depfile_arg(parser)
56*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--output', required=True, help='Dex output path.')
57*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
58*8975f5c5SAndroid Build Coastguard Worker      '--class-inputs',
59*8975f5c5SAndroid Build Coastguard Worker      action='append',
60*8975f5c5SAndroid Build Coastguard Worker      help='GN-list of .jars with .class files.')
61*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
62*8975f5c5SAndroid Build Coastguard Worker      '--class-inputs-filearg',
63*8975f5c5SAndroid Build Coastguard Worker      action='append',
64*8975f5c5SAndroid Build Coastguard Worker      help='GN-list of .jars with .class files (added to depfile).')
65*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
66*8975f5c5SAndroid Build Coastguard Worker      '--dex-inputs', action='append', help='GN-list of .jars with .dex files.')
67*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
68*8975f5c5SAndroid Build Coastguard Worker      '--dex-inputs-filearg',
69*8975f5c5SAndroid Build Coastguard Worker      action='append',
70*8975f5c5SAndroid Build Coastguard Worker      help='GN-list of .jars with .dex files (added to depfile).')
71*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
72*8975f5c5SAndroid Build Coastguard Worker      '--incremental-dir',
73*8975f5c5SAndroid Build Coastguard Worker      help='Path of directory to put intermediate dex files.')
74*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--library',
75*8975f5c5SAndroid Build Coastguard Worker                      action='store_true',
76*8975f5c5SAndroid Build Coastguard Worker                      help='Allow numerous dex files within output.')
77*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--r8-jar-path', required=True, help='Path to R8 jar.')
78*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--skip-custom-d8',
79*8975f5c5SAndroid Build Coastguard Worker                      action='store_true',
80*8975f5c5SAndroid Build Coastguard Worker                      help='When rebuilding the CustomD8 jar, this may be '
81*8975f5c5SAndroid Build Coastguard Worker                      'necessary to avoid incompatibility with the new r8 '
82*8975f5c5SAndroid Build Coastguard Worker                      'jar.')
83*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--custom-d8-jar-path',
84*8975f5c5SAndroid Build Coastguard Worker                      required=True,
85*8975f5c5SAndroid Build Coastguard Worker                      help='Path to our customized d8 jar.')
86*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--desugar-dependencies',
87*8975f5c5SAndroid Build Coastguard Worker                      help='Path to store desugar dependencies.')
88*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--desugar', action='store_true')
89*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
90*8975f5c5SAndroid Build Coastguard Worker      '--bootclasspath',
91*8975f5c5SAndroid Build Coastguard Worker      action='append',
92*8975f5c5SAndroid Build Coastguard Worker      help='GN-list of bootclasspath. Needed for --desugar')
93*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--show-desugar-default-interface-warnings',
94*8975f5c5SAndroid Build Coastguard Worker                      action='store_true',
95*8975f5c5SAndroid Build Coastguard Worker                      help='Enable desugaring warnings.')
96*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
97*8975f5c5SAndroid Build Coastguard Worker      '--classpath',
98*8975f5c5SAndroid Build Coastguard Worker      action='append',
99*8975f5c5SAndroid Build Coastguard Worker      help='GN-list of full classpath. Needed for --desugar')
100*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--release',
101*8975f5c5SAndroid Build Coastguard Worker                      action='store_true',
102*8975f5c5SAndroid Build Coastguard Worker                      help='Run D8 in release mode.')
103*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
104*8975f5c5SAndroid Build Coastguard Worker      '--min-api', help='Minimum Android API level compatibility.')
105*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--force-enable-assertions',
106*8975f5c5SAndroid Build Coastguard Worker                      action='store_true',
107*8975f5c5SAndroid Build Coastguard Worker                      help='Forcefully enable javac generated assertion code.')
108*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--assertion-handler',
109*8975f5c5SAndroid Build Coastguard Worker                      help='The class name of the assertion handler class.')
110*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--warnings-as-errors',
111*8975f5c5SAndroid Build Coastguard Worker                      action='store_true',
112*8975f5c5SAndroid Build Coastguard Worker                      help='Treat all warnings as errors.')
113*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--dump-inputs',
114*8975f5c5SAndroid Build Coastguard Worker                      action='store_true',
115*8975f5c5SAndroid Build Coastguard Worker                      help='Use when filing D8 bugs to capture inputs.'
116*8975f5c5SAndroid Build Coastguard Worker                      ' Stores inputs to d8inputs.zip')
117*8975f5c5SAndroid Build Coastguard Worker  options = parser.parse_args(args)
118*8975f5c5SAndroid Build Coastguard Worker
119*8975f5c5SAndroid Build Coastguard Worker  if options.force_enable_assertions and options.assertion_handler:
120*8975f5c5SAndroid Build Coastguard Worker    parser.error('Cannot use both --force-enable-assertions and '
121*8975f5c5SAndroid Build Coastguard Worker                 '--assertion-handler')
122*8975f5c5SAndroid Build Coastguard Worker
123*8975f5c5SAndroid Build Coastguard Worker  options.class_inputs = action_helpers.parse_gn_list(options.class_inputs)
124*8975f5c5SAndroid Build Coastguard Worker  options.class_inputs_filearg = action_helpers.parse_gn_list(
125*8975f5c5SAndroid Build Coastguard Worker      options.class_inputs_filearg)
126*8975f5c5SAndroid Build Coastguard Worker  options.bootclasspath = action_helpers.parse_gn_list(options.bootclasspath)
127*8975f5c5SAndroid Build Coastguard Worker  options.classpath = action_helpers.parse_gn_list(options.classpath)
128*8975f5c5SAndroid Build Coastguard Worker  options.dex_inputs = action_helpers.parse_gn_list(options.dex_inputs)
129*8975f5c5SAndroid Build Coastguard Worker  options.dex_inputs_filearg = action_helpers.parse_gn_list(
130*8975f5c5SAndroid Build Coastguard Worker      options.dex_inputs_filearg)
131*8975f5c5SAndroid Build Coastguard Worker
132*8975f5c5SAndroid Build Coastguard Worker  return options
133*8975f5c5SAndroid Build Coastguard Worker
134*8975f5c5SAndroid Build Coastguard Worker
135*8975f5c5SAndroid Build Coastguard Workerdef CreateStderrFilter(filters):
136*8975f5c5SAndroid Build Coastguard Worker  def filter_stderr(output):
137*8975f5c5SAndroid Build Coastguard Worker    # Set this when debugging R8 output.
138*8975f5c5SAndroid Build Coastguard Worker    if os.environ.get('R8_SHOW_ALL_OUTPUT', '0') != '0':
139*8975f5c5SAndroid Build Coastguard Worker      return output
140*8975f5c5SAndroid Build Coastguard Worker
141*8975f5c5SAndroid Build Coastguard Worker    # All missing definitions are logged as a single warning, but start on a
142*8975f5c5SAndroid Build Coastguard Worker    # new line like "Missing class ...".
143*8975f5c5SAndroid Build Coastguard Worker    warnings = re.split(r'^(?=Warning|Error|Missing (?:class|field|method))',
144*8975f5c5SAndroid Build Coastguard Worker                        output,
145*8975f5c5SAndroid Build Coastguard Worker                        flags=re.MULTILINE)
146*8975f5c5SAndroid Build Coastguard Worker    preamble, *warnings = warnings
147*8975f5c5SAndroid Build Coastguard Worker
148*8975f5c5SAndroid Build Coastguard Worker    combined_pattern = '|'.join(filters)
149*8975f5c5SAndroid Build Coastguard Worker    preamble = build_utils.FilterLines(preamble, combined_pattern)
150*8975f5c5SAndroid Build Coastguard Worker
151*8975f5c5SAndroid Build Coastguard Worker    compiled_re = re.compile(combined_pattern, re.DOTALL)
152*8975f5c5SAndroid Build Coastguard Worker    warnings = [w for w in warnings if not compiled_re.search(w)]
153*8975f5c5SAndroid Build Coastguard Worker
154*8975f5c5SAndroid Build Coastguard Worker    return preamble + ''.join(warnings)
155*8975f5c5SAndroid Build Coastguard Worker
156*8975f5c5SAndroid Build Coastguard Worker  return filter_stderr
157*8975f5c5SAndroid Build Coastguard Worker
158*8975f5c5SAndroid Build Coastguard Worker
159*8975f5c5SAndroid Build Coastguard Workerdef _RunD8(dex_cmd, input_paths, output_path, warnings_as_errors,
160*8975f5c5SAndroid Build Coastguard Worker           show_desugar_default_interface_warnings):
161*8975f5c5SAndroid Build Coastguard Worker  dex_cmd = dex_cmd + ['--output', output_path] + input_paths
162*8975f5c5SAndroid Build Coastguard Worker
163*8975f5c5SAndroid Build Coastguard Worker  # Missing deps can happen for prebuilts that are missing transitive deps
164*8975f5c5SAndroid Build Coastguard Worker  # and have set enable_bytecode_checks=false.
165*8975f5c5SAndroid Build Coastguard Worker  filters = list(DEFAULT_IGNORE_WARNINGS)
166*8975f5c5SAndroid Build Coastguard Worker  if not show_desugar_default_interface_warnings:
167*8975f5c5SAndroid Build Coastguard Worker    filters += INTERFACE_DESUGARING_WARNINGS
168*8975f5c5SAndroid Build Coastguard Worker
169*8975f5c5SAndroid Build Coastguard Worker  stderr_filter = CreateStderrFilter(filters)
170*8975f5c5SAndroid Build Coastguard Worker
171*8975f5c5SAndroid Build Coastguard Worker  is_debug = logging.getLogger().isEnabledFor(logging.DEBUG)
172*8975f5c5SAndroid Build Coastguard Worker
173*8975f5c5SAndroid Build Coastguard Worker  # Avoid deleting the flag file when DEX_DEBUG is set in case the flag file
174*8975f5c5SAndroid Build Coastguard Worker  # needs to be examined after the build.
175*8975f5c5SAndroid Build Coastguard Worker  with tempfile.NamedTemporaryFile(mode='w', delete=not is_debug) as flag_file:
176*8975f5c5SAndroid Build Coastguard Worker    # Chosen arbitrarily. Needed to avoid command-line length limits.
177*8975f5c5SAndroid Build Coastguard Worker    MAX_ARGS = 50
178*8975f5c5SAndroid Build Coastguard Worker    orig_dex_cmd = dex_cmd
179*8975f5c5SAndroid Build Coastguard Worker    if len(dex_cmd) > MAX_ARGS:
180*8975f5c5SAndroid Build Coastguard Worker      # Add all flags to D8 (anything after the first --) as well as all
181*8975f5c5SAndroid Build Coastguard Worker      # positional args at the end to the flag file.
182*8975f5c5SAndroid Build Coastguard Worker      for idx, cmd in enumerate(dex_cmd):
183*8975f5c5SAndroid Build Coastguard Worker        if cmd.startswith('--'):
184*8975f5c5SAndroid Build Coastguard Worker          flag_file.write('\n'.join(dex_cmd[idx:]))
185*8975f5c5SAndroid Build Coastguard Worker          flag_file.flush()
186*8975f5c5SAndroid Build Coastguard Worker          dex_cmd = dex_cmd[:idx]
187*8975f5c5SAndroid Build Coastguard Worker          dex_cmd.append('@' + flag_file.name)
188*8975f5c5SAndroid Build Coastguard Worker          break
189*8975f5c5SAndroid Build Coastguard Worker
190*8975f5c5SAndroid Build Coastguard Worker    # stdout sometimes spams with things like:
191*8975f5c5SAndroid Build Coastguard Worker    # Stripped invalid locals information from 1 method.
192*8975f5c5SAndroid Build Coastguard Worker    try:
193*8975f5c5SAndroid Build Coastguard Worker      build_utils.CheckOutput(dex_cmd,
194*8975f5c5SAndroid Build Coastguard Worker                              stderr_filter=stderr_filter,
195*8975f5c5SAndroid Build Coastguard Worker                              fail_on_output=warnings_as_errors)
196*8975f5c5SAndroid Build Coastguard Worker    except Exception as e:
197*8975f5c5SAndroid Build Coastguard Worker      if isinstance(e, build_utils.CalledProcessError):
198*8975f5c5SAndroid Build Coastguard Worker        output = e.output  # pylint: disable=no-member
199*8975f5c5SAndroid Build Coastguard Worker        if "global synthetic for 'Record desugaring'" in output:
200*8975f5c5SAndroid Build Coastguard Worker          sys.stderr.write('Java records are not supported.\n')
201*8975f5c5SAndroid Build Coastguard Worker          sys.stderr.write(
202*8975f5c5SAndroid Build Coastguard Worker              'See https://chromium.googlesource.com/chromium/src/+/' +
203*8975f5c5SAndroid Build Coastguard Worker              'main/styleguide/java/java.md#Records\n')
204*8975f5c5SAndroid Build Coastguard Worker          sys.exit(1)
205*8975f5c5SAndroid Build Coastguard Worker      if orig_dex_cmd is not dex_cmd:
206*8975f5c5SAndroid Build Coastguard Worker        sys.stderr.write('Full command: ' + shlex.join(orig_dex_cmd) + '\n')
207*8975f5c5SAndroid Build Coastguard Worker      raise
208*8975f5c5SAndroid Build Coastguard Worker
209*8975f5c5SAndroid Build Coastguard Worker
210*8975f5c5SAndroid Build Coastguard Workerdef _ZipAligned(dex_files, output_path, services_map):
211*8975f5c5SAndroid Build Coastguard Worker  """Creates a .dex.jar with 4-byte aligned files.
212*8975f5c5SAndroid Build Coastguard Worker
213*8975f5c5SAndroid Build Coastguard Worker  Args:
214*8975f5c5SAndroid Build Coastguard Worker    dex_files: List of dex files.
215*8975f5c5SAndroid Build Coastguard Worker    output_path: The output file in which to write the zip.
216*8975f5c5SAndroid Build Coastguard Worker    services_map: map of path->data for META-INF/services
217*8975f5c5SAndroid Build Coastguard Worker  """
218*8975f5c5SAndroid Build Coastguard Worker  with zipfile.ZipFile(output_path, 'w') as z:
219*8975f5c5SAndroid Build Coastguard Worker    for i, dex_file in enumerate(dex_files):
220*8975f5c5SAndroid Build Coastguard Worker      name = 'classes{}.dex'.format(i + 1 if i > 0 else '')
221*8975f5c5SAndroid Build Coastguard Worker      zip_helpers.add_to_zip_hermetic(z, name, src_path=dex_file, alignment=4)
222*8975f5c5SAndroid Build Coastguard Worker    for path, data in sorted(services_map.items()):
223*8975f5c5SAndroid Build Coastguard Worker      zip_helpers.add_to_zip_hermetic(z, path, data=data, alignment=4)
224*8975f5c5SAndroid Build Coastguard Worker
225*8975f5c5SAndroid Build Coastguard Worker
226*8975f5c5SAndroid Build Coastguard Workerdef _CreateServicesMap(service_jars):
227*8975f5c5SAndroid Build Coastguard Worker  ret = {}
228*8975f5c5SAndroid Build Coastguard Worker  origins = {}
229*8975f5c5SAndroid Build Coastguard Worker  for jar_path in service_jars:
230*8975f5c5SAndroid Build Coastguard Worker    with zipfile.ZipFile(jar_path, 'r') as z:
231*8975f5c5SAndroid Build Coastguard Worker      for n in z.namelist():
232*8975f5c5SAndroid Build Coastguard Worker        if n.startswith('META-INF/services/') and not n.endswith('/'):
233*8975f5c5SAndroid Build Coastguard Worker          if n in _IGNORE_SERVICE_ENTRIES:
234*8975f5c5SAndroid Build Coastguard Worker            continue
235*8975f5c5SAndroid Build Coastguard Worker          data = z.read(n)
236*8975f5c5SAndroid Build Coastguard Worker          if ret.get(n, data) == data:
237*8975f5c5SAndroid Build Coastguard Worker            ret[n] = data
238*8975f5c5SAndroid Build Coastguard Worker            origins[n] = jar_path
239*8975f5c5SAndroid Build Coastguard Worker          else:
240*8975f5c5SAndroid Build Coastguard Worker            # We should arguably just concat the files here, but Chrome's own
241*8975f5c5SAndroid Build Coastguard Worker            # uses (via ServiceLoaderUtil) all assume only one entry.
242*8975f5c5SAndroid Build Coastguard Worker            raise Exception(f"""\
243*8975f5c5SAndroid Build Coastguard WorkerConflicting contents for: {n}
244*8975f5c5SAndroid Build Coastguard Worker{origins[n]}:
245*8975f5c5SAndroid Build Coastguard Worker{ret[n]}
246*8975f5c5SAndroid Build Coastguard Worker{jar_path}:
247*8975f5c5SAndroid Build Coastguard Worker{data}
248*8975f5c5SAndroid Build Coastguard Worker
249*8975f5c5SAndroid Build Coastguard WorkerIf this entry can be safely ignored (because the ServiceLoader.load() call is \
250*8975f5c5SAndroid Build Coastguard Workernever hit), update _IGNORE_SERVICE_ENTRIES in dex.py.
251*8975f5c5SAndroid Build Coastguard Worker""")
252*8975f5c5SAndroid Build Coastguard Worker  return ret
253*8975f5c5SAndroid Build Coastguard Worker
254*8975f5c5SAndroid Build Coastguard Worker
255*8975f5c5SAndroid Build Coastguard Workerdef _CreateFinalDex(d8_inputs,
256*8975f5c5SAndroid Build Coastguard Worker                    output,
257*8975f5c5SAndroid Build Coastguard Worker                    tmp_dir,
258*8975f5c5SAndroid Build Coastguard Worker                    dex_cmd,
259*8975f5c5SAndroid Build Coastguard Worker                    options=None,
260*8975f5c5SAndroid Build Coastguard Worker                    service_jars=None):
261*8975f5c5SAndroid Build Coastguard Worker  tmp_dex_output = os.path.join(tmp_dir, 'tmp_dex_output.zip')
262*8975f5c5SAndroid Build Coastguard Worker  needs_dexing = not all(f.endswith('.dex') for f in d8_inputs)
263*8975f5c5SAndroid Build Coastguard Worker  needs_dexmerge = output.endswith('.dex') or not (options and options.library)
264*8975f5c5SAndroid Build Coastguard Worker  services_map = _CreateServicesMap(service_jars or [])
265*8975f5c5SAndroid Build Coastguard Worker  if needs_dexing or needs_dexmerge:
266*8975f5c5SAndroid Build Coastguard Worker    tmp_dex_dir = os.path.join(tmp_dir, 'tmp_dex_dir')
267*8975f5c5SAndroid Build Coastguard Worker    os.mkdir(tmp_dex_dir)
268*8975f5c5SAndroid Build Coastguard Worker
269*8975f5c5SAndroid Build Coastguard Worker    _RunD8(dex_cmd, d8_inputs, tmp_dex_dir,
270*8975f5c5SAndroid Build Coastguard Worker           (not options or options.warnings_as_errors),
271*8975f5c5SAndroid Build Coastguard Worker           (options and options.show_desugar_default_interface_warnings))
272*8975f5c5SAndroid Build Coastguard Worker    logging.debug('Performed dex merging')
273*8975f5c5SAndroid Build Coastguard Worker
274*8975f5c5SAndroid Build Coastguard Worker    dex_files = [os.path.join(tmp_dex_dir, f) for f in os.listdir(tmp_dex_dir)]
275*8975f5c5SAndroid Build Coastguard Worker
276*8975f5c5SAndroid Build Coastguard Worker    if output.endswith('.dex'):
277*8975f5c5SAndroid Build Coastguard Worker      if len(dex_files) > 1:
278*8975f5c5SAndroid Build Coastguard Worker        raise Exception('%d files created, expected 1' % len(dex_files))
279*8975f5c5SAndroid Build Coastguard Worker      tmp_dex_output = dex_files[0]
280*8975f5c5SAndroid Build Coastguard Worker    else:
281*8975f5c5SAndroid Build Coastguard Worker      _ZipAligned(sorted(dex_files), tmp_dex_output, services_map)
282*8975f5c5SAndroid Build Coastguard Worker  else:
283*8975f5c5SAndroid Build Coastguard Worker    # Skip dexmerger. Just put all incrementals into the .jar individually.
284*8975f5c5SAndroid Build Coastguard Worker    _ZipAligned(sorted(d8_inputs), tmp_dex_output, services_map)
285*8975f5c5SAndroid Build Coastguard Worker    logging.debug('Quick-zipped %d files', len(d8_inputs))
286*8975f5c5SAndroid Build Coastguard Worker
287*8975f5c5SAndroid Build Coastguard Worker  # The dex file is complete and can be moved out of tmp_dir.
288*8975f5c5SAndroid Build Coastguard Worker  shutil.move(tmp_dex_output, output)
289*8975f5c5SAndroid Build Coastguard Worker
290*8975f5c5SAndroid Build Coastguard Worker
291*8975f5c5SAndroid Build Coastguard Workerdef _IntermediateDexFilePathsFromInputJars(class_inputs, incremental_dir):
292*8975f5c5SAndroid Build Coastguard Worker  """Returns list of intermediate dex file paths, .jar files with services."""
293*8975f5c5SAndroid Build Coastguard Worker  dex_files = []
294*8975f5c5SAndroid Build Coastguard Worker  service_jars = set()
295*8975f5c5SAndroid Build Coastguard Worker  for jar in class_inputs:
296*8975f5c5SAndroid Build Coastguard Worker    with zipfile.ZipFile(jar, 'r') as z:
297*8975f5c5SAndroid Build Coastguard Worker      for subpath in z.namelist():
298*8975f5c5SAndroid Build Coastguard Worker        if _IsClassFile(subpath):
299*8975f5c5SAndroid Build Coastguard Worker          subpath = subpath[:-5] + 'dex'
300*8975f5c5SAndroid Build Coastguard Worker          dex_files.append(os.path.join(incremental_dir, subpath))
301*8975f5c5SAndroid Build Coastguard Worker        elif subpath.startswith('META-INF/services/'):
302*8975f5c5SAndroid Build Coastguard Worker          service_jars.add(jar)
303*8975f5c5SAndroid Build Coastguard Worker  return dex_files, sorted(service_jars)
304*8975f5c5SAndroid Build Coastguard Worker
305*8975f5c5SAndroid Build Coastguard Worker
306*8975f5c5SAndroid Build Coastguard Workerdef _DeleteStaleIncrementalDexFiles(dex_dir, dex_files):
307*8975f5c5SAndroid Build Coastguard Worker  """Deletes intermediate .dex files that are no longer needed."""
308*8975f5c5SAndroid Build Coastguard Worker  all_files = build_utils.FindInDirectory(dex_dir)
309*8975f5c5SAndroid Build Coastguard Worker  desired_files = set(dex_files)
310*8975f5c5SAndroid Build Coastguard Worker  for path in all_files:
311*8975f5c5SAndroid Build Coastguard Worker    if path not in desired_files:
312*8975f5c5SAndroid Build Coastguard Worker      os.unlink(path)
313*8975f5c5SAndroid Build Coastguard Worker
314*8975f5c5SAndroid Build Coastguard Worker
315*8975f5c5SAndroid Build Coastguard Workerdef _ParseDesugarDeps(desugar_dependencies_file):
316*8975f5c5SAndroid Build Coastguard Worker  # pylint: disable=line-too-long
317*8975f5c5SAndroid Build Coastguard Worker  """Returns a dict of dependent/dependency mapping parsed from the file.
318*8975f5c5SAndroid Build Coastguard Worker
319*8975f5c5SAndroid Build Coastguard Worker  Example file format:
320*8975f5c5SAndroid Build Coastguard Worker  $ tail out/Debug/gen/base/base_java__dex.desugardeps
321*8975f5c5SAndroid Build Coastguard Worker  org/chromium/base/task/SingleThreadTaskRunnerImpl.class
322*8975f5c5SAndroid Build Coastguard Worker    <-  org/chromium/base/task/SingleThreadTaskRunner.class
323*8975f5c5SAndroid Build Coastguard Worker    <-  org/chromium/base/task/TaskRunnerImpl.class
324*8975f5c5SAndroid Build Coastguard Worker  org/chromium/base/task/TaskRunnerImpl.class
325*8975f5c5SAndroid Build Coastguard Worker    <-  org/chromium/base/task/TaskRunner.class
326*8975f5c5SAndroid Build Coastguard Worker  org/chromium/base/task/TaskRunnerImplJni$1.class
327*8975f5c5SAndroid Build Coastguard Worker    <-  obj/base/jni_java.turbine.jar:org/jni_zero/JniStaticTestMocker.class
328*8975f5c5SAndroid Build Coastguard Worker  org/chromium/base/task/TaskRunnerImplJni.class
329*8975f5c5SAndroid Build Coastguard Worker    <-  org/chromium/base/task/TaskRunnerImpl$Natives.class
330*8975f5c5SAndroid Build Coastguard Worker  """
331*8975f5c5SAndroid Build Coastguard Worker  # pylint: enable=line-too-long
332*8975f5c5SAndroid Build Coastguard Worker  dependents_from_dependency = collections.defaultdict(set)
333*8975f5c5SAndroid Build Coastguard Worker  if desugar_dependencies_file and os.path.exists(desugar_dependencies_file):
334*8975f5c5SAndroid Build Coastguard Worker    with open(desugar_dependencies_file, 'r') as f:
335*8975f5c5SAndroid Build Coastguard Worker      dependent = None
336*8975f5c5SAndroid Build Coastguard Worker      for line in f:
337*8975f5c5SAndroid Build Coastguard Worker        line = line.rstrip()
338*8975f5c5SAndroid Build Coastguard Worker        if line.startswith('  <-  '):
339*8975f5c5SAndroid Build Coastguard Worker          dependency = line[len('  <-  '):]
340*8975f5c5SAndroid Build Coastguard Worker          # Note that this is a reversed mapping from the one in CustomD8.java.
341*8975f5c5SAndroid Build Coastguard Worker          dependents_from_dependency[dependency].add(dependent)
342*8975f5c5SAndroid Build Coastguard Worker        else:
343*8975f5c5SAndroid Build Coastguard Worker          dependent = line
344*8975f5c5SAndroid Build Coastguard Worker  return dependents_from_dependency
345*8975f5c5SAndroid Build Coastguard Worker
346*8975f5c5SAndroid Build Coastguard Worker
347*8975f5c5SAndroid Build Coastguard Workerdef _ComputeRequiredDesugarClasses(changes, desugar_dependencies_file,
348*8975f5c5SAndroid Build Coastguard Worker                                   class_inputs, classpath):
349*8975f5c5SAndroid Build Coastguard Worker  dependents_from_dependency = _ParseDesugarDeps(desugar_dependencies_file)
350*8975f5c5SAndroid Build Coastguard Worker  required_classes = set()
351*8975f5c5SAndroid Build Coastguard Worker  # Gather classes that need to be re-desugared from changes in the classpath.
352*8975f5c5SAndroid Build Coastguard Worker  for jar in classpath:
353*8975f5c5SAndroid Build Coastguard Worker    for subpath in changes.IterChangedSubpaths(jar):
354*8975f5c5SAndroid Build Coastguard Worker      dependency = '{}:{}'.format(jar, subpath)
355*8975f5c5SAndroid Build Coastguard Worker      required_classes.update(dependents_from_dependency[dependency])
356*8975f5c5SAndroid Build Coastguard Worker
357*8975f5c5SAndroid Build Coastguard Worker  for jar in class_inputs:
358*8975f5c5SAndroid Build Coastguard Worker    for subpath in changes.IterChangedSubpaths(jar):
359*8975f5c5SAndroid Build Coastguard Worker      required_classes.update(dependents_from_dependency[subpath])
360*8975f5c5SAndroid Build Coastguard Worker
361*8975f5c5SAndroid Build Coastguard Worker  return required_classes
362*8975f5c5SAndroid Build Coastguard Worker
363*8975f5c5SAndroid Build Coastguard Worker
364*8975f5c5SAndroid Build Coastguard Workerdef _IsClassFile(path):
365*8975f5c5SAndroid Build Coastguard Worker  if os.path.basename(path) in _SKIPPED_CLASS_FILE_NAMES:
366*8975f5c5SAndroid Build Coastguard Worker    return False
367*8975f5c5SAndroid Build Coastguard Worker  return path.endswith('.class')
368*8975f5c5SAndroid Build Coastguard Worker
369*8975f5c5SAndroid Build Coastguard Worker
370*8975f5c5SAndroid Build Coastguard Workerdef _ExtractClassFiles(changes, tmp_dir, class_inputs, required_classes_set):
371*8975f5c5SAndroid Build Coastguard Worker  classes_list = []
372*8975f5c5SAndroid Build Coastguard Worker  for jar in class_inputs:
373*8975f5c5SAndroid Build Coastguard Worker    if changes:
374*8975f5c5SAndroid Build Coastguard Worker      changed_class_list = (set(changes.IterChangedSubpaths(jar))
375*8975f5c5SAndroid Build Coastguard Worker                            | required_classes_set)
376*8975f5c5SAndroid Build Coastguard Worker      predicate = lambda x: x in changed_class_list and _IsClassFile(x)
377*8975f5c5SAndroid Build Coastguard Worker    else:
378*8975f5c5SAndroid Build Coastguard Worker      predicate = _IsClassFile
379*8975f5c5SAndroid Build Coastguard Worker
380*8975f5c5SAndroid Build Coastguard Worker    classes_list.extend(
381*8975f5c5SAndroid Build Coastguard Worker        build_utils.ExtractAll(jar, path=tmp_dir, predicate=predicate))
382*8975f5c5SAndroid Build Coastguard Worker  return classes_list
383*8975f5c5SAndroid Build Coastguard Worker
384*8975f5c5SAndroid Build Coastguard Worker
385*8975f5c5SAndroid Build Coastguard Workerdef _CreateIntermediateDexFiles(changes, options, tmp_dir, dex_cmd):
386*8975f5c5SAndroid Build Coastguard Worker  # Create temporary directory for classes to be extracted to.
387*8975f5c5SAndroid Build Coastguard Worker  tmp_extract_dir = os.path.join(tmp_dir, 'tmp_extract_dir')
388*8975f5c5SAndroid Build Coastguard Worker  os.mkdir(tmp_extract_dir)
389*8975f5c5SAndroid Build Coastguard Worker
390*8975f5c5SAndroid Build Coastguard Worker  # Do a full rebuild when changes occur in non-input files.
391*8975f5c5SAndroid Build Coastguard Worker  allowed_changed = set(options.class_inputs)
392*8975f5c5SAndroid Build Coastguard Worker  allowed_changed.update(options.dex_inputs)
393*8975f5c5SAndroid Build Coastguard Worker  allowed_changed.update(options.classpath)
394*8975f5c5SAndroid Build Coastguard Worker  strings_changed = changes.HasStringChanges()
395*8975f5c5SAndroid Build Coastguard Worker  non_direct_input_changed = next(
396*8975f5c5SAndroid Build Coastguard Worker      (p for p in changes.IterChangedPaths() if p not in allowed_changed), None)
397*8975f5c5SAndroid Build Coastguard Worker
398*8975f5c5SAndroid Build Coastguard Worker  if strings_changed or non_direct_input_changed:
399*8975f5c5SAndroid Build Coastguard Worker    logging.debug('Full dex required: strings_changed=%s path_changed=%s',
400*8975f5c5SAndroid Build Coastguard Worker                  strings_changed, non_direct_input_changed)
401*8975f5c5SAndroid Build Coastguard Worker    changes = None
402*8975f5c5SAndroid Build Coastguard Worker
403*8975f5c5SAndroid Build Coastguard Worker  if changes is None:
404*8975f5c5SAndroid Build Coastguard Worker    required_desugar_classes_set = set()
405*8975f5c5SAndroid Build Coastguard Worker  else:
406*8975f5c5SAndroid Build Coastguard Worker    required_desugar_classes_set = _ComputeRequiredDesugarClasses(
407*8975f5c5SAndroid Build Coastguard Worker        changes, options.desugar_dependencies, options.class_inputs,
408*8975f5c5SAndroid Build Coastguard Worker        options.classpath)
409*8975f5c5SAndroid Build Coastguard Worker    logging.debug('Class files needing re-desugar: %d',
410*8975f5c5SAndroid Build Coastguard Worker                  len(required_desugar_classes_set))
411*8975f5c5SAndroid Build Coastguard Worker  class_files = _ExtractClassFiles(changes, tmp_extract_dir,
412*8975f5c5SAndroid Build Coastguard Worker                                   options.class_inputs,
413*8975f5c5SAndroid Build Coastguard Worker                                   required_desugar_classes_set)
414*8975f5c5SAndroid Build Coastguard Worker  logging.debug('Extracted class files: %d', len(class_files))
415*8975f5c5SAndroid Build Coastguard Worker
416*8975f5c5SAndroid Build Coastguard Worker  # If the only change is deleting a file, class_files will be empty.
417*8975f5c5SAndroid Build Coastguard Worker  if class_files:
418*8975f5c5SAndroid Build Coastguard Worker    # Dex necessary classes into intermediate dex files.
419*8975f5c5SAndroid Build Coastguard Worker    dex_cmd = dex_cmd + ['--intermediate', '--file-per-class-file']
420*8975f5c5SAndroid Build Coastguard Worker    if options.desugar_dependencies and not options.skip_custom_d8:
421*8975f5c5SAndroid Build Coastguard Worker      # Adding os.sep to remove the entire prefix.
422*8975f5c5SAndroid Build Coastguard Worker      dex_cmd += ['--file-tmp-prefix', tmp_extract_dir + os.sep]
423*8975f5c5SAndroid Build Coastguard Worker      if changes is None and os.path.exists(options.desugar_dependencies):
424*8975f5c5SAndroid Build Coastguard Worker        # Since incremental dexing only ever adds to the desugar_dependencies
425*8975f5c5SAndroid Build Coastguard Worker        # file, whenever full dexes are required the .desugardeps files need to
426*8975f5c5SAndroid Build Coastguard Worker        # be manually removed.
427*8975f5c5SAndroid Build Coastguard Worker        os.unlink(options.desugar_dependencies)
428*8975f5c5SAndroid Build Coastguard Worker    _RunD8(dex_cmd, class_files, options.incremental_dir,
429*8975f5c5SAndroid Build Coastguard Worker           options.warnings_as_errors,
430*8975f5c5SAndroid Build Coastguard Worker           options.show_desugar_default_interface_warnings)
431*8975f5c5SAndroid Build Coastguard Worker    logging.debug('Dexed class files.')
432*8975f5c5SAndroid Build Coastguard Worker
433*8975f5c5SAndroid Build Coastguard Worker
434*8975f5c5SAndroid Build Coastguard Workerdef _OnStaleMd5(changes, options, final_dex_inputs, service_jars, dex_cmd):
435*8975f5c5SAndroid Build Coastguard Worker  logging.debug('_OnStaleMd5')
436*8975f5c5SAndroid Build Coastguard Worker  with build_utils.TempDir() as tmp_dir:
437*8975f5c5SAndroid Build Coastguard Worker    if options.incremental_dir:
438*8975f5c5SAndroid Build Coastguard Worker      # Create directory for all intermediate dex files.
439*8975f5c5SAndroid Build Coastguard Worker      if not os.path.exists(options.incremental_dir):
440*8975f5c5SAndroid Build Coastguard Worker        os.makedirs(options.incremental_dir)
441*8975f5c5SAndroid Build Coastguard Worker
442*8975f5c5SAndroid Build Coastguard Worker      _DeleteStaleIncrementalDexFiles(options.incremental_dir, final_dex_inputs)
443*8975f5c5SAndroid Build Coastguard Worker      logging.debug('Stale files deleted')
444*8975f5c5SAndroid Build Coastguard Worker      _CreateIntermediateDexFiles(changes, options, tmp_dir, dex_cmd)
445*8975f5c5SAndroid Build Coastguard Worker
446*8975f5c5SAndroid Build Coastguard Worker    _CreateFinalDex(final_dex_inputs,
447*8975f5c5SAndroid Build Coastguard Worker                    options.output,
448*8975f5c5SAndroid Build Coastguard Worker                    tmp_dir,
449*8975f5c5SAndroid Build Coastguard Worker                    dex_cmd,
450*8975f5c5SAndroid Build Coastguard Worker                    options=options,
451*8975f5c5SAndroid Build Coastguard Worker                    service_jars=service_jars)
452*8975f5c5SAndroid Build Coastguard Worker
453*8975f5c5SAndroid Build Coastguard Worker
454*8975f5c5SAndroid Build Coastguard Workerdef MergeDexForIncrementalInstall(r8_jar_path, src_paths, dest_dex_jar,
455*8975f5c5SAndroid Build Coastguard Worker                                  min_api):
456*8975f5c5SAndroid Build Coastguard Worker  dex_cmd = build_utils.JavaCmd(xmx=_DEX_XMX) + [
457*8975f5c5SAndroid Build Coastguard Worker      '-cp',
458*8975f5c5SAndroid Build Coastguard Worker      r8_jar_path,
459*8975f5c5SAndroid Build Coastguard Worker      'com.android.tools.r8.D8',
460*8975f5c5SAndroid Build Coastguard Worker      '--min-api',
461*8975f5c5SAndroid Build Coastguard Worker      min_api,
462*8975f5c5SAndroid Build Coastguard Worker  ]
463*8975f5c5SAndroid Build Coastguard Worker  with build_utils.TempDir() as tmp_dir:
464*8975f5c5SAndroid Build Coastguard Worker    _CreateFinalDex(src_paths,
465*8975f5c5SAndroid Build Coastguard Worker                    dest_dex_jar,
466*8975f5c5SAndroid Build Coastguard Worker                    tmp_dir,
467*8975f5c5SAndroid Build Coastguard Worker                    dex_cmd,
468*8975f5c5SAndroid Build Coastguard Worker                    service_jars=src_paths)
469*8975f5c5SAndroid Build Coastguard Worker
470*8975f5c5SAndroid Build Coastguard Worker
471*8975f5c5SAndroid Build Coastguard Workerdef main(args):
472*8975f5c5SAndroid Build Coastguard Worker  build_utils.InitLogging('DEX_DEBUG')
473*8975f5c5SAndroid Build Coastguard Worker  options = _ParseArgs(args)
474*8975f5c5SAndroid Build Coastguard Worker
475*8975f5c5SAndroid Build Coastguard Worker  options.class_inputs += options.class_inputs_filearg
476*8975f5c5SAndroid Build Coastguard Worker  options.dex_inputs += options.dex_inputs_filearg
477*8975f5c5SAndroid Build Coastguard Worker
478*8975f5c5SAndroid Build Coastguard Worker  input_paths = ([
479*8975f5c5SAndroid Build Coastguard Worker      build_utils.JAVA_PATH_FOR_INPUTS, options.r8_jar_path,
480*8975f5c5SAndroid Build Coastguard Worker      options.custom_d8_jar_path
481*8975f5c5SAndroid Build Coastguard Worker  ] + options.class_inputs + options.dex_inputs)
482*8975f5c5SAndroid Build Coastguard Worker
483*8975f5c5SAndroid Build Coastguard Worker  depfile_deps = options.class_inputs_filearg + options.dex_inputs_filearg
484*8975f5c5SAndroid Build Coastguard Worker
485*8975f5c5SAndroid Build Coastguard Worker  output_paths = [options.output]
486*8975f5c5SAndroid Build Coastguard Worker
487*8975f5c5SAndroid Build Coastguard Worker  track_subpaths_allowlist = []
488*8975f5c5SAndroid Build Coastguard Worker  if options.incremental_dir:
489*8975f5c5SAndroid Build Coastguard Worker    final_dex_inputs, service_jars = _IntermediateDexFilePathsFromInputJars(
490*8975f5c5SAndroid Build Coastguard Worker        options.class_inputs, options.incremental_dir)
491*8975f5c5SAndroid Build Coastguard Worker    output_paths += final_dex_inputs
492*8975f5c5SAndroid Build Coastguard Worker    track_subpaths_allowlist += options.class_inputs
493*8975f5c5SAndroid Build Coastguard Worker  else:
494*8975f5c5SAndroid Build Coastguard Worker    final_dex_inputs = list(options.class_inputs)
495*8975f5c5SAndroid Build Coastguard Worker    service_jars = final_dex_inputs
496*8975f5c5SAndroid Build Coastguard Worker  service_jars += options.dex_inputs
497*8975f5c5SAndroid Build Coastguard Worker  final_dex_inputs += options.dex_inputs
498*8975f5c5SAndroid Build Coastguard Worker
499*8975f5c5SAndroid Build Coastguard Worker  dex_cmd = build_utils.JavaCmd(xmx=_DEX_XMX)
500*8975f5c5SAndroid Build Coastguard Worker
501*8975f5c5SAndroid Build Coastguard Worker  if options.dump_inputs:
502*8975f5c5SAndroid Build Coastguard Worker    dex_cmd += ['-Dcom.android.tools.r8.dumpinputtofile=d8inputs.zip']
503*8975f5c5SAndroid Build Coastguard Worker
504*8975f5c5SAndroid Build Coastguard Worker  if not options.skip_custom_d8:
505*8975f5c5SAndroid Build Coastguard Worker    dex_cmd += [
506*8975f5c5SAndroid Build Coastguard Worker        '-cp',
507*8975f5c5SAndroid Build Coastguard Worker        '{}:{}'.format(options.r8_jar_path, options.custom_d8_jar_path),
508*8975f5c5SAndroid Build Coastguard Worker        'org.chromium.build.CustomD8',
509*8975f5c5SAndroid Build Coastguard Worker    ]
510*8975f5c5SAndroid Build Coastguard Worker  else:
511*8975f5c5SAndroid Build Coastguard Worker    dex_cmd += [
512*8975f5c5SAndroid Build Coastguard Worker        '-cp',
513*8975f5c5SAndroid Build Coastguard Worker        options.r8_jar_path,
514*8975f5c5SAndroid Build Coastguard Worker        'com.android.tools.r8.D8',
515*8975f5c5SAndroid Build Coastguard Worker    ]
516*8975f5c5SAndroid Build Coastguard Worker
517*8975f5c5SAndroid Build Coastguard Worker  if options.release:
518*8975f5c5SAndroid Build Coastguard Worker    dex_cmd += ['--release']
519*8975f5c5SAndroid Build Coastguard Worker  if options.min_api:
520*8975f5c5SAndroid Build Coastguard Worker    dex_cmd += ['--min-api', options.min_api]
521*8975f5c5SAndroid Build Coastguard Worker
522*8975f5c5SAndroid Build Coastguard Worker  if not options.desugar:
523*8975f5c5SAndroid Build Coastguard Worker    dex_cmd += ['--no-desugaring']
524*8975f5c5SAndroid Build Coastguard Worker  elif options.classpath:
525*8975f5c5SAndroid Build Coastguard Worker    # The classpath is used by D8 to for interface desugaring.
526*8975f5c5SAndroid Build Coastguard Worker    if options.desugar_dependencies and not options.skip_custom_d8:
527*8975f5c5SAndroid Build Coastguard Worker      dex_cmd += ['--desugar-dependencies', options.desugar_dependencies]
528*8975f5c5SAndroid Build Coastguard Worker      if track_subpaths_allowlist:
529*8975f5c5SAndroid Build Coastguard Worker        track_subpaths_allowlist += options.classpath
530*8975f5c5SAndroid Build Coastguard Worker    depfile_deps += options.classpath
531*8975f5c5SAndroid Build Coastguard Worker    input_paths += options.classpath
532*8975f5c5SAndroid Build Coastguard Worker    # Still pass the entire classpath in case a new dependency is needed by
533*8975f5c5SAndroid Build Coastguard Worker    # desugar, so that desugar_dependencies will be updated for the next build.
534*8975f5c5SAndroid Build Coastguard Worker    for path in options.classpath:
535*8975f5c5SAndroid Build Coastguard Worker      dex_cmd += ['--classpath', path]
536*8975f5c5SAndroid Build Coastguard Worker
537*8975f5c5SAndroid Build Coastguard Worker  if options.classpath:
538*8975f5c5SAndroid Build Coastguard Worker    dex_cmd += ['--lib', build_utils.JAVA_HOME]
539*8975f5c5SAndroid Build Coastguard Worker    for path in options.bootclasspath:
540*8975f5c5SAndroid Build Coastguard Worker      dex_cmd += ['--lib', path]
541*8975f5c5SAndroid Build Coastguard Worker    depfile_deps += options.bootclasspath
542*8975f5c5SAndroid Build Coastguard Worker    input_paths += options.bootclasspath
543*8975f5c5SAndroid Build Coastguard Worker
544*8975f5c5SAndroid Build Coastguard Worker
545*8975f5c5SAndroid Build Coastguard Worker  if options.assertion_handler:
546*8975f5c5SAndroid Build Coastguard Worker    dex_cmd += ['--force-assertions-handler:' + options.assertion_handler]
547*8975f5c5SAndroid Build Coastguard Worker  if options.force_enable_assertions:
548*8975f5c5SAndroid Build Coastguard Worker    dex_cmd += ['--force-enable-assertions']
549*8975f5c5SAndroid Build Coastguard Worker
550*8975f5c5SAndroid Build Coastguard Worker  # The changes feature from md5_check allows us to only re-dex the class files
551*8975f5c5SAndroid Build Coastguard Worker  # that have changed and the class files that need to be re-desugared by D8.
552*8975f5c5SAndroid Build Coastguard Worker  md5_check.CallAndWriteDepfileIfStale(
553*8975f5c5SAndroid Build Coastguard Worker      lambda changes: _OnStaleMd5(changes, options, final_dex_inputs,
554*8975f5c5SAndroid Build Coastguard Worker                                  service_jars, dex_cmd),
555*8975f5c5SAndroid Build Coastguard Worker      options,
556*8975f5c5SAndroid Build Coastguard Worker      input_paths=input_paths,
557*8975f5c5SAndroid Build Coastguard Worker      input_strings=dex_cmd + [str(bool(options.incremental_dir))],
558*8975f5c5SAndroid Build Coastguard Worker      output_paths=output_paths,
559*8975f5c5SAndroid Build Coastguard Worker      pass_changes=True,
560*8975f5c5SAndroid Build Coastguard Worker      track_subpaths_allowlist=track_subpaths_allowlist,
561*8975f5c5SAndroid Build Coastguard Worker      depfile_deps=depfile_deps)
562*8975f5c5SAndroid Build Coastguard Worker
563*8975f5c5SAndroid Build Coastguard Worker
564*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__':
565*8975f5c5SAndroid Build Coastguard Worker  sys.exit(main(sys.argv[1:]))
566