1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*8975f5c5SAndroid Build Coastguard Worker# 3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2023 The Chromium Authors 4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 6*8975f5c5SAndroid Build Coastguard Worker 7*8975f5c5SAndroid Build Coastguard Workerimport argparse 8*8975f5c5SAndroid Build Coastguard Workerimport logging 9*8975f5c5SAndroid Build Coastguard Workerimport os 10*8975f5c5SAndroid Build Coastguard Workerimport shutil 11*8975f5c5SAndroid Build Coastguard Workerimport sys 12*8975f5c5SAndroid Build Coastguard Workerimport time 13*8975f5c5SAndroid Build Coastguard Worker 14*8975f5c5SAndroid Build Coastguard Workerimport compile_java 15*8975f5c5SAndroid Build Coastguard Worker 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 Worker 19*8975f5c5SAndroid Build Coastguard Worker 20*8975f5c5SAndroid Build Coastguard Workerdef _RunCompiler(args, 21*8975f5c5SAndroid Build Coastguard Worker kotlinc_cmd, 22*8975f5c5SAndroid Build Coastguard Worker source_files, 23*8975f5c5SAndroid Build Coastguard Worker jar_path, 24*8975f5c5SAndroid Build Coastguard Worker intermediates_out_dir=None): 25*8975f5c5SAndroid Build Coastguard Worker """Runs the Kotlin compiler.""" 26*8975f5c5SAndroid Build Coastguard Worker logging.info('Starting _RunCompiler') 27*8975f5c5SAndroid Build Coastguard Worker 28*8975f5c5SAndroid Build Coastguard Worker source_files = source_files.copy() 29*8975f5c5SAndroid Build Coastguard Worker kt_files = [f for f in source_files if f.endswith('.kt')] 30*8975f5c5SAndroid Build Coastguard Worker assert len(kt_files) > 0, 'At least one .kt file must be passed in.' 31*8975f5c5SAndroid Build Coastguard Worker 32*8975f5c5SAndroid Build Coastguard Worker java_srcjars = args.java_srcjars 33*8975f5c5SAndroid Build Coastguard Worker 34*8975f5c5SAndroid Build Coastguard Worker # Use jar_path's directory to ensure paths are relative (needed for rbe). 35*8975f5c5SAndroid Build Coastguard Worker temp_dir = jar_path + '.staging' 36*8975f5c5SAndroid Build Coastguard Worker build_utils.DeleteDirectory(temp_dir) 37*8975f5c5SAndroid Build Coastguard Worker os.makedirs(temp_dir) 38*8975f5c5SAndroid Build Coastguard Worker try: 39*8975f5c5SAndroid Build Coastguard Worker classes_dir = os.path.join(temp_dir, 'classes') 40*8975f5c5SAndroid Build Coastguard Worker os.makedirs(classes_dir) 41*8975f5c5SAndroid Build Coastguard Worker 42*8975f5c5SAndroid Build Coastguard Worker input_srcjars_dir = os.path.join(intermediates_out_dir or temp_dir, 43*8975f5c5SAndroid Build Coastguard Worker 'input_srcjars') 44*8975f5c5SAndroid Build Coastguard Worker 45*8975f5c5SAndroid Build Coastguard Worker if java_srcjars: 46*8975f5c5SAndroid Build Coastguard Worker logging.info('Extracting srcjars to %s', input_srcjars_dir) 47*8975f5c5SAndroid Build Coastguard Worker build_utils.MakeDirectory(input_srcjars_dir) 48*8975f5c5SAndroid Build Coastguard Worker for srcjar in args.java_srcjars: 49*8975f5c5SAndroid Build Coastguard Worker source_files += build_utils.ExtractAll(srcjar, 50*8975f5c5SAndroid Build Coastguard Worker no_clobber=True, 51*8975f5c5SAndroid Build Coastguard Worker path=input_srcjars_dir, 52*8975f5c5SAndroid Build Coastguard Worker pattern='*.java') 53*8975f5c5SAndroid Build Coastguard Worker logging.info('Done extracting srcjars') 54*8975f5c5SAndroid Build Coastguard Worker 55*8975f5c5SAndroid Build Coastguard Worker # Don't include the output directory in the initial set of args since it 56*8975f5c5SAndroid Build Coastguard Worker # being in a temp dir makes it unstable (breaks md5 stamping). 57*8975f5c5SAndroid Build Coastguard Worker cmd = list(kotlinc_cmd) 58*8975f5c5SAndroid Build Coastguard Worker cmd += ['-d', classes_dir] 59*8975f5c5SAndroid Build Coastguard Worker 60*8975f5c5SAndroid Build Coastguard Worker if args.classpath: 61*8975f5c5SAndroid Build Coastguard Worker cmd += ['-classpath', ':'.join(args.classpath)] 62*8975f5c5SAndroid Build Coastguard Worker 63*8975f5c5SAndroid Build Coastguard Worker # This a kotlinc plugin to generate header files for .kt files, similar to 64*8975f5c5SAndroid Build Coastguard Worker # turbine for .java files. 65*8975f5c5SAndroid Build Coastguard Worker jvm_abi_path = os.path.join(build_utils.KOTLIN_HOME, 'lib', 66*8975f5c5SAndroid Build Coastguard Worker 'jvm-abi-gen.jar') 67*8975f5c5SAndroid Build Coastguard Worker cmd += [ 68*8975f5c5SAndroid Build Coastguard Worker f'-Xplugin={jvm_abi_path}', '-P', 69*8975f5c5SAndroid Build Coastguard Worker 'plugin:org.jetbrains.kotlin.jvm.abi:outputDir=' + 70*8975f5c5SAndroid Build Coastguard Worker args.interface_jar_path 71*8975f5c5SAndroid Build Coastguard Worker ] 72*8975f5c5SAndroid Build Coastguard Worker 73*8975f5c5SAndroid Build Coastguard Worker # Pass source paths as response files to avoid extremely long command 74*8975f5c5SAndroid Build Coastguard Worker # lines that are tedius to debug. 75*8975f5c5SAndroid Build Coastguard Worker source_files_rsp_path = os.path.join(temp_dir, 'files_list.txt') 76*8975f5c5SAndroid Build Coastguard Worker with open(source_files_rsp_path, 'w') as f: 77*8975f5c5SAndroid Build Coastguard Worker f.write(' '.join(source_files)) 78*8975f5c5SAndroid Build Coastguard Worker cmd += ['@' + source_files_rsp_path] 79*8975f5c5SAndroid Build Coastguard Worker 80*8975f5c5SAndroid Build Coastguard Worker # Explicitly set JAVA_HOME since some bots do not have this already set. 81*8975f5c5SAndroid Build Coastguard Worker env = os.environ.copy() 82*8975f5c5SAndroid Build Coastguard Worker env['JAVA_HOME'] = build_utils.JAVA_HOME 83*8975f5c5SAndroid Build Coastguard Worker 84*8975f5c5SAndroid Build Coastguard Worker logging.debug('Build command %s', cmd) 85*8975f5c5SAndroid Build Coastguard Worker start = time.time() 86*8975f5c5SAndroid Build Coastguard Worker build_utils.CheckOutput(cmd, 87*8975f5c5SAndroid Build Coastguard Worker env=env, 88*8975f5c5SAndroid Build Coastguard Worker print_stdout=args.chromium_code, 89*8975f5c5SAndroid Build Coastguard Worker fail_on_output=args.warnings_as_errors) 90*8975f5c5SAndroid Build Coastguard Worker logging.info('Kotlin compilation took %ss', time.time() - start) 91*8975f5c5SAndroid Build Coastguard Worker 92*8975f5c5SAndroid Build Coastguard Worker compile_java.CreateJarFile(jar_path, classes_dir) 93*8975f5c5SAndroid Build Coastguard Worker 94*8975f5c5SAndroid Build Coastguard Worker logging.info('Completed all steps in _RunCompiler') 95*8975f5c5SAndroid Build Coastguard Worker finally: 96*8975f5c5SAndroid Build Coastguard Worker shutil.rmtree(temp_dir) 97*8975f5c5SAndroid Build Coastguard Worker 98*8975f5c5SAndroid Build Coastguard Worker 99*8975f5c5SAndroid Build Coastguard Workerdef _ParseOptions(argv): 100*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 101*8975f5c5SAndroid Build Coastguard Worker action_helpers.add_depfile_arg(parser) 102*8975f5c5SAndroid Build Coastguard Worker 103*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--java-srcjars', 104*8975f5c5SAndroid Build Coastguard Worker action='append', 105*8975f5c5SAndroid Build Coastguard Worker default=[], 106*8975f5c5SAndroid Build Coastguard Worker help='List of srcjars to include in compilation.') 107*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 108*8975f5c5SAndroid Build Coastguard Worker '--generated-dir', 109*8975f5c5SAndroid Build Coastguard Worker help='Subdirectory within target_gen_dir to place extracted srcjars and ' 110*8975f5c5SAndroid Build Coastguard Worker 'annotation processor output for codesearch to find.') 111*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--classpath', action='append', help='Classpath to use.') 112*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 113*8975f5c5SAndroid Build Coastguard Worker '--chromium-code', 114*8975f5c5SAndroid Build Coastguard Worker action='store_true', 115*8975f5c5SAndroid Build Coastguard Worker help='Whether code being compiled should be built with stricter ' 116*8975f5c5SAndroid Build Coastguard Worker 'warnings for chromium code.') 117*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--warnings-as-errors', 118*8975f5c5SAndroid Build Coastguard Worker action='store_true', 119*8975f5c5SAndroid Build Coastguard Worker help='Treat all warnings as errors.') 120*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--jar-path', help='Jar output path.', required=True) 121*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--interface-jar-path', 122*8975f5c5SAndroid Build Coastguard Worker help='Interface jar output path.', 123*8975f5c5SAndroid Build Coastguard Worker required=True) 124*8975f5c5SAndroid Build Coastguard Worker 125*8975f5c5SAndroid Build Coastguard Worker args, extra_args = parser.parse_known_args(argv) 126*8975f5c5SAndroid Build Coastguard Worker 127*8975f5c5SAndroid Build Coastguard Worker args.classpath = action_helpers.parse_gn_list(args.classpath) 128*8975f5c5SAndroid Build Coastguard Worker args.java_srcjars = action_helpers.parse_gn_list(args.java_srcjars) 129*8975f5c5SAndroid Build Coastguard Worker 130*8975f5c5SAndroid Build Coastguard Worker source_files = [] 131*8975f5c5SAndroid Build Coastguard Worker for arg in extra_args: 132*8975f5c5SAndroid Build Coastguard Worker # Interpret a path prefixed with @ as a file containing a list of sources. 133*8975f5c5SAndroid Build Coastguard Worker if arg.startswith('@'): 134*8975f5c5SAndroid Build Coastguard Worker source_files.extend(build_utils.ReadSourcesList(arg[1:])) 135*8975f5c5SAndroid Build Coastguard Worker else: 136*8975f5c5SAndroid Build Coastguard Worker assert not arg.startswith('--'), f'Undefined option {arg}' 137*8975f5c5SAndroid Build Coastguard Worker source_files.append(arg) 138*8975f5c5SAndroid Build Coastguard Worker 139*8975f5c5SAndroid Build Coastguard Worker return args, source_files 140*8975f5c5SAndroid Build Coastguard Worker 141*8975f5c5SAndroid Build Coastguard Worker 142*8975f5c5SAndroid Build Coastguard Workerdef main(argv): 143*8975f5c5SAndroid Build Coastguard Worker build_utils.InitLogging('KOTLINC_DEBUG') 144*8975f5c5SAndroid Build Coastguard Worker argv = build_utils.ExpandFileArgs(argv) 145*8975f5c5SAndroid Build Coastguard Worker args, source_files = _ParseOptions(argv) 146*8975f5c5SAndroid Build Coastguard Worker 147*8975f5c5SAndroid Build Coastguard Worker kotlinc_cmd = [build_utils.KOTLINC_PATH] 148*8975f5c5SAndroid Build Coastguard Worker 149*8975f5c5SAndroid Build Coastguard Worker kotlinc_cmd += [ 150*8975f5c5SAndroid Build Coastguard Worker '-no-jdk', # Avoid depending on the bundled JDK. 151*8975f5c5SAndroid Build Coastguard Worker # Avoid depending on the bundled Kotlin stdlib. This may have a version 152*8975f5c5SAndroid Build Coastguard Worker # skew with the one in //third_party/android_deps (which is the one we 153*8975f5c5SAndroid Build Coastguard Worker # prefer to use). 154*8975f5c5SAndroid Build Coastguard Worker '-no-stdlib', 155*8975f5c5SAndroid Build Coastguard Worker # Avoid depending on the bundled Kotlin reflect libs. 156*8975f5c5SAndroid Build Coastguard Worker '-no-reflect', 157*8975f5c5SAndroid Build Coastguard Worker # We typically set a default of 1G for java commands, see 158*8975f5c5SAndroid Build Coastguard Worker # build_utils.JavaCmd. This may help prevent OOMs. 159*8975f5c5SAndroid Build Coastguard Worker '-J-Xmx1G', 160*8975f5c5SAndroid Build Coastguard Worker ] 161*8975f5c5SAndroid Build Coastguard Worker 162*8975f5c5SAndroid Build Coastguard Worker if args.generated_dir: 163*8975f5c5SAndroid Build Coastguard Worker # Delete any stale files in the generated directory. The purpose of 164*8975f5c5SAndroid Build Coastguard Worker # args.generated_dir is for codesearch. 165*8975f5c5SAndroid Build Coastguard Worker shutil.rmtree(args.generated_dir, True) 166*8975f5c5SAndroid Build Coastguard Worker 167*8975f5c5SAndroid Build Coastguard Worker _RunCompiler(args, 168*8975f5c5SAndroid Build Coastguard Worker kotlinc_cmd, 169*8975f5c5SAndroid Build Coastguard Worker source_files, 170*8975f5c5SAndroid Build Coastguard Worker args.jar_path, 171*8975f5c5SAndroid Build Coastguard Worker intermediates_out_dir=args.generated_dir) 172*8975f5c5SAndroid Build Coastguard Worker 173*8975f5c5SAndroid Build Coastguard Worker if args.depfile: 174*8975f5c5SAndroid Build Coastguard Worker # GN already knows of the source files, so avoid listing individual files 175*8975f5c5SAndroid Build Coastguard Worker # in the depfile. 176*8975f5c5SAndroid Build Coastguard Worker action_helpers.write_depfile(args.depfile, args.jar_path, args.classpath) 177*8975f5c5SAndroid Build Coastguard Worker 178*8975f5c5SAndroid Build Coastguard Worker 179*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 180*8975f5c5SAndroid Build Coastguard Worker sys.exit(main(sys.argv[1:])) 181