1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*8975f5c5SAndroid Build Coastguard Worker# Copyright 2020 The Chromium Authors 3*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 5*8975f5c5SAndroid Build Coastguard Worker"""Wraps the turbine jar and expands @FileArgs.""" 6*8975f5c5SAndroid Build Coastguard Worker 7*8975f5c5SAndroid Build Coastguard Workerimport argparse 8*8975f5c5SAndroid Build Coastguard Workerimport functools 9*8975f5c5SAndroid Build Coastguard Workerimport logging 10*8975f5c5SAndroid Build Coastguard Workerimport sys 11*8975f5c5SAndroid Build Coastguard Workerimport time 12*8975f5c5SAndroid Build Coastguard Workerimport zipfile 13*8975f5c5SAndroid Build Coastguard Worker 14*8975f5c5SAndroid Build Coastguard Workerimport compile_java 15*8975f5c5SAndroid Build Coastguard Workerimport javac_output_processor 16*8975f5c5SAndroid Build Coastguard Workerfrom util import build_utils 17*8975f5c5SAndroid Build Coastguard Workerimport action_helpers # build_utils adds //build to sys.path. 18*8975f5c5SAndroid Build Coastguard Workerimport zip_helpers 19*8975f5c5SAndroid Build Coastguard Worker 20*8975f5c5SAndroid Build Coastguard Worker 21*8975f5c5SAndroid Build Coastguard Workerdef ProcessJavacOutput(output, target_name): 22*8975f5c5SAndroid Build Coastguard Worker output_processor = javac_output_processor.JavacOutputProcessor(target_name) 23*8975f5c5SAndroid Build Coastguard Worker lines = output_processor.Process(output.split('\n')) 24*8975f5c5SAndroid Build Coastguard Worker return '\n'.join(lines) 25*8975f5c5SAndroid Build Coastguard Worker 26*8975f5c5SAndroid Build Coastguard Worker 27*8975f5c5SAndroid Build Coastguard Workerdef main(argv): 28*8975f5c5SAndroid Build Coastguard Worker build_utils.InitLogging('TURBINE_DEBUG') 29*8975f5c5SAndroid Build Coastguard Worker argv = build_utils.ExpandFileArgs(argv[1:]) 30*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 31*8975f5c5SAndroid Build Coastguard Worker action_helpers.add_depfile_arg(parser) 32*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--target-name', help='Fully qualified GN target name.') 33*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 34*8975f5c5SAndroid Build Coastguard Worker '--turbine-jar-path', required=True, help='Path to the turbine jar file.') 35*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 36*8975f5c5SAndroid Build Coastguard Worker '--java-srcjars', 37*8975f5c5SAndroid Build Coastguard Worker action='append', 38*8975f5c5SAndroid Build Coastguard Worker default=[], 39*8975f5c5SAndroid Build Coastguard Worker help='List of srcjars to include in compilation.') 40*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--classpath', action='append', help='Classpath to use.') 41*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 42*8975f5c5SAndroid Build Coastguard Worker '--processors', 43*8975f5c5SAndroid Build Coastguard Worker action='append', 44*8975f5c5SAndroid Build Coastguard Worker help='GN list of annotation processor main classes.') 45*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 46*8975f5c5SAndroid Build Coastguard Worker '--processorpath', 47*8975f5c5SAndroid Build Coastguard Worker action='append', 48*8975f5c5SAndroid Build Coastguard Worker help='GN list of jars that comprise the classpath used for Annotation ' 49*8975f5c5SAndroid Build Coastguard Worker 'Processors.') 50*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 51*8975f5c5SAndroid Build Coastguard Worker '--processor-args', 52*8975f5c5SAndroid Build Coastguard Worker action='append', 53*8975f5c5SAndroid Build Coastguard Worker help='key=value arguments for the annotation processors.') 54*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--jar-path', help='Jar output path.', required=True) 55*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 56*8975f5c5SAndroid Build Coastguard Worker '--generated-jar-path', 57*8975f5c5SAndroid Build Coastguard Worker required=True, 58*8975f5c5SAndroid Build Coastguard Worker help='Output path for generated source files.') 59*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--warnings-as-errors', 60*8975f5c5SAndroid Build Coastguard Worker action='store_true', 61*8975f5c5SAndroid Build Coastguard Worker help='Treat all warnings as errors.') 62*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--kotlin-jar-path', 63*8975f5c5SAndroid Build Coastguard Worker help='Kotlin jar to be merged into the output jar.') 64*8975f5c5SAndroid Build Coastguard Worker options, unknown_args = parser.parse_known_args(argv) 65*8975f5c5SAndroid Build Coastguard Worker 66*8975f5c5SAndroid Build Coastguard Worker options.classpath = action_helpers.parse_gn_list(options.classpath) 67*8975f5c5SAndroid Build Coastguard Worker options.processorpath = action_helpers.parse_gn_list(options.processorpath) 68*8975f5c5SAndroid Build Coastguard Worker options.processors = action_helpers.parse_gn_list(options.processors) 69*8975f5c5SAndroid Build Coastguard Worker options.java_srcjars = action_helpers.parse_gn_list(options.java_srcjars) 70*8975f5c5SAndroid Build Coastguard Worker 71*8975f5c5SAndroid Build Coastguard Worker files = [] 72*8975f5c5SAndroid Build Coastguard Worker for arg in unknown_args: 73*8975f5c5SAndroid Build Coastguard Worker # Interpret a path prefixed with @ as a file containing a list of sources. 74*8975f5c5SAndroid Build Coastguard Worker if arg.startswith('@'): 75*8975f5c5SAndroid Build Coastguard Worker files.extend(build_utils.ReadSourcesList(arg[1:])) 76*8975f5c5SAndroid Build Coastguard Worker 77*8975f5c5SAndroid Build Coastguard Worker # The target's .sources file contains both Java and Kotlin files. We use 78*8975f5c5SAndroid Build Coastguard Worker # compile_kt.py to compile the Kotlin files to .class and header jars. 79*8975f5c5SAndroid Build Coastguard Worker # Turbine is run only on .java files. 80*8975f5c5SAndroid Build Coastguard Worker java_files = [f for f in files if f.endswith('.java')] 81*8975f5c5SAndroid Build Coastguard Worker 82*8975f5c5SAndroid Build Coastguard Worker cmd = build_utils.JavaCmd() + [ 83*8975f5c5SAndroid Build Coastguard Worker '-classpath', options.turbine_jar_path, 'com.google.turbine.main.Main' 84*8975f5c5SAndroid Build Coastguard Worker ] 85*8975f5c5SAndroid Build Coastguard Worker javac_cmd = ['--release', '17'] 86*8975f5c5SAndroid Build Coastguard Worker 87*8975f5c5SAndroid Build Coastguard Worker # Turbine reads lists from command line args by consuming args until one 88*8975f5c5SAndroid Build Coastguard Worker # starts with double dash (--). Thus command line args should be grouped 89*8975f5c5SAndroid Build Coastguard Worker # together and passed in together. 90*8975f5c5SAndroid Build Coastguard Worker if options.processors: 91*8975f5c5SAndroid Build Coastguard Worker cmd += ['--processors'] 92*8975f5c5SAndroid Build Coastguard Worker cmd += options.processors 93*8975f5c5SAndroid Build Coastguard Worker 94*8975f5c5SAndroid Build Coastguard Worker if options.processorpath: 95*8975f5c5SAndroid Build Coastguard Worker cmd += ['--processorpath'] 96*8975f5c5SAndroid Build Coastguard Worker cmd += options.processorpath 97*8975f5c5SAndroid Build Coastguard Worker 98*8975f5c5SAndroid Build Coastguard Worker if options.processor_args: 99*8975f5c5SAndroid Build Coastguard Worker for arg in options.processor_args: 100*8975f5c5SAndroid Build Coastguard Worker javac_cmd.extend(['-A%s' % arg]) 101*8975f5c5SAndroid Build Coastguard Worker 102*8975f5c5SAndroid Build Coastguard Worker if options.classpath: 103*8975f5c5SAndroid Build Coastguard Worker cmd += ['--classpath'] 104*8975f5c5SAndroid Build Coastguard Worker cmd += options.classpath 105*8975f5c5SAndroid Build Coastguard Worker 106*8975f5c5SAndroid Build Coastguard Worker if options.java_srcjars: 107*8975f5c5SAndroid Build Coastguard Worker cmd += ['--source_jars'] 108*8975f5c5SAndroid Build Coastguard Worker cmd += options.java_srcjars 109*8975f5c5SAndroid Build Coastguard Worker 110*8975f5c5SAndroid Build Coastguard Worker if java_files: 111*8975f5c5SAndroid Build Coastguard Worker # Use jar_path to ensure paths are relative (needed for rbe). 112*8975f5c5SAndroid Build Coastguard Worker files_rsp_path = options.jar_path + '.java_files_list.txt' 113*8975f5c5SAndroid Build Coastguard Worker with open(files_rsp_path, 'w') as f: 114*8975f5c5SAndroid Build Coastguard Worker f.write('\n'.join(java_files)) 115*8975f5c5SAndroid Build Coastguard Worker # Pass source paths as response files to avoid extremely long command 116*8975f5c5SAndroid Build Coastguard Worker # lines that are tedius to debug. 117*8975f5c5SAndroid Build Coastguard Worker cmd += ['--sources'] 118*8975f5c5SAndroid Build Coastguard Worker cmd += ['@' + files_rsp_path] 119*8975f5c5SAndroid Build Coastguard Worker 120*8975f5c5SAndroid Build Coastguard Worker cmd += ['--javacopts'] 121*8975f5c5SAndroid Build Coastguard Worker cmd += javac_cmd 122*8975f5c5SAndroid Build Coastguard Worker cmd += ['--'] # Terminate javacopts 123*8975f5c5SAndroid Build Coastguard Worker 124*8975f5c5SAndroid Build Coastguard Worker # Use AtomicOutput so that output timestamps are not updated when outputs 125*8975f5c5SAndroid Build Coastguard Worker # are not changed. 126*8975f5c5SAndroid Build Coastguard Worker with action_helpers.atomic_output(options.jar_path) as output_jar, \ 127*8975f5c5SAndroid Build Coastguard Worker action_helpers.atomic_output(options.generated_jar_path) as gensrc_jar: 128*8975f5c5SAndroid Build Coastguard Worker cmd += ['--output', output_jar.name, '--gensrc_output', gensrc_jar.name] 129*8975f5c5SAndroid Build Coastguard Worker process_javac_output_partial = functools.partial( 130*8975f5c5SAndroid Build Coastguard Worker ProcessJavacOutput, target_name=options.target_name) 131*8975f5c5SAndroid Build Coastguard Worker 132*8975f5c5SAndroid Build Coastguard Worker logging.debug('Command: %s', cmd) 133*8975f5c5SAndroid Build Coastguard Worker start = time.time() 134*8975f5c5SAndroid Build Coastguard Worker try: 135*8975f5c5SAndroid Build Coastguard Worker build_utils.CheckOutput(cmd, 136*8975f5c5SAndroid Build Coastguard Worker print_stdout=True, 137*8975f5c5SAndroid Build Coastguard Worker stdout_filter=process_javac_output_partial, 138*8975f5c5SAndroid Build Coastguard Worker stderr_filter=process_javac_output_partial, 139*8975f5c5SAndroid Build Coastguard Worker fail_on_output=options.warnings_as_errors) 140*8975f5c5SAndroid Build Coastguard Worker except build_utils.CalledProcessError as e: 141*8975f5c5SAndroid Build Coastguard Worker # Do not output stacktrace as it takes up space on gerrit UI, forcing 142*8975f5c5SAndroid Build Coastguard Worker # you to click though to find the actual compilation error. It's never 143*8975f5c5SAndroid Build Coastguard Worker # interesting to see the Python stacktrace for a Java compilation error. 144*8975f5c5SAndroid Build Coastguard Worker sys.stderr.write(e.output) 145*8975f5c5SAndroid Build Coastguard Worker sys.exit(1) 146*8975f5c5SAndroid Build Coastguard Worker end = time.time() - start 147*8975f5c5SAndroid Build Coastguard Worker logging.info('Header compilation took %ss', end) 148*8975f5c5SAndroid Build Coastguard Worker if options.kotlin_jar_path: 149*8975f5c5SAndroid Build Coastguard Worker with zipfile.ZipFile(output_jar.name, 'a') as out_zip: 150*8975f5c5SAndroid Build Coastguard Worker path_transform = lambda p: p if p.endswith('.class') else None 151*8975f5c5SAndroid Build Coastguard Worker zip_helpers.merge_zips(out_zip, [options.kotlin_jar_path], 152*8975f5c5SAndroid Build Coastguard Worker path_transform=path_transform) 153*8975f5c5SAndroid Build Coastguard Worker 154*8975f5c5SAndroid Build Coastguard Worker if options.depfile: 155*8975f5c5SAndroid Build Coastguard Worker # GN already knows of the java files, so avoid listing individual java files 156*8975f5c5SAndroid Build Coastguard Worker # in the depfile. 157*8975f5c5SAndroid Build Coastguard Worker depfile_deps = (options.classpath + options.processorpath + 158*8975f5c5SAndroid Build Coastguard Worker options.java_srcjars) 159*8975f5c5SAndroid Build Coastguard Worker action_helpers.write_depfile(options.depfile, options.jar_path, 160*8975f5c5SAndroid Build Coastguard Worker depfile_deps) 161*8975f5c5SAndroid Build Coastguard Worker 162*8975f5c5SAndroid Build Coastguard Worker 163*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 164*8975f5c5SAndroid Build Coastguard Worker sys.exit(main(sys.argv)) 165