Make javac and jar a single build action

This allows us to more accurately specify the outputs of each action (we
can't specify the .class file outputs easily because determing them
essentially requires compiling the .java files).

The lint action still operates directly on the .class files, so we continue to
support specifying a directory for the .class files (but in a very simple to
remove way).

BUG=359249

Review URL: https://codereview.chromium.org/328893003

git-svn-id: http://src.chromium.org/svn/trunk/src/build@279152 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
This commit is contained in:
cjhopman@chromium.org 2014-06-23 18:42:13 +00:00
Родитель d5cac44d70
Коммит cf328cf8da
5 изменённых файлов: 103 добавлений и 98 удалений

Просмотреть файл

@ -12,32 +12,36 @@ import sys
from util import build_utils
from util import md5_check
def DoJar(options):
class_files = build_utils.FindInDirectory(options.classes_dir, '*.class')
for exclude in build_utils.ParseGypList(options.excluded_classes):
class_files = filter(
lambda f: not fnmatch.fnmatch(f, exclude), class_files)
jar_path = os.path.abspath(options.jar_path)
def Jar(class_files, classes_dir, jar_path):
jar_path = os.path.abspath(jar_path)
# The paths of the files in the jar will be the same as they are passed in to
# the command. Because of this, the command should be run in
# options.classes_dir so the .class file paths in the jar are correct.
jar_cwd = options.classes_dir
jar_cwd = classes_dir
class_files_rel = [os.path.relpath(f, jar_cwd) for f in class_files]
jar_cmd = ['jar', 'cf0', jar_path] + class_files_rel
record_path = '%s.md5.stamp' % options.jar_path
record_path = '%s.md5.stamp' % jar_path
md5_check.CallAndRecordIfStale(
lambda: build_utils.CheckOutput(jar_cmd, cwd=jar_cwd),
record_path=record_path,
input_paths=class_files,
input_strings=jar_cmd)
input_strings=jar_cmd,
force=not os.path.exists(jar_path),
)
build_utils.Touch(options.jar_path)
build_utils.Touch(jar_path, fail_if_missing=True)
def JarDirectory(classes_dir, excluded_classes, jar_path):
class_files = build_utils.FindInDirectory(classes_dir, '*.class')
for exclude in excluded_classes:
class_files = filter(
lambda f: not fnmatch.fnmatch(f, exclude), class_files)
Jar(class_files, classes_dir, jar_path)
def main():
parser = optparse.OptionParser()
parser.add_option('--classes-dir', help='Directory containing .class files.')
@ -48,7 +52,9 @@ def main():
options, _ = parser.parse_args()
DoJar(options)
JarDirectory(options.classes_dir,
build_utils.ParseGypList(options.excluded_classes),
options.jar_path)
if options.stamp:
build_utils.Touch(options.stamp)

Просмотреть файл

@ -7,12 +7,15 @@
import fnmatch
import optparse
import os
import shutil
import re
import sys
from util import build_utils
from util import md5_check
import jar
sys.path.append(build_utils.COLORAMA_ROOT)
import colorama
@ -49,14 +52,10 @@ def ColorJavacOutput(output):
return '\n'.join(map(ApplyColor, output.split('\n')))
def DoJavac(options, args):
output_dir = options.output_dir
src_gendirs = build_utils.ParseGypList(options.src_gendirs)
java_files = args + build_utils.FindInDirectories(src_gendirs, '*.java')
if options.javac_includes:
javac_includes = build_utils.ParseGypList(options.javac_includes)
def DoJavac(
classpath, javac_includes, classes_dir, chromium_code, java_files):
if javac_includes:
javac_includes = build_utils.ParseGypList(javac_includes)
filtered_java_files = []
for f in java_files:
for include in javac_includes:
@ -69,7 +68,7 @@ def DoJavac(options, args):
# crash... Sorted order works, so use that.
# See https://code.google.com/p/guava-libraries/issues/detail?id=950
java_files.sort()
classpath = build_utils.ParseGypList(options.classpath)
classpath = build_utils.ParseGypList(classpath)
jar_inputs = []
for path in classpath:
@ -83,8 +82,8 @@ def DoJavac(options, args):
'-source', '1.5',
'-target', '1.5',
'-classpath', ':'.join(classpath),
'-d', output_dir]
if options.chromium_code:
'-d', classes_dir]
if chromium_code:
javac_args.extend(['-Xlint:unchecked', '-Xlint:deprecation'])
else:
# XDignore.symbol.file makes javac compile against rt.jar instead of
@ -95,19 +94,12 @@ def DoJavac(options, args):
javac_cmd = ['javac'] + javac_args + java_files
def Compile():
# Delete the classes directory. This ensures that all .class files in the
# output are actually from the input .java files. For example, if a .java
# file is deleted or an inner class is removed, the classes directory should
# not contain the corresponding old .class file after running this action.
build_utils.DeleteDirectory(output_dir)
build_utils.MakeDirectory(output_dir)
build_utils.CheckOutput(
javac_cmd,
print_stdout=options.chromium_code,
print_stdout=chromium_code,
stderr_filter=ColorJavacOutput)
record_path = '%s/javac.md5.stamp' % options.output_dir
record_path = os.path.join(classes_dir, 'javac.md5.stamp')
md5_check.CallAndRecordIfStale(
Compile,
record_path=record_path,
@ -119,21 +111,59 @@ def main():
colorama.init()
parser = optparse.OptionParser()
parser.add_option('--src-gendirs',
parser.add_option(
'--src-gendirs',
help='Directories containing generated java files.')
parser.add_option('--javac-includes',
help='A list of file patterns. If provided, only java files that match' +
'one of the patterns will be compiled.')
parser.add_option('--classpath', help='Classpath for javac.')
parser.add_option('--output-dir', help='Directory for javac output.')
parser.add_option(
'--javac-includes',
help='A list of file patterns. If provided, only java files that match' +
'one of the patterns will be compiled.')
parser.add_option(
'--jar-excluded-classes',
help='List of .class file patterns to exclude from the jar.')
parser.add_option(
'--chromium-code',
type='int',
help='Whether code being compiled should be built with stricter '
'warnings for chromium code.')
parser.add_option(
'--classes-dir',
help='Directory for compiled .class files.')
parser.add_option('--jar-path', help='Jar output path.')
parser.add_option('--stamp', help='Path to touch on success.')
parser.add_option('--chromium-code', type='int', help='Whether code being '
'compiled should be built with stricter warnings for '
'chromium code.')
options, args = parser.parse_args()
DoJavac(options, args)
java_files = args
if options.src_gendirs:
src_gendirs = build_utils.ParseGypList(options.src_gendirs)
java_files += build_utils.FindInDirectories(src_gendirs, '*.java')
with build_utils.TempDir() as classes_dir:
DoJavac(
options.classpath,
options.javac_includes,
classes_dir,
options.chromium_code,
java_files)
if options.jar_path:
jar.JarDirectory(classes_dir,
build_utils.ParseGypList(options.jar_excluded_classes),
options.jar_path)
if options.classes_dir:
# Delete the old classes directory. This ensures that all .class files in
# the output are actually from the input .java files. For example, if a
# .java file is deleted or an inner class is removed, the classes
# directory should not contain the corresponding old .class file after
# running this action.
build_utils.DeleteDirectory(options.classes_dir)
shutil.copytree(classes_dir, options.classes_dir)
if options.stamp:
build_utils.Touch(options.stamp)

Просмотреть файл

@ -41,7 +41,10 @@ def DeleteDirectory(dir_path):
shutil.rmtree(dir_path)
def Touch(path):
def Touch(path, fail_if_missing=False):
if fail_if_missing and not os.path.exists(path):
raise Exception(path + ' doesn\'t exist.')
MakeDirectory(os.path.dirname(path))
with open(path, 'a'):
os.utime(path, None)

Просмотреть файл

@ -230,14 +230,17 @@
],
'outputs': [
'<(compile_stamp)',
'<(javac_jar_path)',
],
'action': [
'python', '<(DEPTH)/build/android/gyp/javac.py',
'--output-dir=<(classes_dir)',
'--classes-dir=<(classes_dir)',
'--classpath=>(input_jars_paths)',
'--src-gendirs=>(generated_src_dirs)',
'--javac-includes=<(javac_includes)',
'--chromium-code=<(chromium_code)',
'--jar-path=<(javac_jar_path)',
'--jar-excluded-classes=<(jar_excluded_classes)',
'--stamp=<(compile_stamp)',
'>@(java_sources)',
]
@ -260,25 +263,6 @@
],
'includes': [ 'android/lint_action.gypi' ],
},
{
'action_name': 'jar_<(_target_name)',
'message': 'Creating <(_target_name) jar',
'inputs': [
'<(DEPTH)/build/android/gyp/util/build_utils.py',
'<(DEPTH)/build/android/gyp/util/md5_check.py',
'<(DEPTH)/build/android/gyp/jar.py',
'<(compile_stamp)',
],
'outputs': [
'<(javac_jar_path)',
],
'action': [
'python', '<(DEPTH)/build/android/gyp/jar.py',
'--classes-dir=<(classes_dir)',
'--jar-path=<(javac_jar_path)',
'--excluded-classes=<(jar_excluded_classes)',
]
},
{
'action_name': 'instr_jar_<(_target_name)',
'message': 'Instrumenting <(_target_name) jar',

Просмотреть файл

@ -94,10 +94,10 @@
'jar_stamp': '<(intermediate_dir)/jar.stamp',
'obfuscate_stamp': '<(intermediate_dir)/obfuscate.stamp',
'strip_stamp': '<(intermediate_dir)/strip.stamp',
'classes_dir': '<(intermediate_dir)/classes',
'classes_final_dir': '<(intermediate_dir)/classes_instr',
'classes_dir': '<(intermediate_dir)/classes/2',
'javac_includes': [],
'jar_excluded_classes': [],
'javac_jar_path': '<(intermediate_dir)/<(_target_name).javac.jar',
'jar_path': '<(PRODUCT_DIR)/lib.java/<(jar_name)',
'obfuscated_jar_path': '<(intermediate_dir)/obfuscated.jar',
'test_jar_path': '<(PRODUCT_DIR)/test.lib.java/<(apk_name).jar',
@ -153,7 +153,6 @@
'apk_package_native_libs_dir': '<(apk_package_native_libs_dir)',
'unsigned_standalone_apk_path': '<(unsigned_standalone_apk_path)',
'extra_native_libs': [],
'apk_dex_input_paths': [ '>@(library_dexed_jars_paths)' ],
},
# Pass the jar path to the apk's "fake" jar target. This would be better as
# direct_dependent_settings, but a variable set by a direct_dependent_settings
@ -540,14 +539,17 @@
],
'outputs': [
'<(compile_stamp)',
'<(javac_jar_path)',
],
'action': [
'python', '<(DEPTH)/build/android/gyp/javac.py',
'--output-dir=<(classes_dir)',
'--classes-dir=<(classes_dir)',
'--classpath=>(input_jars_paths) <(android_sdk_jar)',
'--src-gendirs=>(gen_src_dirs)',
'--javac-includes=<(javac_includes)',
'--chromium-code=<(chromium_code)',
'--jar-path=<(javac_jar_path)',
'--jar-excluded-classes=<(jar_excluded_classes)',
'--stamp=<(compile_stamp)',
'>@(java_sources)',
],
@ -571,42 +573,22 @@
'includes': [ 'android/lint_action.gypi' ],
},
{
'action_name': 'instr_classes_<(_target_name)',
'message': 'Instrumenting <(_target_name) classes',
'action_name': 'instr_jar_<(_target_name)',
'message': 'Instrumenting <(_target_name) jar',
'variables': {
'input_path': '<(classes_dir)',
'output_path': '<(classes_final_dir)',
'input_path': '<(javac_jar_path)',
'output_path': '<(jar_path)',
'stamp_path': '<(instr_stamp)',
'instr_type': 'classes',
'instr_type': 'jar',
},
'inputs': [
'<(compile_stamp)',
],
'outputs': [
'<(instr_stamp)',
],
'includes': [ 'android/instr_action.gypi' ],
},
{
'action_name': 'jar_<(_target_name)',
'message': 'Creating <(_target_name) jar',
'inputs': [
'<(DEPTH)/build/android/gyp/util/build_utils.py',
'<(DEPTH)/build/android/gyp/util/md5_check.py',
'<(DEPTH)/build/android/gyp/jar.py',
'<(instr_stamp)',
],
'outputs': [
'<(jar_stamp)',
'<(jar_path)',
],
'action': [
'python', '<(DEPTH)/build/android/gyp/jar.py',
'--classes-dir=<(classes_final_dir)',
'--jar-path=<(jar_path)',
'--excluded-classes=<(jar_excluded_classes)',
'--stamp=<(jar_stamp)',
]
'inputs': [
'<(javac_jar_path)',
],
'includes': [ 'android/instr_action.gypi' ],
},
{
'action_name': 'obfuscate_<(_target_name)',
@ -696,11 +678,11 @@
{
'action_name': 'dex_<(_target_name)',
'variables': {
'output_path': '<(dex_path)',
'dex_input_paths': [
'>@(apk_dex_input_paths)',
'>@(library_dexed_jars_paths)',
'<(jar_path)',
],
'output_path': '<(dex_path)',
'proguard_enabled_input_path': '<(obfuscated_jar_path)',
},
'target_conditions': [