xref: /aosp_15_r20/external/angle/build/android/gyp/compile_java.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 collections
8*8975f5c5SAndroid Build Coastguard Workerimport functools
9*8975f5c5SAndroid Build Coastguard Workerimport itertools
10*8975f5c5SAndroid Build Coastguard Workerimport logging
11*8975f5c5SAndroid Build Coastguard Workerimport optparse
12*8975f5c5SAndroid Build Coastguard Workerimport os
13*8975f5c5SAndroid Build Coastguard Workerimport pathlib
14*8975f5c5SAndroid Build Coastguard Workerimport re
15*8975f5c5SAndroid Build Coastguard Workerimport shlex
16*8975f5c5SAndroid Build Coastguard Workerimport shutil
17*8975f5c5SAndroid Build Coastguard Workerimport sys
18*8975f5c5SAndroid Build Coastguard Workerimport time
19*8975f5c5SAndroid Build Coastguard Workerimport zipfile
20*8975f5c5SAndroid Build Coastguard Worker
21*8975f5c5SAndroid Build Coastguard Workerimport javac_output_processor
22*8975f5c5SAndroid Build Coastguard Workerfrom util import build_utils
23*8975f5c5SAndroid Build Coastguard Workerfrom util import md5_check
24*8975f5c5SAndroid Build Coastguard Workerfrom util import jar_info_utils
25*8975f5c5SAndroid Build Coastguard Workerfrom util import server_utils
26*8975f5c5SAndroid Build Coastguard Workerimport action_helpers  # build_utils adds //build to sys.path.
27*8975f5c5SAndroid Build Coastguard Workerimport zip_helpers
28*8975f5c5SAndroid Build Coastguard Worker
29*8975f5c5SAndroid Build Coastguard Worker_JAVAC_EXTRACTOR = os.path.join(build_utils.DIR_SOURCE_ROOT, 'third_party',
30*8975f5c5SAndroid Build Coastguard Worker                                'android_prebuilts', 'build_tools', 'common',
31*8975f5c5SAndroid Build Coastguard Worker                                'framework', 'javac_extractor.jar')
32*8975f5c5SAndroid Build Coastguard Worker
33*8975f5c5SAndroid Build Coastguard Worker# Add a check here to cause the suggested fix to be applied while compiling.
34*8975f5c5SAndroid Build Coastguard Worker# Use this when trying to enable more checks.
35*8975f5c5SAndroid Build Coastguard WorkerERRORPRONE_CHECKS_TO_APPLY = []
36*8975f5c5SAndroid Build Coastguard Worker
37*8975f5c5SAndroid Build Coastguard Worker# Checks to disable in tests.
38*8975f5c5SAndroid Build Coastguard WorkerTESTONLY_ERRORPRONE_WARNINGS_TO_DISABLE = [
39*8975f5c5SAndroid Build Coastguard Worker    # Too much effort to enable.
40*8975f5c5SAndroid Build Coastguard Worker    'UnusedVariable',
41*8975f5c5SAndroid Build Coastguard Worker    # These are allowed in tests.
42*8975f5c5SAndroid Build Coastguard Worker    'NoStreams',
43*8975f5c5SAndroid Build Coastguard Worker]
44*8975f5c5SAndroid Build Coastguard Worker
45*8975f5c5SAndroid Build Coastguard Worker# Full list of checks: https://errorprone.info/bugpatterns
46*8975f5c5SAndroid Build Coastguard WorkerERRORPRONE_WARNINGS_TO_DISABLE = [
47*8975f5c5SAndroid Build Coastguard Worker    'InlineMeInliner',
48*8975f5c5SAndroid Build Coastguard Worker    'InlineMeSuggester',
49*8975f5c5SAndroid Build Coastguard Worker    # High priority to enable:
50*8975f5c5SAndroid Build Coastguard Worker    'HidingField',
51*8975f5c5SAndroid Build Coastguard Worker    'AlreadyChecked',
52*8975f5c5SAndroid Build Coastguard Worker    'DirectInvocationOnMock',
53*8975f5c5SAndroid Build Coastguard Worker    'MockNotUsedInProduction',
54*8975f5c5SAndroid Build Coastguard Worker    # High priority to enable in non-tests:
55*8975f5c5SAndroid Build Coastguard Worker    'JdkObsolete',
56*8975f5c5SAndroid Build Coastguard Worker    'ReturnValueIgnored',
57*8975f5c5SAndroid Build Coastguard Worker    'StaticAssignmentInConstructor',
58*8975f5c5SAndroid Build Coastguard Worker    # These are all for Javadoc, which we don't really care about.
59*8975f5c5SAndroid Build Coastguard Worker    # vvv
60*8975f5c5SAndroid Build Coastguard Worker    'InvalidBlockTag',
61*8975f5c5SAndroid Build Coastguard Worker    'InvalidParam',
62*8975f5c5SAndroid Build Coastguard Worker    'InvalidLink',
63*8975f5c5SAndroid Build Coastguard Worker    'InvalidInlineTag',
64*8975f5c5SAndroid Build Coastguard Worker    'MalformedInlineTag',
65*8975f5c5SAndroid Build Coastguard Worker    'MissingSummary',
66*8975f5c5SAndroid Build Coastguard Worker    'UnescapedEntity',
67*8975f5c5SAndroid Build Coastguard Worker    'UnrecognisedJavadocTag',
68*8975f5c5SAndroid Build Coastguard Worker    # ^^^
69*8975f5c5SAndroid Build Coastguard Worker    'MutablePublicArray',
70*8975f5c5SAndroid Build Coastguard Worker    'NonCanonicalType',
71*8975f5c5SAndroid Build Coastguard Worker    'DoNotClaimAnnotations',
72*8975f5c5SAndroid Build Coastguard Worker    'JavaUtilDate',
73*8975f5c5SAndroid Build Coastguard Worker    'IdentityHashMapUsage',
74*8975f5c5SAndroid Build Coastguard Worker    'StaticMockMember',
75*8975f5c5SAndroid Build Coastguard Worker    # Triggers in tests where this is useful to do.
76*8975f5c5SAndroid Build Coastguard Worker    'StaticAssignmentOfThrowable',
77*8975f5c5SAndroid Build Coastguard Worker    # TODO(crbug.com/41384349): Follow steps in bug.
78*8975f5c5SAndroid Build Coastguard Worker    'CatchAndPrintStackTrace',
79*8975f5c5SAndroid Build Coastguard Worker    # TODO(crbug.com/41364806): Follow steps in bug.
80*8975f5c5SAndroid Build Coastguard Worker    'TypeParameterUnusedInFormals',
81*8975f5c5SAndroid Build Coastguard Worker    # Android platform default is always UTF-8.
82*8975f5c5SAndroid Build Coastguard Worker    # https://developer.android.com/reference/java/nio/charset/Charset.html#defaultCharset()
83*8975f5c5SAndroid Build Coastguard Worker    'DefaultCharset',
84*8975f5c5SAndroid Build Coastguard Worker    # There are lots of times when we just want to post a task.
85*8975f5c5SAndroid Build Coastguard Worker    'FutureReturnValueIgnored',
86*8975f5c5SAndroid Build Coastguard Worker    # Just false positives in our code.
87*8975f5c5SAndroid Build Coastguard Worker    'ThreadJoinLoop',
88*8975f5c5SAndroid Build Coastguard Worker    # Low priority corner cases with String.split.
89*8975f5c5SAndroid Build Coastguard Worker    # Linking Guava and using Splitter was rejected
90*8975f5c5SAndroid Build Coastguard Worker    # in the https://chromium-review.googlesource.com/c/chromium/src/+/871630.
91*8975f5c5SAndroid Build Coastguard Worker    'StringSplitter',
92*8975f5c5SAndroid Build Coastguard Worker    # Preferred to use another method since it propagates exceptions better.
93*8975f5c5SAndroid Build Coastguard Worker    'ClassNewInstance',
94*8975f5c5SAndroid Build Coastguard Worker    # Results in false positives.
95*8975f5c5SAndroid Build Coastguard Worker    'ThreadLocalUsage',
96*8975f5c5SAndroid Build Coastguard Worker    # Low priority.
97*8975f5c5SAndroid Build Coastguard Worker    'EqualsHashCode',
98*8975f5c5SAndroid Build Coastguard Worker    # Not necessary for tests.
99*8975f5c5SAndroid Build Coastguard Worker    'OverrideThrowableToString',
100*8975f5c5SAndroid Build Coastguard Worker    # Not that useful.
101*8975f5c5SAndroid Build Coastguard Worker    'UnsafeReflectiveConstructionCast',
102*8975f5c5SAndroid Build Coastguard Worker    # Not that useful.
103*8975f5c5SAndroid Build Coastguard Worker    'MixedMutabilityReturnType',
104*8975f5c5SAndroid Build Coastguard Worker    # Nice to have.
105*8975f5c5SAndroid Build Coastguard Worker    'EqualsGetClass',
106*8975f5c5SAndroid Build Coastguard Worker    # A lot of false-positives from CharSequence.equals().
107*8975f5c5SAndroid Build Coastguard Worker    'UndefinedEquals',
108*8975f5c5SAndroid Build Coastguard Worker    # Dagger generated code triggers this.
109*8975f5c5SAndroid Build Coastguard Worker    'SameNameButDifferent',
110*8975f5c5SAndroid Build Coastguard Worker    # Does not apply to Android because it assumes no desugaring.
111*8975f5c5SAndroid Build Coastguard Worker    'UnnecessaryLambda',
112*8975f5c5SAndroid Build Coastguard Worker    # Nice to have.
113*8975f5c5SAndroid Build Coastguard Worker    'EmptyCatch',
114*8975f5c5SAndroid Build Coastguard Worker    # Nice to have.
115*8975f5c5SAndroid Build Coastguard Worker    'BadImport',
116*8975f5c5SAndroid Build Coastguard Worker    # Nice to have.
117*8975f5c5SAndroid Build Coastguard Worker    'UseCorrectAssertInTests',
118*8975f5c5SAndroid Build Coastguard Worker    # Must be off since we are now passing in annotation processor generated
119*8975f5c5SAndroid Build Coastguard Worker    # code as a source jar (deduplicating work with turbine).
120*8975f5c5SAndroid Build Coastguard Worker    'RefersToDaggerCodegen',
121*8975f5c5SAndroid Build Coastguard Worker    # We already have presubmit checks for this. We don't want it to fail
122*8975f5c5SAndroid Build Coastguard Worker    # local compiles.
123*8975f5c5SAndroid Build Coastguard Worker    'RemoveUnusedImports',
124*8975f5c5SAndroid Build Coastguard Worker    # Only has false positives (would not want to enable this).
125*8975f5c5SAndroid Build Coastguard Worker    'UnicodeEscape',
126*8975f5c5SAndroid Build Coastguard Worker    # A lot of existing violations. e.g. Should return List and not ArrayList
127*8975f5c5SAndroid Build Coastguard Worker    'NonApiType',
128*8975f5c5SAndroid Build Coastguard Worker    # Nice to have.
129*8975f5c5SAndroid Build Coastguard Worker    'StringCharset',
130*8975f5c5SAndroid Build Coastguard Worker    # Nice to have.
131*8975f5c5SAndroid Build Coastguard Worker    'StringCaseLocaleUsage',
132*8975f5c5SAndroid Build Coastguard Worker    # Low priority.
133*8975f5c5SAndroid Build Coastguard Worker    'RedundantControlFlow',
134*8975f5c5SAndroid Build Coastguard Worker]
135*8975f5c5SAndroid Build Coastguard Worker
136*8975f5c5SAndroid Build Coastguard Worker# Full list of checks: https://errorprone.info/bugpatterns
137*8975f5c5SAndroid Build Coastguard Worker# Only those marked as "experimental" need to be listed here in order to be
138*8975f5c5SAndroid Build Coastguard Worker# enabled.
139*8975f5c5SAndroid Build Coastguard WorkerERRORPRONE_WARNINGS_TO_ENABLE = [
140*8975f5c5SAndroid Build Coastguard Worker    'BinderIdentityRestoredDangerously',
141*8975f5c5SAndroid Build Coastguard Worker    'EmptyIf',
142*8975f5c5SAndroid Build Coastguard Worker    'EqualsBrokenForNull',
143*8975f5c5SAndroid Build Coastguard Worker    'InvalidThrows',
144*8975f5c5SAndroid Build Coastguard Worker    'LongLiteralLowerCaseSuffix',
145*8975f5c5SAndroid Build Coastguard Worker    'MultiVariableDeclaration',
146*8975f5c5SAndroid Build Coastguard Worker    'RedundantOverride',
147*8975f5c5SAndroid Build Coastguard Worker    'StaticQualifiedUsingExpression',
148*8975f5c5SAndroid Build Coastguard Worker    'TimeUnitMismatch',
149*8975f5c5SAndroid Build Coastguard Worker    'UnnecessaryStaticImport',
150*8975f5c5SAndroid Build Coastguard Worker    'UseBinds',
151*8975f5c5SAndroid Build Coastguard Worker    'WildcardImport',
152*8975f5c5SAndroid Build Coastguard Worker    'NoStreams',
153*8975f5c5SAndroid Build Coastguard Worker]
154*8975f5c5SAndroid Build Coastguard Worker
155*8975f5c5SAndroid Build Coastguard Worker
156*8975f5c5SAndroid Build Coastguard Workerdef ProcessJavacOutput(output, target_name):
157*8975f5c5SAndroid Build Coastguard Worker  # These warnings cannot be suppressed even for third party code. Deprecation
158*8975f5c5SAndroid Build Coastguard Worker  # warnings especially do not help since we must support older android version.
159*8975f5c5SAndroid Build Coastguard Worker  deprecated_re = re.compile(r'Note: .* uses? or overrides? a deprecated API')
160*8975f5c5SAndroid Build Coastguard Worker  unchecked_re = re.compile(
161*8975f5c5SAndroid Build Coastguard Worker      r'(Note: .* uses? unchecked or unsafe operations.)$')
162*8975f5c5SAndroid Build Coastguard Worker  recompile_re = re.compile(r'(Note: Recompile with -Xlint:.* for details.)$')
163*8975f5c5SAndroid Build Coastguard Worker
164*8975f5c5SAndroid Build Coastguard Worker  def ApplyFilters(line):
165*8975f5c5SAndroid Build Coastguard Worker    return not (deprecated_re.match(line) or unchecked_re.match(line)
166*8975f5c5SAndroid Build Coastguard Worker                or recompile_re.match(line))
167*8975f5c5SAndroid Build Coastguard Worker
168*8975f5c5SAndroid Build Coastguard Worker  output = build_utils.FilterReflectiveAccessJavaWarnings(output)
169*8975f5c5SAndroid Build Coastguard Worker
170*8975f5c5SAndroid Build Coastguard Worker  # Warning currently cannot be silenced via javac flag.
171*8975f5c5SAndroid Build Coastguard Worker  if 'Unsafe is internal proprietary API' in output:
172*8975f5c5SAndroid Build Coastguard Worker    # Example:
173*8975f5c5SAndroid Build Coastguard Worker    # HiddenApiBypass.java:69: warning: Unsafe is internal proprietary API and
174*8975f5c5SAndroid Build Coastguard Worker    # may be removed in a future release
175*8975f5c5SAndroid Build Coastguard Worker    # import sun.misc.Unsafe;
176*8975f5c5SAndroid Build Coastguard Worker    #                 ^
177*8975f5c5SAndroid Build Coastguard Worker    output = re.sub(r'.*?Unsafe is internal proprietary API[\s\S]*?\^\n', '',
178*8975f5c5SAndroid Build Coastguard Worker                    output)
179*8975f5c5SAndroid Build Coastguard Worker    output = re.sub(r'\d+ warnings\n', '', output)
180*8975f5c5SAndroid Build Coastguard Worker
181*8975f5c5SAndroid Build Coastguard Worker  lines = (l for l in output.split('\n') if ApplyFilters(l))
182*8975f5c5SAndroid Build Coastguard Worker
183*8975f5c5SAndroid Build Coastguard Worker  output_processor = javac_output_processor.JavacOutputProcessor(target_name)
184*8975f5c5SAndroid Build Coastguard Worker  lines = output_processor.Process(lines)
185*8975f5c5SAndroid Build Coastguard Worker
186*8975f5c5SAndroid Build Coastguard Worker  return '\n'.join(lines)
187*8975f5c5SAndroid Build Coastguard Worker
188*8975f5c5SAndroid Build Coastguard Worker
189*8975f5c5SAndroid Build Coastguard Workerdef CreateJarFile(jar_path,
190*8975f5c5SAndroid Build Coastguard Worker                  classes_dir,
191*8975f5c5SAndroid Build Coastguard Worker                  services_map=None,
192*8975f5c5SAndroid Build Coastguard Worker                  additional_jar_files=None,
193*8975f5c5SAndroid Build Coastguard Worker                  extra_classes_jar=None):
194*8975f5c5SAndroid Build Coastguard Worker  """Zips files from compilation into a single jar."""
195*8975f5c5SAndroid Build Coastguard Worker  logging.info('Start creating jar file: %s', jar_path)
196*8975f5c5SAndroid Build Coastguard Worker  with action_helpers.atomic_output(jar_path) as f:
197*8975f5c5SAndroid Build Coastguard Worker    with zipfile.ZipFile(f.name, 'w') as z:
198*8975f5c5SAndroid Build Coastguard Worker      zip_helpers.zip_directory(z, classes_dir)
199*8975f5c5SAndroid Build Coastguard Worker      if services_map:
200*8975f5c5SAndroid Build Coastguard Worker        for service_class, impl_classes in sorted(services_map.items()):
201*8975f5c5SAndroid Build Coastguard Worker          zip_path = 'META-INF/services/' + service_class
202*8975f5c5SAndroid Build Coastguard Worker          data = ''.join(f'{x}\n' for x in sorted(impl_classes))
203*8975f5c5SAndroid Build Coastguard Worker          zip_helpers.add_to_zip_hermetic(z, zip_path, data=data)
204*8975f5c5SAndroid Build Coastguard Worker
205*8975f5c5SAndroid Build Coastguard Worker      if additional_jar_files:
206*8975f5c5SAndroid Build Coastguard Worker        for src_path, zip_path in additional_jar_files:
207*8975f5c5SAndroid Build Coastguard Worker          zip_helpers.add_to_zip_hermetic(z, zip_path, src_path=src_path)
208*8975f5c5SAndroid Build Coastguard Worker      if extra_classes_jar:
209*8975f5c5SAndroid Build Coastguard Worker        path_transform = lambda p: p if p.endswith('.class') else None
210*8975f5c5SAndroid Build Coastguard Worker        zip_helpers.merge_zips(z, [extra_classes_jar],
211*8975f5c5SAndroid Build Coastguard Worker                               path_transform=path_transform)
212*8975f5c5SAndroid Build Coastguard Worker  logging.info('Completed jar file: %s', jar_path)
213*8975f5c5SAndroid Build Coastguard Worker
214*8975f5c5SAndroid Build Coastguard Worker
215*8975f5c5SAndroid Build Coastguard Worker# Java lines end in semicolon, whereas Kotlin lines do not.
216*8975f5c5SAndroid Build Coastguard Worker_PACKAGE_RE = re.compile(r'^package\s+(.*?)(;|\s*$)', flags=re.MULTILINE)
217*8975f5c5SAndroid Build Coastguard Worker
218*8975f5c5SAndroid Build Coastguard Worker_SERVICE_IMPL_RE = re.compile(
219*8975f5c5SAndroid Build Coastguard Worker    r'^([\t ]*)@ServiceImpl\(\s*(.+?)\.class\)(.*?)\sclass\s+(\w+)',
220*8975f5c5SAndroid Build Coastguard Worker    flags=re.MULTILINE | re.DOTALL)
221*8975f5c5SAndroid Build Coastguard Worker
222*8975f5c5SAndroid Build Coastguard Worker# Finds all top-level classes (by looking for those that are not indented).
223*8975f5c5SAndroid Build Coastguard Worker_TOP_LEVEL_CLASSES_RE = re.compile(
224*8975f5c5SAndroid Build Coastguard Worker    # Start of line, or after /* package */
225*8975f5c5SAndroid Build Coastguard Worker    r'^(?:/\*.*\*/\s*)?'
226*8975f5c5SAndroid Build Coastguard Worker    # Annotations
227*8975f5c5SAndroid Build Coastguard Worker    r'(?:@\w+(?:\(.*\))\s+)*'
228*8975f5c5SAndroid Build Coastguard Worker    r'(?:(?:public|protected|private)\s+)?'
229*8975f5c5SAndroid Build Coastguard Worker    r'(?:(?:static|abstract|final|sealed)\s+)*'
230*8975f5c5SAndroid Build Coastguard Worker    r'(?:class|@?interface|enum|record)\s+'
231*8975f5c5SAndroid Build Coastguard Worker    r'(\w+?)\b[^"]*?$',
232*8975f5c5SAndroid Build Coastguard Worker    flags=re.MULTILINE)
233*8975f5c5SAndroid Build Coastguard Worker
234*8975f5c5SAndroid Build Coastguard Worker
235*8975f5c5SAndroid Build Coastguard Workerdef ParseJavaSource(data, services_map, path=None):
236*8975f5c5SAndroid Build Coastguard Worker  """This should support both Java and Kotlin files."""
237*8975f5c5SAndroid Build Coastguard Worker  package_name = ''
238*8975f5c5SAndroid Build Coastguard Worker  if m := _PACKAGE_RE.search(data):
239*8975f5c5SAndroid Build Coastguard Worker    package_name = m.group(1)
240*8975f5c5SAndroid Build Coastguard Worker
241*8975f5c5SAndroid Build Coastguard Worker  class_names = _TOP_LEVEL_CLASSES_RE.findall(data)
242*8975f5c5SAndroid Build Coastguard Worker
243*8975f5c5SAndroid Build Coastguard Worker  # Very rare, so worth an upfront check.
244*8975f5c5SAndroid Build Coastguard Worker  if '@ServiceImpl' in data:
245*8975f5c5SAndroid Build Coastguard Worker    for indent, service_class, modifiers, impl_class in (
246*8975f5c5SAndroid Build Coastguard Worker        _SERVICE_IMPL_RE.findall(data)):
247*8975f5c5SAndroid Build Coastguard Worker      if 'public' not in modifiers:
248*8975f5c5SAndroid Build Coastguard Worker        raise Exception(f'@ServiceImpl can be used only on public classes '
249*8975f5c5SAndroid Build Coastguard Worker                        f'(when parsing {path})')
250*8975f5c5SAndroid Build Coastguard Worker      # Assume indent means nested class that is one level deep.
251*8975f5c5SAndroid Build Coastguard Worker      if indent:
252*8975f5c5SAndroid Build Coastguard Worker        impl_class = f'{class_names[0]}${impl_class}'
253*8975f5c5SAndroid Build Coastguard Worker      else:
254*8975f5c5SAndroid Build Coastguard Worker        assert class_names[0] == impl_class
255*8975f5c5SAndroid Build Coastguard Worker
256*8975f5c5SAndroid Build Coastguard Worker      # Parse imports to resolve the class.
257*8975f5c5SAndroid Build Coastguard Worker      dot_idx = service_class.find('.')
258*8975f5c5SAndroid Build Coastguard Worker      # Handle @ServiceImpl(OuterClass.InnerClass.class)
259*8975f5c5SAndroid Build Coastguard Worker      outer_class = service_class if dot_idx == -1 else service_class[:dot_idx]
260*8975f5c5SAndroid Build Coastguard Worker
261*8975f5c5SAndroid Build Coastguard Worker      if m := re.search(r'^import\s+([\w\.]*\.' + outer_class + r')[;\s]',
262*8975f5c5SAndroid Build Coastguard Worker                        data,
263*8975f5c5SAndroid Build Coastguard Worker                        flags=re.MULTILINE):
264*8975f5c5SAndroid Build Coastguard Worker        service_class = m.group(1) + service_class[len(outer_class):]
265*8975f5c5SAndroid Build Coastguard Worker      else:
266*8975f5c5SAndroid Build Coastguard Worker        service_class = f'{package_name}.{service_class}'
267*8975f5c5SAndroid Build Coastguard Worker
268*8975f5c5SAndroid Build Coastguard Worker      # Convert OuterClass.InnerClass -> OuterClass$InnerClass.
269*8975f5c5SAndroid Build Coastguard Worker      for m in list(re.finditer(r'\.[A-Z]', service_class))[1:]:
270*8975f5c5SAndroid Build Coastguard Worker        idx = m.start()
271*8975f5c5SAndroid Build Coastguard Worker        service_class = service_class[:idx] + '$' + service_class[idx + 1:]
272*8975f5c5SAndroid Build Coastguard Worker
273*8975f5c5SAndroid Build Coastguard Worker      services_map[service_class].append(f'{package_name}.{impl_class}')
274*8975f5c5SAndroid Build Coastguard Worker
275*8975f5c5SAndroid Build Coastguard Worker  return package_name, class_names
276*8975f5c5SAndroid Build Coastguard Worker
277*8975f5c5SAndroid Build Coastguard Worker
278*8975f5c5SAndroid Build Coastguard Workerclass _MetadataParser:
279*8975f5c5SAndroid Build Coastguard Worker
280*8975f5c5SAndroid Build Coastguard Worker  def __init__(self, chromium_code, excluded_globs):
281*8975f5c5SAndroid Build Coastguard Worker    self._chromium_code = chromium_code
282*8975f5c5SAndroid Build Coastguard Worker    self._excluded_globs = excluded_globs
283*8975f5c5SAndroid Build Coastguard Worker    # Map of .java path -> .srcjar/nested/path.java.
284*8975f5c5SAndroid Build Coastguard Worker    self._srcjar_files = {}
285*8975f5c5SAndroid Build Coastguard Worker    # Map of @ServiceImpl class -> impl class
286*8975f5c5SAndroid Build Coastguard Worker    self.services_map = collections.defaultdict(list)
287*8975f5c5SAndroid Build Coastguard Worker
288*8975f5c5SAndroid Build Coastguard Worker  def AddSrcJarSources(self, srcjar_path, extracted_paths, parent_dir):
289*8975f5c5SAndroid Build Coastguard Worker    for path in extracted_paths:
290*8975f5c5SAndroid Build Coastguard Worker      # We want the path inside the srcjar so the viewer can have a tree
291*8975f5c5SAndroid Build Coastguard Worker      # structure.
292*8975f5c5SAndroid Build Coastguard Worker      self._srcjar_files[path] = '{}/{}'.format(
293*8975f5c5SAndroid Build Coastguard Worker          srcjar_path, os.path.relpath(path, parent_dir))
294*8975f5c5SAndroid Build Coastguard Worker
295*8975f5c5SAndroid Build Coastguard Worker  def _CheckPathMatchesClassName(self, source_file, package_name, class_name):
296*8975f5c5SAndroid Build Coastguard Worker    if source_file.endswith('.java'):
297*8975f5c5SAndroid Build Coastguard Worker      parts = package_name.split('.') + [class_name + '.java']
298*8975f5c5SAndroid Build Coastguard Worker    else:
299*8975f5c5SAndroid Build Coastguard Worker      parts = package_name.split('.') + [class_name + '.kt']
300*8975f5c5SAndroid Build Coastguard Worker    expected_suffix = os.path.sep.join(parts)
301*8975f5c5SAndroid Build Coastguard Worker    if not source_file.endswith(expected_suffix):
302*8975f5c5SAndroid Build Coastguard Worker      raise Exception(('Source package+class name do not match its path.\n'
303*8975f5c5SAndroid Build Coastguard Worker                       'Actual path: %s\nExpected path: %s') %
304*8975f5c5SAndroid Build Coastguard Worker                      (source_file, expected_suffix))
305*8975f5c5SAndroid Build Coastguard Worker
306*8975f5c5SAndroid Build Coastguard Worker  def _ProcessInfo(self, java_file, package_name, class_names, source):
307*8975f5c5SAndroid Build Coastguard Worker    for class_name in class_names:
308*8975f5c5SAndroid Build Coastguard Worker      yield '{}.{}'.format(package_name, class_name)
309*8975f5c5SAndroid Build Coastguard Worker      # Skip aidl srcjars since they don't indent code correctly.
310*8975f5c5SAndroid Build Coastguard Worker      if '_aidl.srcjar' in source:
311*8975f5c5SAndroid Build Coastguard Worker        continue
312*8975f5c5SAndroid Build Coastguard Worker      assert not self._chromium_code or len(class_names) == 1, (
313*8975f5c5SAndroid Build Coastguard Worker          'Chromium java files must only have one class: {} found: {}'.format(
314*8975f5c5SAndroid Build Coastguard Worker              source, class_names))
315*8975f5c5SAndroid Build Coastguard Worker      if self._chromium_code:
316*8975f5c5SAndroid Build Coastguard Worker        # This check is not necessary but nice to check this somewhere.
317*8975f5c5SAndroid Build Coastguard Worker        self._CheckPathMatchesClassName(java_file, package_name, class_names[0])
318*8975f5c5SAndroid Build Coastguard Worker
319*8975f5c5SAndroid Build Coastguard Worker  def _ShouldIncludeInJarInfo(self, fully_qualified_name):
320*8975f5c5SAndroid Build Coastguard Worker    name_as_class_glob = fully_qualified_name.replace('.', '/') + '.class'
321*8975f5c5SAndroid Build Coastguard Worker    return not build_utils.MatchesGlob(name_as_class_glob, self._excluded_globs)
322*8975f5c5SAndroid Build Coastguard Worker
323*8975f5c5SAndroid Build Coastguard Worker  def ParseAndWriteInfoFile(self, output_path, java_files, kt_files=None):
324*8975f5c5SAndroid Build Coastguard Worker    """Writes a .jar.info file.
325*8975f5c5SAndroid Build Coastguard Worker
326*8975f5c5SAndroid Build Coastguard Worker    Maps fully qualified names for classes to either the java file that they
327*8975f5c5SAndroid Build Coastguard Worker    are defined in or the path of the srcjar that they came from.
328*8975f5c5SAndroid Build Coastguard Worker    """
329*8975f5c5SAndroid Build Coastguard Worker    logging.info('Collecting info file entries')
330*8975f5c5SAndroid Build Coastguard Worker    entries = {}
331*8975f5c5SAndroid Build Coastguard Worker    for path in itertools.chain(java_files, kt_files or []):
332*8975f5c5SAndroid Build Coastguard Worker      data = pathlib.Path(path).read_text()
333*8975f5c5SAndroid Build Coastguard Worker      package_name, class_names = ParseJavaSource(data,
334*8975f5c5SAndroid Build Coastguard Worker                                                  self.services_map,
335*8975f5c5SAndroid Build Coastguard Worker                                                  path=path)
336*8975f5c5SAndroid Build Coastguard Worker      source = self._srcjar_files.get(path, path)
337*8975f5c5SAndroid Build Coastguard Worker      for fully_qualified_name in self._ProcessInfo(path, package_name,
338*8975f5c5SAndroid Build Coastguard Worker                                                    class_names, source):
339*8975f5c5SAndroid Build Coastguard Worker        if self._ShouldIncludeInJarInfo(fully_qualified_name):
340*8975f5c5SAndroid Build Coastguard Worker          entries[fully_qualified_name] = path
341*8975f5c5SAndroid Build Coastguard Worker
342*8975f5c5SAndroid Build Coastguard Worker    logging.info('Writing info file: %s', output_path)
343*8975f5c5SAndroid Build Coastguard Worker    with action_helpers.atomic_output(output_path, mode='wb') as f:
344*8975f5c5SAndroid Build Coastguard Worker      jar_info_utils.WriteJarInfoFile(f, entries, self._srcjar_files)
345*8975f5c5SAndroid Build Coastguard Worker    logging.info('Completed info file: %s', output_path)
346*8975f5c5SAndroid Build Coastguard Worker
347*8975f5c5SAndroid Build Coastguard Worker
348*8975f5c5SAndroid Build Coastguard Workerdef _OnStaleMd5(changes, options, javac_cmd, javac_args, java_files, kt_files):
349*8975f5c5SAndroid Build Coastguard Worker  logging.info('Starting _OnStaleMd5')
350*8975f5c5SAndroid Build Coastguard Worker
351*8975f5c5SAndroid Build Coastguard Worker  # Use the build server for errorprone runs.
352*8975f5c5SAndroid Build Coastguard Worker  if (options.enable_errorprone and not options.skip_build_server
353*8975f5c5SAndroid Build Coastguard Worker      and server_utils.MaybeRunCommand(
354*8975f5c5SAndroid Build Coastguard Worker          name=options.target_name,
355*8975f5c5SAndroid Build Coastguard Worker          argv=sys.argv,
356*8975f5c5SAndroid Build Coastguard Worker          stamp_file=options.jar_path,
357*8975f5c5SAndroid Build Coastguard Worker          force=options.use_build_server,
358*8975f5c5SAndroid Build Coastguard Worker          experimental=options.experimental_build_server)):
359*8975f5c5SAndroid Build Coastguard Worker    logging.info('Using build server')
360*8975f5c5SAndroid Build Coastguard Worker    return
361*8975f5c5SAndroid Build Coastguard Worker
362*8975f5c5SAndroid Build Coastguard Worker  if options.enable_kythe_annotations:
363*8975f5c5SAndroid Build Coastguard Worker    # Kythe requires those env variables to be set and compile_java.py does the
364*8975f5c5SAndroid Build Coastguard Worker    # same
365*8975f5c5SAndroid Build Coastguard Worker    if not os.environ.get('KYTHE_ROOT_DIRECTORY') or \
366*8975f5c5SAndroid Build Coastguard Worker        not os.environ.get('KYTHE_OUTPUT_DIRECTORY'):
367*8975f5c5SAndroid Build Coastguard Worker      raise Exception('--enable-kythe-annotations requires '
368*8975f5c5SAndroid Build Coastguard Worker                      'KYTHE_ROOT_DIRECTORY and KYTHE_OUTPUT_DIRECTORY '
369*8975f5c5SAndroid Build Coastguard Worker                      'environment variables to be set.')
370*8975f5c5SAndroid Build Coastguard Worker    javac_extractor_cmd = build_utils.JavaCmd() + [
371*8975f5c5SAndroid Build Coastguard Worker        '--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED',
372*8975f5c5SAndroid Build Coastguard Worker        '--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED',
373*8975f5c5SAndroid Build Coastguard Worker        '--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED',
374*8975f5c5SAndroid Build Coastguard Worker        '--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED',
375*8975f5c5SAndroid Build Coastguard Worker        '--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED',
376*8975f5c5SAndroid Build Coastguard Worker        '--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED',
377*8975f5c5SAndroid Build Coastguard Worker        '--add-exports=jdk.internal.opt/jdk.internal.opt=ALL-UNNAMED',
378*8975f5c5SAndroid Build Coastguard Worker        '-jar',
379*8975f5c5SAndroid Build Coastguard Worker        _JAVAC_EXTRACTOR,
380*8975f5c5SAndroid Build Coastguard Worker    ]
381*8975f5c5SAndroid Build Coastguard Worker    try:
382*8975f5c5SAndroid Build Coastguard Worker      # _RunCompiler()'s partial javac implementation does not support
383*8975f5c5SAndroid Build Coastguard Worker      # generating outputs in $KYTHE_OUTPUT_DIRECTORY.
384*8975f5c5SAndroid Build Coastguard Worker      _RunCompiler(changes,
385*8975f5c5SAndroid Build Coastguard Worker                   options,
386*8975f5c5SAndroid Build Coastguard Worker                   javac_extractor_cmd + javac_args,
387*8975f5c5SAndroid Build Coastguard Worker                   java_files,
388*8975f5c5SAndroid Build Coastguard Worker                   options.jar_path + '.javac_extractor',
389*8975f5c5SAndroid Build Coastguard Worker                   enable_partial_javac=False)
390*8975f5c5SAndroid Build Coastguard Worker    except build_utils.CalledProcessError as e:
391*8975f5c5SAndroid Build Coastguard Worker      # Having no index for particular target is better than failing entire
392*8975f5c5SAndroid Build Coastguard Worker      # codesearch. Log and error and move on.
393*8975f5c5SAndroid Build Coastguard Worker      logging.error('Could not generate kzip: %s', e)
394*8975f5c5SAndroid Build Coastguard Worker
395*8975f5c5SAndroid Build Coastguard Worker  intermediates_out_dir = None
396*8975f5c5SAndroid Build Coastguard Worker  jar_info_path = None
397*8975f5c5SAndroid Build Coastguard Worker  if not options.enable_errorprone:
398*8975f5c5SAndroid Build Coastguard Worker    # Delete any stale files in the generated directory. The purpose of
399*8975f5c5SAndroid Build Coastguard Worker    # options.generated_dir is for codesearch and Android Studio.
400*8975f5c5SAndroid Build Coastguard Worker    shutil.rmtree(options.generated_dir, True)
401*8975f5c5SAndroid Build Coastguard Worker    intermediates_out_dir = options.generated_dir
402*8975f5c5SAndroid Build Coastguard Worker
403*8975f5c5SAndroid Build Coastguard Worker    # Write .info file only for the main javac invocation (no need to do it
404*8975f5c5SAndroid Build Coastguard Worker    # when running Error Prone.
405*8975f5c5SAndroid Build Coastguard Worker    jar_info_path = options.jar_path + '.info'
406*8975f5c5SAndroid Build Coastguard Worker
407*8975f5c5SAndroid Build Coastguard Worker  # Compiles with Error Prone take twice as long to run as pure javac. Thus GN
408*8975f5c5SAndroid Build Coastguard Worker  # rules run both in parallel, with Error Prone only used for checks.
409*8975f5c5SAndroid Build Coastguard Worker  try:
410*8975f5c5SAndroid Build Coastguard Worker    _RunCompiler(changes,
411*8975f5c5SAndroid Build Coastguard Worker                 options,
412*8975f5c5SAndroid Build Coastguard Worker                 javac_cmd + javac_args,
413*8975f5c5SAndroid Build Coastguard Worker                 java_files,
414*8975f5c5SAndroid Build Coastguard Worker                 options.jar_path,
415*8975f5c5SAndroid Build Coastguard Worker                 kt_files=kt_files,
416*8975f5c5SAndroid Build Coastguard Worker                 jar_info_path=jar_info_path,
417*8975f5c5SAndroid Build Coastguard Worker                 intermediates_out_dir=intermediates_out_dir,
418*8975f5c5SAndroid Build Coastguard Worker                 enable_partial_javac=True)
419*8975f5c5SAndroid Build Coastguard Worker  except build_utils.CalledProcessError as e:
420*8975f5c5SAndroid Build Coastguard Worker    # Do not output stacktrace as it takes up space on gerrit UI, forcing
421*8975f5c5SAndroid Build Coastguard Worker    # you to click though to find the actual compilation error. It's never
422*8975f5c5SAndroid Build Coastguard Worker    # interesting to see the Python stacktrace for a Java compilation error.
423*8975f5c5SAndroid Build Coastguard Worker    sys.stderr.write(e.output)
424*8975f5c5SAndroid Build Coastguard Worker    sys.exit(1)
425*8975f5c5SAndroid Build Coastguard Worker
426*8975f5c5SAndroid Build Coastguard Worker  logging.info('Completed all steps in _OnStaleMd5')
427*8975f5c5SAndroid Build Coastguard Worker
428*8975f5c5SAndroid Build Coastguard Worker
429*8975f5c5SAndroid Build Coastguard Workerdef _RunCompiler(changes,
430*8975f5c5SAndroid Build Coastguard Worker                 options,
431*8975f5c5SAndroid Build Coastguard Worker                 javac_cmd,
432*8975f5c5SAndroid Build Coastguard Worker                 java_files,
433*8975f5c5SAndroid Build Coastguard Worker                 jar_path,
434*8975f5c5SAndroid Build Coastguard Worker                 kt_files=None,
435*8975f5c5SAndroid Build Coastguard Worker                 jar_info_path=None,
436*8975f5c5SAndroid Build Coastguard Worker                 intermediates_out_dir=None,
437*8975f5c5SAndroid Build Coastguard Worker                 enable_partial_javac=False):
438*8975f5c5SAndroid Build Coastguard Worker  """Runs java compiler.
439*8975f5c5SAndroid Build Coastguard Worker
440*8975f5c5SAndroid Build Coastguard Worker  Args:
441*8975f5c5SAndroid Build Coastguard Worker    changes: md5_check.Changes object.
442*8975f5c5SAndroid Build Coastguard Worker    options: Object with command line flags.
443*8975f5c5SAndroid Build Coastguard Worker    javac_cmd: Command to execute.
444*8975f5c5SAndroid Build Coastguard Worker    java_files: List of java files passed from command line.
445*8975f5c5SAndroid Build Coastguard Worker    jar_path: Path of output jar file.
446*8975f5c5SAndroid Build Coastguard Worker    kt_files: List of Kotlin files passed from command line if any.
447*8975f5c5SAndroid Build Coastguard Worker    jar_info_path: Path of the .info file to generate.
448*8975f5c5SAndroid Build Coastguard Worker        If None, .info file will not be generated.
449*8975f5c5SAndroid Build Coastguard Worker    intermediates_out_dir: Directory for saving intermediate outputs.
450*8975f5c5SAndroid Build Coastguard Worker        If None a temporary directory is used.
451*8975f5c5SAndroid Build Coastguard Worker    enable_partial_javac: Enables compiling only Java files which have changed
452*8975f5c5SAndroid Build Coastguard Worker        in the special case that no method signatures have changed. This is
453*8975f5c5SAndroid Build Coastguard Worker        useful for large GN targets.
454*8975f5c5SAndroid Build Coastguard Worker        Not supported if compiling generates outputs other than |jar_path| and
455*8975f5c5SAndroid Build Coastguard Worker        |jar_info_path|.
456*8975f5c5SAndroid Build Coastguard Worker  """
457*8975f5c5SAndroid Build Coastguard Worker  logging.info('Starting _RunCompiler')
458*8975f5c5SAndroid Build Coastguard Worker
459*8975f5c5SAndroid Build Coastguard Worker  java_files = java_files.copy()
460*8975f5c5SAndroid Build Coastguard Worker  java_srcjars = options.java_srcjars
461*8975f5c5SAndroid Build Coastguard Worker  parse_java_files = jar_info_path is not None
462*8975f5c5SAndroid Build Coastguard Worker
463*8975f5c5SAndroid Build Coastguard Worker  # Use jar_path's directory to ensure paths are relative (needed for rbe).
464*8975f5c5SAndroid Build Coastguard Worker  temp_dir = jar_path + '.staging'
465*8975f5c5SAndroid Build Coastguard Worker  build_utils.DeleteDirectory(temp_dir)
466*8975f5c5SAndroid Build Coastguard Worker  os.makedirs(temp_dir)
467*8975f5c5SAndroid Build Coastguard Worker  metadata_parser = _MetadataParser(options.chromium_code,
468*8975f5c5SAndroid Build Coastguard Worker                                    options.jar_info_exclude_globs)
469*8975f5c5SAndroid Build Coastguard Worker  try:
470*8975f5c5SAndroid Build Coastguard Worker    classes_dir = os.path.join(temp_dir, 'classes')
471*8975f5c5SAndroid Build Coastguard Worker
472*8975f5c5SAndroid Build Coastguard Worker    if java_files:
473*8975f5c5SAndroid Build Coastguard Worker      os.makedirs(classes_dir)
474*8975f5c5SAndroid Build Coastguard Worker
475*8975f5c5SAndroid Build Coastguard Worker      if enable_partial_javac and changes:
476*8975f5c5SAndroid Build Coastguard Worker        all_changed_paths_are_java = all(
477*8975f5c5SAndroid Build Coastguard Worker            p.endswith(".java") for p in changes.IterChangedPaths())
478*8975f5c5SAndroid Build Coastguard Worker        if (all_changed_paths_are_java and not changes.HasStringChanges()
479*8975f5c5SAndroid Build Coastguard Worker            and os.path.exists(jar_path)
480*8975f5c5SAndroid Build Coastguard Worker            and (jar_info_path is None or os.path.exists(jar_info_path))):
481*8975f5c5SAndroid Build Coastguard Worker          # Log message is used by tests to determine whether partial javac
482*8975f5c5SAndroid Build Coastguard Worker          # optimization was used.
483*8975f5c5SAndroid Build Coastguard Worker          logging.info('Using partial javac optimization for %s compile' %
484*8975f5c5SAndroid Build Coastguard Worker                       (jar_path))
485*8975f5c5SAndroid Build Coastguard Worker
486*8975f5c5SAndroid Build Coastguard Worker          # Header jar corresponding to |java_files| did not change.
487*8975f5c5SAndroid Build Coastguard Worker          # As a build speed optimization (crbug.com/1170778), re-compile only
488*8975f5c5SAndroid Build Coastguard Worker          # java files which have changed. Re-use old jar .info file.
489*8975f5c5SAndroid Build Coastguard Worker          java_files = list(changes.IterChangedPaths())
490*8975f5c5SAndroid Build Coastguard Worker
491*8975f5c5SAndroid Build Coastguard Worker          # Disable srcjar extraction, since we know the srcjar didn't show as
492*8975f5c5SAndroid Build Coastguard Worker          # changed (only .java files).
493*8975f5c5SAndroid Build Coastguard Worker          java_srcjars = None
494*8975f5c5SAndroid Build Coastguard Worker
495*8975f5c5SAndroid Build Coastguard Worker          # @ServiceImpl has class retention, so will alter header jars when
496*8975f5c5SAndroid Build Coastguard Worker          # modified (and hence not reach this block).
497*8975f5c5SAndroid Build Coastguard Worker          # Likewise, nothing in .info files can change if header jar did not
498*8975f5c5SAndroid Build Coastguard Worker          # change.
499*8975f5c5SAndroid Build Coastguard Worker          parse_java_files = False
500*8975f5c5SAndroid Build Coastguard Worker
501*8975f5c5SAndroid Build Coastguard Worker          # Extracts .class as well as META-INF/services.
502*8975f5c5SAndroid Build Coastguard Worker          build_utils.ExtractAll(jar_path, classes_dir)
503*8975f5c5SAndroid Build Coastguard Worker
504*8975f5c5SAndroid Build Coastguard Worker    if intermediates_out_dir is None:
505*8975f5c5SAndroid Build Coastguard Worker      intermediates_out_dir = temp_dir
506*8975f5c5SAndroid Build Coastguard Worker
507*8975f5c5SAndroid Build Coastguard Worker    input_srcjars_dir = os.path.join(intermediates_out_dir, 'input_srcjars')
508*8975f5c5SAndroid Build Coastguard Worker
509*8975f5c5SAndroid Build Coastguard Worker    if java_srcjars:
510*8975f5c5SAndroid Build Coastguard Worker      logging.info('Extracting srcjars to %s', input_srcjars_dir)
511*8975f5c5SAndroid Build Coastguard Worker      build_utils.MakeDirectory(input_srcjars_dir)
512*8975f5c5SAndroid Build Coastguard Worker      for srcjar in options.java_srcjars:
513*8975f5c5SAndroid Build Coastguard Worker        extracted_files = build_utils.ExtractAll(
514*8975f5c5SAndroid Build Coastguard Worker            srcjar, no_clobber=True, path=input_srcjars_dir, pattern='*.java')
515*8975f5c5SAndroid Build Coastguard Worker        java_files.extend(extracted_files)
516*8975f5c5SAndroid Build Coastguard Worker        if parse_java_files:
517*8975f5c5SAndroid Build Coastguard Worker          metadata_parser.AddSrcJarSources(srcjar, extracted_files,
518*8975f5c5SAndroid Build Coastguard Worker                                           input_srcjars_dir)
519*8975f5c5SAndroid Build Coastguard Worker      logging.info('Done extracting srcjars')
520*8975f5c5SAndroid Build Coastguard Worker
521*8975f5c5SAndroid Build Coastguard Worker    if java_files:
522*8975f5c5SAndroid Build Coastguard Worker      # Don't include the output directory in the initial set of args since it
523*8975f5c5SAndroid Build Coastguard Worker      # being in a temp dir makes it unstable (breaks md5 stamping).
524*8975f5c5SAndroid Build Coastguard Worker      cmd = list(javac_cmd)
525*8975f5c5SAndroid Build Coastguard Worker      cmd += ['-d', classes_dir]
526*8975f5c5SAndroid Build Coastguard Worker
527*8975f5c5SAndroid Build Coastguard Worker      if options.classpath:
528*8975f5c5SAndroid Build Coastguard Worker        cmd += ['-classpath', ':'.join(options.classpath)]
529*8975f5c5SAndroid Build Coastguard Worker
530*8975f5c5SAndroid Build Coastguard Worker      # Pass source paths as response files to avoid extremely long command
531*8975f5c5SAndroid Build Coastguard Worker      # lines that are tedius to debug.
532*8975f5c5SAndroid Build Coastguard Worker      java_files_rsp_path = os.path.join(temp_dir, 'files_list.txt')
533*8975f5c5SAndroid Build Coastguard Worker      with open(java_files_rsp_path, 'w') as f:
534*8975f5c5SAndroid Build Coastguard Worker        f.write(' '.join(java_files))
535*8975f5c5SAndroid Build Coastguard Worker      cmd += ['@' + java_files_rsp_path]
536*8975f5c5SAndroid Build Coastguard Worker
537*8975f5c5SAndroid Build Coastguard Worker      process_javac_output_partial = functools.partial(
538*8975f5c5SAndroid Build Coastguard Worker          ProcessJavacOutput, target_name=options.target_name)
539*8975f5c5SAndroid Build Coastguard Worker
540*8975f5c5SAndroid Build Coastguard Worker      logging.debug('Build command %s', cmd)
541*8975f5c5SAndroid Build Coastguard Worker      start = time.time()
542*8975f5c5SAndroid Build Coastguard Worker      before_join_callback = None
543*8975f5c5SAndroid Build Coastguard Worker      if parse_java_files:
544*8975f5c5SAndroid Build Coastguard Worker        before_join_callback = lambda: metadata_parser.ParseAndWriteInfoFile(
545*8975f5c5SAndroid Build Coastguard Worker            jar_info_path, java_files, kt_files)
546*8975f5c5SAndroid Build Coastguard Worker
547*8975f5c5SAndroid Build Coastguard Worker      if options.print_javac_command_line:
548*8975f5c5SAndroid Build Coastguard Worker        print(shlex.join(cmd))
549*8975f5c5SAndroid Build Coastguard Worker        return
550*8975f5c5SAndroid Build Coastguard Worker
551*8975f5c5SAndroid Build Coastguard Worker      build_utils.CheckOutput(cmd,
552*8975f5c5SAndroid Build Coastguard Worker                              print_stdout=options.chromium_code,
553*8975f5c5SAndroid Build Coastguard Worker                              stdout_filter=process_javac_output_partial,
554*8975f5c5SAndroid Build Coastguard Worker                              stderr_filter=process_javac_output_partial,
555*8975f5c5SAndroid Build Coastguard Worker                              fail_on_output=options.warnings_as_errors,
556*8975f5c5SAndroid Build Coastguard Worker                              before_join_callback=before_join_callback)
557*8975f5c5SAndroid Build Coastguard Worker      end = time.time() - start
558*8975f5c5SAndroid Build Coastguard Worker      logging.info('Java compilation took %ss', end)
559*8975f5c5SAndroid Build Coastguard Worker    elif parse_java_files:
560*8975f5c5SAndroid Build Coastguard Worker      if options.print_javac_command_line:
561*8975f5c5SAndroid Build Coastguard Worker        raise Exception('need java files for --print-javac-command-line.')
562*8975f5c5SAndroid Build Coastguard Worker      metadata_parser.ParseAndWriteInfoFile(jar_info_path, java_files, kt_files)
563*8975f5c5SAndroid Build Coastguard Worker
564*8975f5c5SAndroid Build Coastguard Worker    CreateJarFile(jar_path, classes_dir, metadata_parser.services_map,
565*8975f5c5SAndroid Build Coastguard Worker                  options.additional_jar_files, options.kotlin_jar_path)
566*8975f5c5SAndroid Build Coastguard Worker
567*8975f5c5SAndroid Build Coastguard Worker    # Remove input srcjars that confuse Android Studio:
568*8975f5c5SAndroid Build Coastguard Worker    # https://crbug.com/353326240
569*8975f5c5SAndroid Build Coastguard Worker    for root, _, files in os.walk(intermediates_out_dir):
570*8975f5c5SAndroid Build Coastguard Worker      for subpath in files:
571*8975f5c5SAndroid Build Coastguard Worker        p = os.path.join(root, subpath)
572*8975f5c5SAndroid Build Coastguard Worker        # JNI Zero placeholders
573*8975f5c5SAndroid Build Coastguard Worker        if '_jni_java/' in p and not p.endswith('Jni.java'):
574*8975f5c5SAndroid Build Coastguard Worker          os.unlink(p)
575*8975f5c5SAndroid Build Coastguard Worker
576*8975f5c5SAndroid Build Coastguard Worker    logging.info('Completed all steps in _RunCompiler')
577*8975f5c5SAndroid Build Coastguard Worker  finally:
578*8975f5c5SAndroid Build Coastguard Worker    # preserve temp_dir for rsp fie when --print-javac-command-line
579*8975f5c5SAndroid Build Coastguard Worker    if not options.print_javac_command_line:
580*8975f5c5SAndroid Build Coastguard Worker      shutil.rmtree(temp_dir)
581*8975f5c5SAndroid Build Coastguard Worker
582*8975f5c5SAndroid Build Coastguard Worker
583*8975f5c5SAndroid Build Coastguard Workerdef _ParseOptions(argv):
584*8975f5c5SAndroid Build Coastguard Worker  parser = optparse.OptionParser()
585*8975f5c5SAndroid Build Coastguard Worker  action_helpers.add_depfile_arg(parser)
586*8975f5c5SAndroid Build Coastguard Worker
587*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--target-name', help='Fully qualified GN target name.')
588*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--skip-build-server',
589*8975f5c5SAndroid Build Coastguard Worker                    action='store_true',
590*8975f5c5SAndroid Build Coastguard Worker                    help='Avoid using the build server.')
591*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--use-build-server',
592*8975f5c5SAndroid Build Coastguard Worker                    action='store_true',
593*8975f5c5SAndroid Build Coastguard Worker                    help='Always use the build server.')
594*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--experimental-build-server',
595*8975f5c5SAndroid Build Coastguard Worker                    action='store_true',
596*8975f5c5SAndroid Build Coastguard Worker                    help='Use experimental build server features.')
597*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--java-srcjars',
598*8975f5c5SAndroid Build Coastguard Worker                    action='append',
599*8975f5c5SAndroid Build Coastguard Worker                    default=[],
600*8975f5c5SAndroid Build Coastguard Worker                    help='List of srcjars to include in compilation.')
601*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
602*8975f5c5SAndroid Build Coastguard Worker      '--generated-dir',
603*8975f5c5SAndroid Build Coastguard Worker      help='Subdirectory within target_gen_dir to place extracted srcjars and '
604*8975f5c5SAndroid Build Coastguard Worker      'annotation processor output for codesearch to find.')
605*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--classpath', action='append', help='Classpath to use.')
606*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
607*8975f5c5SAndroid Build Coastguard Worker      '--processorpath',
608*8975f5c5SAndroid Build Coastguard Worker      action='append',
609*8975f5c5SAndroid Build Coastguard Worker      help='GN list of jars that comprise the classpath used for Annotation '
610*8975f5c5SAndroid Build Coastguard Worker      'Processors.')
611*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
612*8975f5c5SAndroid Build Coastguard Worker      '--processor-arg',
613*8975f5c5SAndroid Build Coastguard Worker      dest='processor_args',
614*8975f5c5SAndroid Build Coastguard Worker      action='append',
615*8975f5c5SAndroid Build Coastguard Worker      help='key=value arguments for the annotation processors.')
616*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
617*8975f5c5SAndroid Build Coastguard Worker      '--additional-jar-file',
618*8975f5c5SAndroid Build Coastguard Worker      dest='additional_jar_files',
619*8975f5c5SAndroid Build Coastguard Worker      action='append',
620*8975f5c5SAndroid Build Coastguard Worker      help='Additional files to package into jar. By default, only Java .class '
621*8975f5c5SAndroid Build Coastguard Worker      'files are packaged into the jar. Files should be specified in '
622*8975f5c5SAndroid Build Coastguard Worker      'format <filename>:<path to be placed in jar>.')
623*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
624*8975f5c5SAndroid Build Coastguard Worker      '--jar-info-exclude-globs',
625*8975f5c5SAndroid Build Coastguard Worker      help='GN list of exclude globs to filter from generated .info files.')
626*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
627*8975f5c5SAndroid Build Coastguard Worker      '--chromium-code',
628*8975f5c5SAndroid Build Coastguard Worker      type='int',
629*8975f5c5SAndroid Build Coastguard Worker      help='Whether code being compiled should be built with stricter '
630*8975f5c5SAndroid Build Coastguard Worker      'warnings for chromium code.')
631*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
632*8975f5c5SAndroid Build Coastguard Worker      '--errorprone-path', help='Use the Errorprone compiler at this path.')
633*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
634*8975f5c5SAndroid Build Coastguard Worker      '--enable-errorprone',
635*8975f5c5SAndroid Build Coastguard Worker      action='store_true',
636*8975f5c5SAndroid Build Coastguard Worker      help='Enable errorprone checks')
637*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--enable-nullaway',
638*8975f5c5SAndroid Build Coastguard Worker                    action='store_true',
639*8975f5c5SAndroid Build Coastguard Worker                    help='Enable NullAway (requires --enable-errorprone)')
640*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--testonly',
641*8975f5c5SAndroid Build Coastguard Worker                    action='store_true',
642*8975f5c5SAndroid Build Coastguard Worker                    help='Disable some Error Prone checks')
643*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--warnings-as-errors',
644*8975f5c5SAndroid Build Coastguard Worker                    action='store_true',
645*8975f5c5SAndroid Build Coastguard Worker                    help='Treat all warnings as errors.')
646*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--jar-path', help='Jar output path.')
647*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
648*8975f5c5SAndroid Build Coastguard Worker      '--javac-arg',
649*8975f5c5SAndroid Build Coastguard Worker      action='append',
650*8975f5c5SAndroid Build Coastguard Worker      default=[],
651*8975f5c5SAndroid Build Coastguard Worker      help='Additional arguments to pass to javac.')
652*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--print-javac-command-line',
653*8975f5c5SAndroid Build Coastguard Worker                    action='store_true',
654*8975f5c5SAndroid Build Coastguard Worker                    help='Just show javac command line (for ide_query).')
655*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
656*8975f5c5SAndroid Build Coastguard Worker      '--enable-kythe-annotations',
657*8975f5c5SAndroid Build Coastguard Worker      action='store_true',
658*8975f5c5SAndroid Build Coastguard Worker      help='Enable generation of Kythe kzip, used for codesearch. Ensure '
659*8975f5c5SAndroid Build Coastguard Worker      'proper environment variables are set before using this flag.')
660*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
661*8975f5c5SAndroid Build Coastguard Worker      '--header-jar',
662*8975f5c5SAndroid Build Coastguard Worker      help='This is the header jar for the current target that contains '
663*8975f5c5SAndroid Build Coastguard Worker      'META-INF/services/* files to be included in the output jar.')
664*8975f5c5SAndroid Build Coastguard Worker  parser.add_option(
665*8975f5c5SAndroid Build Coastguard Worker      '--kotlin-jar-path',
666*8975f5c5SAndroid Build Coastguard Worker      help='Kotlin jar to be merged into the output jar. This contains the '
667*8975f5c5SAndroid Build Coastguard Worker      ".class files from this target's .kt files.")
668*8975f5c5SAndroid Build Coastguard Worker
669*8975f5c5SAndroid Build Coastguard Worker  options, args = parser.parse_args(argv)
670*8975f5c5SAndroid Build Coastguard Worker  build_utils.CheckOptions(options, parser, required=('jar_path', ))
671*8975f5c5SAndroid Build Coastguard Worker
672*8975f5c5SAndroid Build Coastguard Worker  options.classpath = action_helpers.parse_gn_list(options.classpath)
673*8975f5c5SAndroid Build Coastguard Worker  options.processorpath = action_helpers.parse_gn_list(options.processorpath)
674*8975f5c5SAndroid Build Coastguard Worker  options.java_srcjars = action_helpers.parse_gn_list(options.java_srcjars)
675*8975f5c5SAndroid Build Coastguard Worker  options.jar_info_exclude_globs = action_helpers.parse_gn_list(
676*8975f5c5SAndroid Build Coastguard Worker      options.jar_info_exclude_globs)
677*8975f5c5SAndroid Build Coastguard Worker
678*8975f5c5SAndroid Build Coastguard Worker  additional_jar_files = []
679*8975f5c5SAndroid Build Coastguard Worker  for arg in options.additional_jar_files or []:
680*8975f5c5SAndroid Build Coastguard Worker    filepath, jar_filepath = arg.split(':')
681*8975f5c5SAndroid Build Coastguard Worker    additional_jar_files.append((filepath, jar_filepath))
682*8975f5c5SAndroid Build Coastguard Worker  options.additional_jar_files = additional_jar_files
683*8975f5c5SAndroid Build Coastguard Worker
684*8975f5c5SAndroid Build Coastguard Worker  files = []
685*8975f5c5SAndroid Build Coastguard Worker  for arg in args:
686*8975f5c5SAndroid Build Coastguard Worker    # Interpret a path prefixed with @ as a file containing a list of sources.
687*8975f5c5SAndroid Build Coastguard Worker    if arg.startswith('@'):
688*8975f5c5SAndroid Build Coastguard Worker      files.extend(build_utils.ReadSourcesList(arg[1:]))
689*8975f5c5SAndroid Build Coastguard Worker    else:
690*8975f5c5SAndroid Build Coastguard Worker      files.append(arg)
691*8975f5c5SAndroid Build Coastguard Worker
692*8975f5c5SAndroid Build Coastguard Worker  # The target's .sources file contains both Java and Kotlin files. We use
693*8975f5c5SAndroid Build Coastguard Worker  # compile_kt.py to compile the Kotlin files to .class and header jars. Javac
694*8975f5c5SAndroid Build Coastguard Worker  # is run only on .java files.
695*8975f5c5SAndroid Build Coastguard Worker  java_files = [f for f in files if f.endswith('.java')]
696*8975f5c5SAndroid Build Coastguard Worker  # Kotlin files are needed to populate the info file and attribute size in
697*8975f5c5SAndroid Build Coastguard Worker  # supersize back to the appropriate Kotlin file.
698*8975f5c5SAndroid Build Coastguard Worker  kt_files = [f for f in files if f.endswith('.kt')]
699*8975f5c5SAndroid Build Coastguard Worker
700*8975f5c5SAndroid Build Coastguard Worker  return options, java_files, kt_files
701*8975f5c5SAndroid Build Coastguard Worker
702*8975f5c5SAndroid Build Coastguard Worker
703*8975f5c5SAndroid Build Coastguard Workerdef main(argv):
704*8975f5c5SAndroid Build Coastguard Worker  build_utils.InitLogging('JAVAC_DEBUG')
705*8975f5c5SAndroid Build Coastguard Worker  argv = build_utils.ExpandFileArgs(argv)
706*8975f5c5SAndroid Build Coastguard Worker  options, java_files, kt_files = _ParseOptions(argv)
707*8975f5c5SAndroid Build Coastguard Worker
708*8975f5c5SAndroid Build Coastguard Worker  javac_cmd = [build_utils.JAVAC_PATH]
709*8975f5c5SAndroid Build Coastguard Worker
710*8975f5c5SAndroid Build Coastguard Worker  javac_args = [
711*8975f5c5SAndroid Build Coastguard Worker      '-g',
712*8975f5c5SAndroid Build Coastguard Worker      # Jacoco does not currently support a higher value.
713*8975f5c5SAndroid Build Coastguard Worker      '--release',
714*8975f5c5SAndroid Build Coastguard Worker      '17',
715*8975f5c5SAndroid Build Coastguard Worker      # Chromium only allows UTF8 source files.  Being explicit avoids
716*8975f5c5SAndroid Build Coastguard Worker      # javac pulling a default encoding from the user's environment.
717*8975f5c5SAndroid Build Coastguard Worker      '-encoding',
718*8975f5c5SAndroid Build Coastguard Worker      'UTF-8',
719*8975f5c5SAndroid Build Coastguard Worker      # Prevent compiler from compiling .java files not listed as inputs.
720*8975f5c5SAndroid Build Coastguard Worker      # See: http://blog.ltgt.net/most-build-tools-misuse-javac/
721*8975f5c5SAndroid Build Coastguard Worker      '-sourcepath',
722*8975f5c5SAndroid Build Coastguard Worker      ':',
723*8975f5c5SAndroid Build Coastguard Worker      # protobuf-generated files fail this check (javadoc has @deprecated,
724*8975f5c5SAndroid Build Coastguard Worker      # but method missing @Deprecated annotation).
725*8975f5c5SAndroid Build Coastguard Worker      '-Xlint:-dep-ann',
726*8975f5c5SAndroid Build Coastguard Worker      # Do not warn about finalize() methods. Android still intends to support
727*8975f5c5SAndroid Build Coastguard Worker      # them.
728*8975f5c5SAndroid Build Coastguard Worker      '-Xlint:-removal',
729*8975f5c5SAndroid Build Coastguard Worker      # https://crbug.com/1441023
730*8975f5c5SAndroid Build Coastguard Worker      '-J-XX:+PerfDisableSharedMem',
731*8975f5c5SAndroid Build Coastguard Worker  ]
732*8975f5c5SAndroid Build Coastguard Worker
733*8975f5c5SAndroid Build Coastguard Worker  if options.enable_errorprone:
734*8975f5c5SAndroid Build Coastguard Worker    # All errorprone args are passed space-separated in a single arg.
735*8975f5c5SAndroid Build Coastguard Worker    errorprone_flags = ['-Xplugin:ErrorProne']
736*8975f5c5SAndroid Build Coastguard Worker
737*8975f5c5SAndroid Build Coastguard Worker    if options.enable_nullaway:
738*8975f5c5SAndroid Build Coastguard Worker      # See: https://github.com/uber/NullAway/wiki/Configuration
739*8975f5c5SAndroid Build Coastguard Worker      # Treat these packages as @NullMarked by default.
740*8975f5c5SAndroid Build Coastguard Worker      # These apply to both .jars in classpath as well as code being compiled.
741*8975f5c5SAndroid Build Coastguard Worker      errorprone_flags += [
742*8975f5c5SAndroid Build Coastguard Worker          '-XepOpt:NullAway:AnnotatedPackages=android,java,org.chromium'
743*8975f5c5SAndroid Build Coastguard Worker      ]
744*8975f5c5SAndroid Build Coastguard Worker      # Detect "assert foo != null" as a null check.
745*8975f5c5SAndroid Build Coastguard Worker      errorprone_flags += ['-XepOpt:NullAway:AssertsEnabled=true']
746*8975f5c5SAndroid Build Coastguard Worker      # Do not ignore @Nullable in non-annotated packages.
747*8975f5c5SAndroid Build Coastguard Worker      errorprone_flags += [
748*8975f5c5SAndroid Build Coastguard Worker          '-XepOpt:NullAway:AcknowledgeRestrictiveAnnotations=true'
749*8975f5c5SAndroid Build Coastguard Worker      ]
750*8975f5c5SAndroid Build Coastguard Worker      # Treat @RecentlyNullable the same as @Nullable.
751*8975f5c5SAndroid Build Coastguard Worker      errorprone_flags += ['-XepOpt:Nullaway:AcknowledgeAndroidRecent=true']
752*8975f5c5SAndroid Build Coastguard Worker      # Enable experimental checking of @Nullable generics.
753*8975f5c5SAndroid Build Coastguard Worker      # https://github.com/uber/NullAway/wiki/JSpecify-Support
754*8975f5c5SAndroid Build Coastguard Worker      errorprone_flags += ['-XepOpt:NullAway:JSpecifyMode=true']
755*8975f5c5SAndroid Build Coastguard Worker      # Treat these the same as constructors.
756*8975f5c5SAndroid Build Coastguard Worker      init_methods = [
757*8975f5c5SAndroid Build Coastguard Worker          'android.app.Application.onCreate',
758*8975f5c5SAndroid Build Coastguard Worker          'android.app.Activity.onCreate',
759*8975f5c5SAndroid Build Coastguard Worker          'android.app.Service.onCreate',
760*8975f5c5SAndroid Build Coastguard Worker          'android.app.backup.BackupAgent.onCreate',
761*8975f5c5SAndroid Build Coastguard Worker          'android.content.ContentProvider.attachInfo',
762*8975f5c5SAndroid Build Coastguard Worker          'android.content.ContentProvider.onCreate',
763*8975f5c5SAndroid Build Coastguard Worker          'android.content.ContentWrapper.attachBaseContext',
764*8975f5c5SAndroid Build Coastguard Worker      ]
765*8975f5c5SAndroid Build Coastguard Worker      errorprone_flags += [
766*8975f5c5SAndroid Build Coastguard Worker          '-XepOpt:NullAway:KnownInitializers=' + ','.join(init_methods)
767*8975f5c5SAndroid Build Coastguard Worker      ]
768*8975f5c5SAndroid Build Coastguard Worker
769*8975f5c5SAndroid Build Coastguard Worker    # Make everything a warning so that when treat_warnings_as_errors is false,
770*8975f5c5SAndroid Build Coastguard Worker    # they do not fail the build.
771*8975f5c5SAndroid Build Coastguard Worker    errorprone_flags += ['-XepAllErrorsAsWarnings']
772*8975f5c5SAndroid Build Coastguard Worker    # Don't check generated files (those tagged with @Generated).
773*8975f5c5SAndroid Build Coastguard Worker    errorprone_flags += ['-XepDisableWarningsInGeneratedCode']
774*8975f5c5SAndroid Build Coastguard Worker    errorprone_flags.extend('-Xep:{}:OFF'.format(x)
775*8975f5c5SAndroid Build Coastguard Worker                            for x in ERRORPRONE_WARNINGS_TO_DISABLE)
776*8975f5c5SAndroid Build Coastguard Worker    errorprone_flags.extend('-Xep:{}:WARN'.format(x)
777*8975f5c5SAndroid Build Coastguard Worker                            for x in ERRORPRONE_WARNINGS_TO_ENABLE)
778*8975f5c5SAndroid Build Coastguard Worker    if options.testonly:
779*8975f5c5SAndroid Build Coastguard Worker      errorprone_flags.extend('-Xep:{}:OFF'.format(x)
780*8975f5c5SAndroid Build Coastguard Worker                              for x in TESTONLY_ERRORPRONE_WARNINGS_TO_DISABLE)
781*8975f5c5SAndroid Build Coastguard Worker
782*8975f5c5SAndroid Build Coastguard Worker    if ERRORPRONE_CHECKS_TO_APPLY:
783*8975f5c5SAndroid Build Coastguard Worker      to_apply = list(ERRORPRONE_CHECKS_TO_APPLY)
784*8975f5c5SAndroid Build Coastguard Worker      if options.testonly:
785*8975f5c5SAndroid Build Coastguard Worker        to_apply = [
786*8975f5c5SAndroid Build Coastguard Worker            x for x in to_apply
787*8975f5c5SAndroid Build Coastguard Worker            if x not in TESTONLY_ERRORPRONE_WARNINGS_TO_DISABLE
788*8975f5c5SAndroid Build Coastguard Worker        ]
789*8975f5c5SAndroid Build Coastguard Worker      errorprone_flags += [
790*8975f5c5SAndroid Build Coastguard Worker          '-XepPatchLocation:IN_PLACE', '-XepPatchChecks:,' + ','.join(to_apply)
791*8975f5c5SAndroid Build Coastguard Worker      ]
792*8975f5c5SAndroid Build Coastguard Worker
793*8975f5c5SAndroid Build Coastguard Worker    # These are required to use JDK 16, and are taken directly from
794*8975f5c5SAndroid Build Coastguard Worker    # https://errorprone.info/docs/installation
795*8975f5c5SAndroid Build Coastguard Worker    javac_args += [
796*8975f5c5SAndroid Build Coastguard Worker        '-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED',
797*8975f5c5SAndroid Build Coastguard Worker        '-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED',
798*8975f5c5SAndroid Build Coastguard Worker        '-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED',
799*8975f5c5SAndroid Build Coastguard Worker        '-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED',
800*8975f5c5SAndroid Build Coastguard Worker        '-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED',
801*8975f5c5SAndroid Build Coastguard Worker        '-J--add-exports=jdk.compiler/com.sun.tools.javac.processing='
802*8975f5c5SAndroid Build Coastguard Worker        'ALL-UNNAMED',
803*8975f5c5SAndroid Build Coastguard Worker        '-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED',
804*8975f5c5SAndroid Build Coastguard Worker        '-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED',
805*8975f5c5SAndroid Build Coastguard Worker        '-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED',
806*8975f5c5SAndroid Build Coastguard Worker        '-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED',
807*8975f5c5SAndroid Build Coastguard Worker    ]
808*8975f5c5SAndroid Build Coastguard Worker
809*8975f5c5SAndroid Build Coastguard Worker    javac_args += ['-XDcompilePolicy=simple', ' '.join(errorprone_flags)]
810*8975f5c5SAndroid Build Coastguard Worker
811*8975f5c5SAndroid Build Coastguard Worker    javac_args += ['-XDshould-stop.ifError=FLOW']
812*8975f5c5SAndroid Build Coastguard Worker    # This flag quits errorprone after checks and before code generation, since
813*8975f5c5SAndroid Build Coastguard Worker    # we do not need errorprone outputs, this speeds up errorprone by 4 seconds
814*8975f5c5SAndroid Build Coastguard Worker    # for chrome_java.
815*8975f5c5SAndroid Build Coastguard Worker    if not ERRORPRONE_CHECKS_TO_APPLY:
816*8975f5c5SAndroid Build Coastguard Worker      javac_args += ['-XDshould-stop.ifNoError=FLOW']
817*8975f5c5SAndroid Build Coastguard Worker
818*8975f5c5SAndroid Build Coastguard Worker  # This effectively disables all annotation processors, even including
819*8975f5c5SAndroid Build Coastguard Worker  # annotation processors in service provider configuration files named
820*8975f5c5SAndroid Build Coastguard Worker  # META-INF/. See the following link for reference:
821*8975f5c5SAndroid Build Coastguard Worker  #     https://docs.oracle.com/en/java/javase/11/tools/javac.html
822*8975f5c5SAndroid Build Coastguard Worker  javac_args.extend(['-proc:none'])
823*8975f5c5SAndroid Build Coastguard Worker
824*8975f5c5SAndroid Build Coastguard Worker  if options.processorpath:
825*8975f5c5SAndroid Build Coastguard Worker    javac_args.extend(['-processorpath', ':'.join(options.processorpath)])
826*8975f5c5SAndroid Build Coastguard Worker  if options.processor_args:
827*8975f5c5SAndroid Build Coastguard Worker    for arg in options.processor_args:
828*8975f5c5SAndroid Build Coastguard Worker      javac_args.extend(['-A%s' % arg])
829*8975f5c5SAndroid Build Coastguard Worker
830*8975f5c5SAndroid Build Coastguard Worker  javac_args.extend(options.javac_arg)
831*8975f5c5SAndroid Build Coastguard Worker
832*8975f5c5SAndroid Build Coastguard Worker  if options.print_javac_command_line:
833*8975f5c5SAndroid Build Coastguard Worker    if options.java_srcjars:
834*8975f5c5SAndroid Build Coastguard Worker      raise Exception(
835*8975f5c5SAndroid Build Coastguard Worker          '--print-javac-command-line does not work with --java-srcjars')
836*8975f5c5SAndroid Build Coastguard Worker    _OnStaleMd5(None, options, javac_cmd, javac_args, java_files, kt_files)
837*8975f5c5SAndroid Build Coastguard Worker    return 0
838*8975f5c5SAndroid Build Coastguard Worker
839*8975f5c5SAndroid Build Coastguard Worker  classpath_inputs = options.classpath + options.processorpath
840*8975f5c5SAndroid Build Coastguard Worker
841*8975f5c5SAndroid Build Coastguard Worker  depfile_deps = classpath_inputs
842*8975f5c5SAndroid Build Coastguard Worker  # Files that are already inputs in GN should go in input_paths.
843*8975f5c5SAndroid Build Coastguard Worker  input_paths = ([build_utils.JAVAC_PATH] + depfile_deps +
844*8975f5c5SAndroid Build Coastguard Worker                 options.java_srcjars + java_files + kt_files)
845*8975f5c5SAndroid Build Coastguard Worker  if options.header_jar:
846*8975f5c5SAndroid Build Coastguard Worker    input_paths.append(options.header_jar)
847*8975f5c5SAndroid Build Coastguard Worker  input_paths += [x[0] for x in options.additional_jar_files]
848*8975f5c5SAndroid Build Coastguard Worker
849*8975f5c5SAndroid Build Coastguard Worker  output_paths = [options.jar_path]
850*8975f5c5SAndroid Build Coastguard Worker  if not options.enable_errorprone:
851*8975f5c5SAndroid Build Coastguard Worker    output_paths += [options.jar_path + '.info']
852*8975f5c5SAndroid Build Coastguard Worker
853*8975f5c5SAndroid Build Coastguard Worker  input_strings = (javac_cmd + javac_args + options.classpath + java_files +
854*8975f5c5SAndroid Build Coastguard Worker                   kt_files +
855*8975f5c5SAndroid Build Coastguard Worker                   [options.warnings_as_errors, options.jar_info_exclude_globs])
856*8975f5c5SAndroid Build Coastguard Worker
857*8975f5c5SAndroid Build Coastguard Worker  do_it = lambda changes: _OnStaleMd5(changes, options, javac_cmd, javac_args,
858*8975f5c5SAndroid Build Coastguard Worker                                      java_files, kt_files)
859*8975f5c5SAndroid Build Coastguard Worker  # Incremental build optimization doesn't work for ErrorProne. Skip md5 check.
860*8975f5c5SAndroid Build Coastguard Worker  if options.enable_errorprone:
861*8975f5c5SAndroid Build Coastguard Worker    do_it(None)
862*8975f5c5SAndroid Build Coastguard Worker    action_helpers.write_depfile(options.depfile, output_paths[0], depfile_deps)
863*8975f5c5SAndroid Build Coastguard Worker  else:
864*8975f5c5SAndroid Build Coastguard Worker    # Use md5_check for |pass_changes| feature.
865*8975f5c5SAndroid Build Coastguard Worker    md5_check.CallAndWriteDepfileIfStale(do_it,
866*8975f5c5SAndroid Build Coastguard Worker                                         options,
867*8975f5c5SAndroid Build Coastguard Worker                                         depfile_deps=depfile_deps,
868*8975f5c5SAndroid Build Coastguard Worker                                         input_paths=input_paths,
869*8975f5c5SAndroid Build Coastguard Worker                                         input_strings=input_strings,
870*8975f5c5SAndroid Build Coastguard Worker                                         output_paths=output_paths,
871*8975f5c5SAndroid Build Coastguard Worker                                         pass_changes=True)
872*8975f5c5SAndroid Build Coastguard Worker  return 0
873*8975f5c5SAndroid Build Coastguard Worker
874*8975f5c5SAndroid Build Coastguard Worker
875*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__':
876*8975f5c5SAndroid Build Coastguard Worker  sys.exit(main(sys.argv[1:]))
877