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