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