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