1#!/usr/bin/env python 2# 3# Copyright 2013 The Chromium Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7import distutils.spawn 8import logging 9import multiprocessing 10import optparse 11import os 12import re 13import shutil 14import sys 15import time 16import zipfile 17 18from util import build_utils 19from util import md5_check 20from util import jar_info_utils 21 22sys.path.insert( 23 0, 24 os.path.join(build_utils.DIR_SOURCE_ROOT, 'third_party', 'colorama', 'src')) 25import colorama 26 27_JAVAC_EXTRACTOR = os.path.join(build_utils.DIR_SOURCE_ROOT, 'third_party', 28 'android_prebuilts', 'build_tools', 'common', 29 'framework', 'javac_extractor.jar') 30 31# Full list of checks: https://errorprone.info/bugpatterns 32ERRORPRONE_WARNINGS_TO_TURN_OFF = [ 33 # This one should really be turned on. 34 'ParameterNotNullable', 35 # TODO(crbug.com/834807): Follow steps in bug 36 'DoubleBraceInitialization', 37 # TODO(crbug.com/834790): Follow steps in bug. 38 'CatchAndPrintStackTrace', 39 # TODO(crbug.com/801210): Follow steps in bug. 40 'SynchronizeOnNonFinalField', 41 # TODO(crbug.com/802073): Follow steps in bug. 42 'TypeParameterUnusedInFormals', 43 # TODO(crbug.com/803484): Follow steps in bug. 44 'CatchFail', 45 # TODO(crbug.com/803485): Follow steps in bug. 46 'JUnitAmbiguousTestClass', 47 # TODO(crbug.com/1027683): Follow steps in bug. 48 'UnnecessaryParentheses', 49 # TODO(wnwen): Fix issue in JavaUploadDataSinkBase.java 50 'PrimitiveAtomicReference', 51 # Android platform default is always UTF-8. 52 # https://developer.android.com/reference/java/nio/charset/Charset.html#defaultCharset() 53 'DefaultCharset', 54 # Low priority since the alternatives still work. 55 'JdkObsolete', 56 # We don't use that many lambdas. 57 'FunctionalInterfaceClash', 58 # There are lots of times when we just want to post a task. 59 'FutureReturnValueIgnored', 60 # Nice to be explicit about operators, but not necessary. 61 'OperatorPrecedence', 62 # Just false positives in our code. 63 'ThreadJoinLoop', 64 # Low priority corner cases with String.split. 65 # Linking Guava and using Splitter was rejected 66 # in the https://chromium-review.googlesource.com/c/chromium/src/+/871630. 67 'StringSplitter', 68 # Preferred to use another method since it propagates exceptions better. 69 'ClassNewInstance', 70 # Nice to have static inner classes but not necessary. 71 'ClassCanBeStatic', 72 # Explicit is better than implicit. 73 'FloatCast', 74 # Results in false positives. 75 'ThreadLocalUsage', 76 # Also just false positives. 77 'Finally', 78 # False positives for Chromium. 79 'FragmentNotInstantiable', 80 # Low priority to fix. 81 'HidingField', 82 # Low priority. 83 'IntLongMath', 84 # Low priority. 85 'BadComparable', 86 # Low priority. 87 'EqualsHashCode', 88 # Nice to fix but low priority. 89 'TypeParameterShadowing', 90 # Good to have immutable enums, also low priority. 91 'ImmutableEnumChecker', 92 # False positives for testing. 93 'InputStreamSlowMultibyteRead', 94 # Nice to have better primitives. 95 'BoxedPrimitiveConstructor', 96 # Not necessary for tests. 97 'OverrideThrowableToString', 98 # Nice to have better type safety. 99 'CollectionToArraySafeParameter', 100 # Makes logcat debugging more difficult, and does not provide obvious 101 # benefits in the Chromium codebase. 102 'ObjectToString', 103 # Triggers on private methods that are @CalledByNative. 104 'UnusedMethod', 105 # Triggers on generated R.java files. 106 'UnusedVariable', 107 # Not that useful. 108 'UnsafeReflectiveConstructionCast', 109 # Not that useful. 110 'MixedMutabilityReturnType', 111 # Nice to have. 112 'EqualsGetClass', 113 # A lot of false-positives from CharSequence.equals(). 114 'UndefinedEquals', 115 # Nice to have. 116 'ExtendingJUnitAssert', 117 # Nice to have. 118 'SystemExitOutsideMain', 119 # Nice to have. 120 'TypeParameterNaming', 121 # Nice to have. 122 'UnusedException', 123 # Nice to have. 124 'UngroupedOverloads', 125 # Nice to have. 126 'FunctionalInterfaceClash', 127 # Nice to have. 128 'InconsistentOverloads', 129 # Dagger generated code triggers this. 130 'SameNameButDifferent', 131 # Nice to have. 132 'UnnecessaryLambda', 133 # Nice to have. 134 'UnnecessaryAnonymousClass', 135 # Nice to have. 136 'LiteProtoToString', 137 # Must be off since we are now passing in annotation processor generated 138 # code as a source jar (deduplicating work with turbine). 139 'RefersToDaggerCodegen', 140] 141 142# Full list of checks: https://errorprone.info/bugpatterns 143# Only those marked as "experimental" need to be listed here in order to be 144# enabled. We build with -Werror, so all default checks cause builds to fail. 145ERRORPRONE_WARNINGS_TO_ERROR = [ 146 'BinderIdentityRestoredDangerously', 147 'EmptyIf', 148 'EqualsBrokenForNull', 149 'InvalidThrows', 150 'LongLiteralLowerCaseSuffix', 151 'MultiVariableDeclaration', 152 'RedundantOverride', 153 'RemoveUnusedImports', 154 'StaticQualifiedUsingExpression', 155 'StringEquality', 156 'TimeUnitMismatch', 157 'UnnecessaryStaticImport', 158 'UseBinds', 159 'WildcardImport', 160] 161 162 163def ProcessJavacOutput(output): 164 fileline_prefix = r'(?P<fileline>(?P<file>[-.\w/\\]+.java):(?P<line>[0-9]+):)' 165 warning_re = re.compile(fileline_prefix + 166 r'(?P<full_message> warning: (?P<message>.*))$') 167 error_re = re.compile(fileline_prefix + 168 r'(?P<full_message> (?P<message>.*))$') 169 marker_re = re.compile(r'\s*(?P<marker>\^)\s*$') 170 171 # These warnings cannot be suppressed even for third party code. Deprecation 172 # warnings especially do not help since we must support older android version. 173 deprecated_re = re.compile( 174 r'(Note: .* uses? or overrides? a deprecated API.)$') 175 unchecked_re = re.compile( 176 r'(Note: .* uses? unchecked or unsafe operations.)$') 177 recompile_re = re.compile(r'(Note: Recompile with -Xlint:.* for details.)$') 178 179 warning_color = ['full_message', colorama.Fore.YELLOW + colorama.Style.DIM] 180 error_color = ['full_message', colorama.Fore.MAGENTA + colorama.Style.BRIGHT] 181 marker_color = ['marker', colorama.Fore.BLUE + colorama.Style.BRIGHT] 182 183 def Colorize(line, regex, color): 184 match = regex.match(line) 185 start = match.start(color[0]) 186 end = match.end(color[0]) 187 return (line[:start] + color[1] + line[start:end] + colorama.Fore.RESET + 188 colorama.Style.RESET_ALL + line[end:]) 189 190 def ApplyFilters(line): 191 return not (deprecated_re.match(line) or unchecked_re.match(line) 192 or recompile_re.match(line)) 193 194 def ApplyColors(line): 195 if warning_re.match(line): 196 line = Colorize(line, warning_re, warning_color) 197 elif error_re.match(line): 198 line = Colorize(line, error_re, error_color) 199 elif marker_re.match(line): 200 line = Colorize(line, marker_re, marker_color) 201 return line 202 203 return '\n'.join(map(ApplyColors, filter(ApplyFilters, output.split('\n')))) 204 205 206def _ExtractClassFiles(jar_path, dest_dir, java_files): 207 """Extracts all .class files not corresponding to |java_files|.""" 208 # Two challenges exist here: 209 # 1. |java_files| have prefixes that are not represented in the the jar paths. 210 # 2. A single .java file results in multiple .class files when it contains 211 # nested classes. 212 # Here's an example: 213 # source path: ../../base/android/java/src/org/chromium/Foo.java 214 # jar paths: org/chromium/Foo.class, org/chromium/Foo$Inner.class 215 # To extract only .class files not related to the given .java files, we strip 216 # off ".class" and "$*.class" and use a substring match against java_files. 217 def extract_predicate(path): 218 if not path.endswith('.class'): 219 return False 220 path_without_suffix = re.sub(r'(?:\$|\.)[^/]*class$', '', path) 221 partial_java_path = path_without_suffix + '.java' 222 return not any(p.endswith(partial_java_path) for p in java_files) 223 224 logging.info('Extracting class files from %s', jar_path) 225 build_utils.ExtractAll(jar_path, path=dest_dir, predicate=extract_predicate) 226 for path in build_utils.FindInDirectory(dest_dir, '*.class'): 227 shutil.copystat(jar_path, path) 228 229 230def _ParsePackageAndClassNames(java_file): 231 package_name = '' 232 class_names = [] 233 with open(java_file) as f: 234 for l in f: 235 # Strip unindented comments. 236 # Considers a leading * as a continuation of a multi-line comment (our 237 # linter doesn't enforce a space before it like there should be). 238 l = re.sub(r'^(?://.*|/?\*.*?(?:\*/\s*|$))', '', l) 239 240 m = re.match(r'package\s+(.*?);', l) 241 if m and not package_name: 242 package_name = m.group(1) 243 244 # Not exactly a proper parser, but works for sources that Chrome uses. 245 # In order to not match nested classes, it just checks for lack of indent. 246 m = re.match(r'(?:\S.*?)?(?:class|@?interface|enum)\s+(.+?)\b', l) 247 if m: 248 class_names.append(m.group(1)) 249 return package_name, class_names 250 251 252def _ProcessJavaFileForInfo(java_file): 253 package_name, class_names = _ParsePackageAndClassNames(java_file) 254 return java_file, package_name, class_names 255 256 257class _InfoFileContext(object): 258 """Manages the creation of the class->source file .info file.""" 259 260 def __init__(self, chromium_code, excluded_globs): 261 self._chromium_code = chromium_code 262 self._excluded_globs = excluded_globs 263 # Map of .java path -> .srcjar/nested/path.java. 264 self._srcjar_files = {} 265 # List of generators from pool.imap_unordered(). 266 self._results = [] 267 # Lazily created multiprocessing.Pool. 268 self._pool = None 269 270 def AddSrcJarSources(self, srcjar_path, extracted_paths, parent_dir): 271 for path in extracted_paths: 272 # We want the path inside the srcjar so the viewer can have a tree 273 # structure. 274 self._srcjar_files[path] = '{}/{}'.format( 275 srcjar_path, os.path.relpath(path, parent_dir)) 276 277 def SubmitFiles(self, java_files): 278 if self._pool is None: 279 # Restrict to just one process to not slow down compiling. Compiling 280 # is always slower. 281 self._pool = multiprocessing.Pool(1) 282 logging.info('Submitting %d files for info', len(java_files)) 283 self._results.append( 284 self._pool.imap_unordered( 285 _ProcessJavaFileForInfo, java_files, chunksize=1000)) 286 287 def _CheckPathMatchesClassName(self, java_file, package_name, class_name): 288 parts = package_name.split('.') + [class_name + '.java'] 289 expected_path_suffix = os.path.sep.join(parts) 290 if not java_file.endswith(expected_path_suffix): 291 raise Exception(('Java package+class name do not match its path.\n' 292 'Actual path: %s\nExpected path: %s') % 293 (java_file, expected_path_suffix)) 294 295 def _ProcessInfo(self, java_file, package_name, class_names, source): 296 for class_name in class_names: 297 yield '{}.{}'.format(package_name, class_name) 298 # Skip aidl srcjars since they don't indent code correctly. 299 if '_aidl.srcjar' in source: 300 continue 301 assert not self._chromium_code or len(class_names) == 1, ( 302 'Chromium java files must only have one class: {}'.format(source)) 303 if self._chromium_code: 304 # This check is not necessary but nice to check this somewhere. 305 self._CheckPathMatchesClassName(java_file, package_name, class_names[0]) 306 307 def _ShouldIncludeInJarInfo(self, fully_qualified_name): 308 name_as_class_glob = fully_qualified_name.replace('.', '/') + '.class' 309 return not build_utils.MatchesGlob(name_as_class_glob, self._excluded_globs) 310 311 def _Collect(self): 312 if self._pool is None: 313 return {} 314 ret = {} 315 for result in self._results: 316 for java_file, package_name, class_names in result: 317 source = self._srcjar_files.get(java_file, java_file) 318 for fully_qualified_name in self._ProcessInfo(java_file, package_name, 319 class_names, source): 320 if self._ShouldIncludeInJarInfo(fully_qualified_name): 321 ret[fully_qualified_name] = java_file 322 self._pool.terminate() 323 return ret 324 325 def __del__(self): 326 # Work around for Python 2.x bug with multiprocessing and daemon threads: 327 # https://bugs.python.org/issue4106 328 if self._pool is not None: 329 logging.info('Joining multiprocessing.Pool') 330 self._pool.terminate() 331 self._pool.join() 332 logging.info('Done.') 333 334 def Commit(self, output_path): 335 """Writes a .jar.info file. 336 337 Maps fully qualified names for classes to either the java file that they 338 are defined in or the path of the srcjar that they came from. 339 """ 340 logging.info('Collecting info file entries') 341 entries = self._Collect() 342 343 logging.info('Writing info file: %s', output_path) 344 with build_utils.AtomicOutput(output_path) as f: 345 jar_info_utils.WriteJarInfoFile(f, entries, self._srcjar_files) 346 logging.info('Completed info file: %s', output_path) 347 348 349def _CreateJarFile(jar_path, provider_configurations, additional_jar_files, 350 classes_dir): 351 logging.info('Start creating jar file: %s', jar_path) 352 with build_utils.AtomicOutput(jar_path) as f: 353 with zipfile.ZipFile(f.name, 'w') as z: 354 build_utils.ZipDir(z, classes_dir) 355 if provider_configurations: 356 for config in provider_configurations: 357 zip_path = 'META-INF/services/' + os.path.basename(config) 358 build_utils.AddToZipHermetic(z, zip_path, src_path=config) 359 360 if additional_jar_files: 361 for src_path, zip_path in additional_jar_files: 362 build_utils.AddToZipHermetic(z, zip_path, src_path=src_path) 363 logging.info('Completed jar file: %s', jar_path) 364 365 366def _OnStaleMd5(options, javac_cmd, javac_args, java_files): 367 logging.info('Starting _OnStaleMd5') 368 if options.enable_kythe_annotations: 369 # Kythe requires those env variables to be set and compile_java.py does the 370 # same 371 if not os.environ.get('KYTHE_ROOT_DIRECTORY') or \ 372 not os.environ.get('KYTHE_OUTPUT_DIRECTORY'): 373 raise Exception('--enable-kythe-annotations requires ' 374 'KYTHE_ROOT_DIRECTORY and KYTHE_OUTPUT_DIRECTORY ' 375 'environment variables to be set.') 376 javac_extractor_cmd = [ 377 build_utils.JAVA_PATH, 378 '-jar', 379 _JAVAC_EXTRACTOR, 380 ] 381 try: 382 _RunCompiler(options, javac_extractor_cmd + javac_args, java_files, 383 options.classpath, options.jar_path + '.javac_extractor', 384 save_outputs=False), 385 except build_utils.CalledProcessError as e: 386 # Having no index for particular target is better than failing entire 387 # codesearch. Log and error and move on. 388 logging.error('Could not generate kzip: %s', e) 389 390 # Compiles with Error Prone take twice as long to run as pure javac. Thus GN 391 # rules run both in parallel, with Error Prone only used for checks. 392 _RunCompiler(options, javac_cmd + javac_args, java_files, 393 options.classpath, options.jar_path, 394 save_outputs=not options.enable_errorprone) 395 logging.info('Completed all steps in _OnStaleMd5') 396 397 398def _RunCompiler(options, javac_cmd, java_files, classpath, jar_path, 399 save_outputs=True): 400 logging.info('Starting _RunCompiler') 401 402 # Compiles with Error Prone take twice as long to run as pure javac. Thus GN 403 # rules run both in parallel, with Error Prone only used for checks. 404 save_outputs = not options.enable_errorprone 405 406 # Use jar_path's directory to ensure paths are relative (needed for goma). 407 temp_dir = jar_path + '.staging' 408 shutil.rmtree(temp_dir, True) 409 os.makedirs(temp_dir) 410 try: 411 classes_dir = os.path.join(temp_dir, 'classes') 412 413 if save_outputs: 414 input_srcjars_dir = os.path.join(options.generated_dir, 'input_srcjars') 415 annotation_processor_outputs_dir = os.path.join( 416 options.generated_dir, 'annotation_processor_outputs') 417 # Delete any stale files in the generated directory. The purpose of 418 # options.generated_dir is for codesearch. 419 shutil.rmtree(options.generated_dir, True) 420 info_file_context = _InfoFileContext(options.chromium_code, 421 options.jar_info_exclude_globs) 422 else: 423 input_srcjars_dir = os.path.join(temp_dir, 'input_srcjars') 424 annotation_processor_outputs_dir = os.path.join( 425 temp_dir, 'annotation_processor_outputs') 426 427 if options.java_srcjars: 428 logging.info('Extracting srcjars to %s', input_srcjars_dir) 429 build_utils.MakeDirectory(input_srcjars_dir) 430 for srcjar in options.java_srcjars: 431 extracted_files = build_utils.ExtractAll( 432 srcjar, no_clobber=True, path=input_srcjars_dir, pattern='*.java') 433 java_files.extend(extracted_files) 434 if save_outputs: 435 info_file_context.AddSrcJarSources(srcjar, extracted_files, 436 input_srcjars_dir) 437 logging.info('Done extracting srcjars') 438 439 if save_outputs and java_files: 440 info_file_context.SubmitFiles(java_files) 441 442 if java_files: 443 # Don't include the output directory in the initial set of args since it 444 # being in a temp dir makes it unstable (breaks md5 stamping). 445 cmd = list(javac_cmd) 446 cmd += ['-d', classes_dir] 447 cmd += ['-s', annotation_processor_outputs_dir] 448 449 # Pass classpath and source paths as response files to avoid extremely 450 # long command lines that are tedius to debug. 451 if classpath: 452 cmd += ['-classpath', ':'.join(classpath)] 453 454 java_files_rsp_path = os.path.join(temp_dir, 'files_list.txt') 455 with open(java_files_rsp_path, 'w') as f: 456 f.write(' '.join(java_files)) 457 cmd += ['@' + java_files_rsp_path] 458 459 logging.debug('Build command %s', cmd) 460 os.makedirs(classes_dir) 461 os.makedirs(annotation_processor_outputs_dir) 462 start = time.time() 463 build_utils.CheckOutput( 464 cmd, 465 print_stdout=options.chromium_code, 466 stdout_filter=ProcessJavacOutput, 467 stderr_filter=ProcessJavacOutput) 468 end = time.time() - start 469 logging.info('Java compilation took %ss', end) 470 471 if save_outputs: 472 annotation_processor_java_files = build_utils.FindInDirectory( 473 annotation_processor_outputs_dir) 474 if annotation_processor_java_files: 475 info_file_context.SubmitFiles(annotation_processor_java_files) 476 477 _CreateJarFile(jar_path, options.provider_configurations, 478 options.additional_jar_files, classes_dir) 479 480 info_file_context.Commit(jar_path + '.info') 481 else: 482 build_utils.Touch(jar_path) 483 484 logging.info('Completed all steps in _RunCompiler') 485 finally: 486 shutil.rmtree(temp_dir) 487 488 489def _ParseOptions(argv): 490 parser = optparse.OptionParser() 491 build_utils.AddDepfileOption(parser) 492 493 parser.add_option( 494 '--java-srcjars', 495 action='append', 496 default=[], 497 help='List of srcjars to include in compilation.') 498 parser.add_option( 499 '--generated-dir', 500 help='Subdirectory within target_gen_dir to place extracted srcjars and ' 501 'annotation processor output for codesearch to find.') 502 parser.add_option( 503 '--bootclasspath', 504 action='append', 505 default=[], 506 help='Boot classpath for javac. If this is specified multiple times, ' 507 'they will all be appended to construct the classpath.') 508 parser.add_option( 509 '--java-version', 510 help='Java language version to use in -source and -target args to javac.') 511 parser.add_option('--classpath', action='append', help='Classpath to use.') 512 parser.add_option( 513 '--processors', 514 action='append', 515 help='GN list of annotation processor main classes.') 516 parser.add_option( 517 '--processorpath', 518 action='append', 519 help='GN list of jars that comprise the classpath used for Annotation ' 520 'Processors.') 521 parser.add_option( 522 '--processor-arg', 523 dest='processor_args', 524 action='append', 525 help='key=value arguments for the annotation processors.') 526 parser.add_option( 527 '--provider-configuration', 528 dest='provider_configurations', 529 action='append', 530 help='File to specify a service provider. Will be included ' 531 'in the jar under META-INF/services.') 532 parser.add_option( 533 '--additional-jar-file', 534 dest='additional_jar_files', 535 action='append', 536 help='Additional files to package into jar. By default, only Java .class ' 537 'files are packaged into the jar. Files should be specified in ' 538 'format <filename>:<path to be placed in jar>.') 539 parser.add_option( 540 '--jar-info-exclude-globs', 541 help='GN list of exclude globs to filter from generated .info files.') 542 parser.add_option( 543 '--chromium-code', 544 type='int', 545 help='Whether code being compiled should be built with stricter ' 546 'warnings for chromium code.') 547 parser.add_option( 548 '--gomacc-path', help='When set, prefix javac command with gomacc') 549 parser.add_option( 550 '--errorprone-path', help='Use the Errorprone compiler at this path.') 551 parser.add_option( 552 '--enable-errorprone', 553 action='store_true', 554 help='Enable errorprone checks') 555 parser.add_option( 556 '--warnings-as-errors', 557 action='store_true', 558 help='Treat all warnings as errors.') 559 parser.add_option('--jar-path', help='Jar output path.') 560 parser.add_option( 561 '--javac-arg', 562 action='append', 563 default=[], 564 help='Additional arguments to pass to javac.') 565 parser.add_option( 566 '--enable-kythe-annotations', 567 action='store_true', 568 help='Enable generation of Kythe kzip, used for codesearch. Ensure ' 569 'proper environment variables are set before using this flag.') 570 571 options, args = parser.parse_args(argv) 572 build_utils.CheckOptions(options, parser, required=('jar_path', )) 573 574 options.bootclasspath = build_utils.ParseGnList(options.bootclasspath) 575 options.classpath = build_utils.ParseGnList(options.classpath) 576 options.processorpath = build_utils.ParseGnList(options.processorpath) 577 options.processors = build_utils.ParseGnList(options.processors) 578 options.java_srcjars = build_utils.ParseGnList(options.java_srcjars) 579 options.jar_info_exclude_globs = build_utils.ParseGnList( 580 options.jar_info_exclude_globs) 581 582 additional_jar_files = [] 583 for arg in options.additional_jar_files or []: 584 filepath, jar_filepath = arg.split(':') 585 additional_jar_files.append((filepath, jar_filepath)) 586 options.additional_jar_files = additional_jar_files 587 588 java_files = [] 589 for arg in args: 590 # Interpret a path prefixed with @ as a file containing a list of sources. 591 if arg.startswith('@'): 592 java_files.extend(build_utils.ReadSourcesList(arg[1:])) 593 else: 594 java_files.append(arg) 595 596 return options, java_files 597 598 599def main(argv): 600 build_utils.InitLogging('JAVAC_DEBUG') 601 colorama.init() 602 603 argv = build_utils.ExpandFileArgs(argv) 604 options, java_files = _ParseOptions(argv) 605 606 javac_cmd = [] 607 if options.gomacc_path: 608 javac_cmd.append(options.gomacc_path) 609 javac_cmd.append(build_utils.JAVAC_PATH) 610 611 javac_args = [ 612 '-g', 613 # Chromium only allows UTF8 source files. Being explicit avoids 614 # javac pulling a default encoding from the user's environment. 615 '-encoding', 616 'UTF-8', 617 # Prevent compiler from compiling .java files not listed as inputs. 618 # See: http://blog.ltgt.net/most-build-tools-misuse-javac/ 619 '-sourcepath', 620 ':', 621 ] 622 623 if options.enable_errorprone: 624 # All errorprone args are passed space-separated in a single arg. 625 errorprone_flags = ['-Xplugin:ErrorProne'] 626 for warning in ERRORPRONE_WARNINGS_TO_TURN_OFF: 627 errorprone_flags.append('-Xep:{}:OFF'.format(warning)) 628 for warning in ERRORPRONE_WARNINGS_TO_ERROR: 629 errorprone_flags.append('-Xep:{}:ERROR'.format(warning)) 630 if not options.warnings_as_errors: 631 errorprone_flags.append('-XepAllErrorsAsWarnings') 632 javac_args += ['-XDcompilePolicy=simple', ' '.join(errorprone_flags)] 633 # This flag quits errorprone after checks and before code generation, since 634 # we do not need errorprone outputs, this speeds up errorprone by 4 seconds 635 # for chrome_java. 636 javac_args += ['-XDshould-stop.ifNoError=FLOW'] 637 638 if options.java_version: 639 javac_args.extend([ 640 '-source', 641 options.java_version, 642 '-target', 643 options.java_version, 644 ]) 645 if options.java_version == '1.8': 646 # Android's boot jar doesn't contain all java 8 classes. 647 options.bootclasspath.append(build_utils.RT_JAR_PATH) 648 649 if options.warnings_as_errors: 650 javac_args.extend(['-Werror']) 651 else: 652 # XDignore.symbol.file makes javac compile against rt.jar instead of 653 # ct.sym. This means that using a java internal package/class will not 654 # trigger a compile warning or error. 655 javac_args.extend(['-XDignore.symbol.file']) 656 657 if options.processors: 658 javac_args.extend(['-processor', ','.join(options.processors)]) 659 else: 660 # This effectively disables all annotation processors, even including 661 # annotation processors in service provider configuration files named 662 # META-INF/. See the following link for reference: 663 # https://docs.oracle.com/en/java/javase/11/tools/javac.html 664 javac_args.extend(['-proc:none']) 665 666 if options.bootclasspath: 667 javac_args.extend(['-bootclasspath', ':'.join(options.bootclasspath)]) 668 669 if options.processorpath: 670 javac_args.extend(['-processorpath', ':'.join(options.processorpath)]) 671 if options.processor_args: 672 for arg in options.processor_args: 673 javac_args.extend(['-A%s' % arg]) 674 675 javac_args.extend(options.javac_arg) 676 677 classpath_inputs = ( 678 options.bootclasspath + options.classpath + options.processorpath) 679 680 # GN already knows of java_files, so listing them just make things worse when 681 # they change. 682 depfile_deps = classpath_inputs + options.java_srcjars 683 input_paths = depfile_deps + java_files 684 input_paths += [x[0] for x in options.additional_jar_files] 685 686 output_paths = [ 687 options.jar_path, 688 options.jar_path + '.info', 689 ] 690 691 input_strings = javac_cmd + javac_args + options.classpath + java_files 692 if options.jar_info_exclude_globs: 693 input_strings.append(options.jar_info_exclude_globs) 694 695 md5_check.CallAndWriteDepfileIfStale( 696 lambda: _OnStaleMd5(options, javac_cmd, javac_args, java_files), 697 options, 698 depfile_deps=depfile_deps, 699 input_paths=input_paths, 700 input_strings=input_strings, 701 output_paths=output_paths) 702 703 704if __name__ == '__main__': 705 sys.exit(main(sys.argv[1:])) 706