| Index: build/android/gyp/javac.py
|
| diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py
|
| index c95dc98eaa7c670703a79303ea22b11eaae8b524..728c49d5eef513191a56f85993dbf368898ffbfe 100755
|
| --- a/build/android/gyp/javac.py
|
| +++ b/build/android/gyp/javac.py
|
| @@ -108,6 +108,102 @@ def _CreateManifest(manifest_path, classpath, main_class=None,
|
| f.write(output)
|
|
|
|
|
| +def _ExtractClassFiles(jar_path, dest_dir, java_files):
|
| + """Extracts all .class files not corresponding to |java_files|."""
|
| + # Two challenges exist here:
|
| + # 1. |java_files| have prefixes that are not represented in the the jar paths.
|
| + # 2. A single .java file results in multiple .class files when it contains
|
| + # nested classes.
|
| + # Here's an example:
|
| + # source path: ../../base/android/java/src/org/chromium/Foo.java
|
| + # jar paths: org/chromium/Foo.class, org/chromium/Foo$Inner.class
|
| + # To extract only .class files not related to the given .java files, we strip
|
| + # off ".class" and "$*.class" and use a substring match against java_files.
|
| + def extract_predicate(path):
|
| + if not path.endswith('.class'):
|
| + return False
|
| + path_without_suffix = re.sub(r'(?:\$[^/]+)?\.class$', '', path)
|
| + return not any(path_without_suffix in p for p in java_files)
|
| +
|
| + build_utils.ExtractAll(jar_path, path=dest_dir, predicate=extract_predicate)
|
| +
|
| +
|
| +def _OnStaleMd5(changes, options, javac_cmd, java_files, classpath_inputs,
|
| + runtime_classpath):
|
| + with build_utils.TempDir() as temp_dir:
|
| + srcjars = options.java_srcjars
|
| + # The .excluded.jar contains .class files excluded from the main jar.
|
| + # It is used for incremental compiles.
|
| + excluded_jar_path = options.jar_path.replace('.jar', '.excluded.jar')
|
| +
|
| + classes_dir = os.path.join(temp_dir, 'classes')
|
| + os.makedirs(classes_dir)
|
| +
|
| + changed_paths = None
|
| + if options.incremental and changes.AddedOrModifiedOnly():
|
| + changed_paths = set(changes.IterChangedPaths())
|
| + # Do a full compile if classpath has changed.
|
| + if any(p in changed_paths for p in classpath_inputs):
|
| + changed_paths = None
|
| + else:
|
| + java_files = [p for p in java_files if p in changed_paths]
|
| + srcjars = [p for p in srcjars if p in changed_paths]
|
| +
|
| + if srcjars:
|
| + java_dir = os.path.join(temp_dir, 'java')
|
| + os.makedirs(java_dir)
|
| + for srcjar in options.java_srcjars:
|
| + extract_predicate = None
|
| + if changed_paths:
|
| + changed_subpaths = set(changes.IterChangedSubpaths(srcjar))
|
| + extract_predicate = lambda p: p in changed_subpaths
|
| + build_utils.ExtractAll(srcjar, path=java_dir, pattern='*.java',
|
| + predicate=extract_predicate)
|
| + jar_srcs = build_utils.FindInDirectory(java_dir, '*.java')
|
| + java_files.extend(_FilterJavaFiles(jar_srcs, options.javac_includes))
|
| +
|
| + if java_files:
|
| + if changed_paths:
|
| + # When no files have been removed and the output jar already
|
| + # exists, reuse .class files from the existing jar.
|
| + _ExtractClassFiles(options.jar_path, classes_dir, java_files)
|
| + _ExtractClassFiles(excluded_jar_path, classes_dir, java_files)
|
| + # Add the extracted files to the classpath.
|
| + classpath_idx = javac_cmd.index('-classpath')
|
| + javac_cmd[classpath_idx + 1] += ':' + classes_dir
|
| +
|
| + # 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 = javac_cmd + ['-d', classes_dir] + java_files
|
| +
|
| + build_utils.CheckOutput(
|
| + cmd,
|
| + print_stdout=options.chromium_code,
|
| + stderr_filter=ColorJavacOutput)
|
| +
|
| + if options.main_class or options.manifest_entry:
|
| + entries = []
|
| + if options.manifest_entry:
|
| + entries = [e.split(':') for e in options.manifest_entry]
|
| + manifest_file = os.path.join(temp_dir, 'manifest')
|
| + _CreateManifest(manifest_file, runtime_classpath, options.main_class,
|
| + entries)
|
| + else:
|
| + manifest_file = None
|
| +
|
| + glob = options.jar_excluded_classes
|
| + inclusion_predicate = lambda f: not build_utils.MatchesGlob(f, glob)
|
| + exclusion_predicate = lambda f: not inclusion_predicate(f)
|
| +
|
| + jar.JarDirectory(classes_dir,
|
| + options.jar_path,
|
| + manifest_file=manifest_file,
|
| + predicate=inclusion_predicate)
|
| + jar.JarDirectory(classes_dir,
|
| + excluded_jar_path,
|
| + predicate=exclusion_predicate)
|
| +
|
| +
|
| def _ParseOptions(argv):
|
| parser = optparse.OptionParser()
|
| build_utils.AddDepfileOption(parser)
|
| @@ -136,6 +232,11 @@ def _ParseOptions(argv):
|
| action='store_true',
|
| help='Whether to use interface jars (.interface.jar) when compiling')
|
| parser.add_option(
|
| + '--incremental',
|
| + action='store_true',
|
| + help='Whether to re-use .class files rather than recompiling them '
|
| + '(when possible).')
|
| + parser.add_option(
|
| '--javac-includes',
|
| default='',
|
| help='A list of file patterns. If provided, only java files that match'
|
| @@ -239,62 +340,40 @@ def main(argv):
|
| # trigger a compile warning or error.
|
| javac_cmd.extend(['-XDignore.symbol.file'])
|
|
|
| - # Compute the list of paths that when changed, we need to rebuild.
|
| - input_paths = options.bootclasspath + options.java_srcjars + java_files
|
| + classpath_inputs = options.bootclasspath
|
| # TODO(agrieve): Remove this .TOC heuristic once GYP is no more.
|
| - if not options.use_ijars:
|
| + if options.use_ijars:
|
| + classpath_inputs.extend(compile_classpath)
|
| + else:
|
| for path in compile_classpath:
|
| if os.path.exists(path + '.TOC'):
|
| - input_paths.append(path + '.TOC')
|
| - else:
|
| - input_paths.append(path)
|
| -
|
| - def on_stale_md5():
|
| - with build_utils.TempDir() as temp_dir:
|
| - if options.java_srcjars:
|
| - java_dir = os.path.join(temp_dir, 'java')
|
| - os.makedirs(java_dir)
|
| - for srcjar in options.java_srcjars:
|
| - build_utils.ExtractAll(srcjar, path=java_dir, pattern='*.java')
|
| - jar_srcs = build_utils.FindInDirectory(java_dir, '*.java')
|
| - java_files.extend(_FilterJavaFiles(jar_srcs, options.javac_includes))
|
| -
|
| - classes_dir = os.path.join(temp_dir, 'classes')
|
| - os.makedirs(classes_dir)
|
| -
|
| - if java_files:
|
| - # 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 = javac_cmd + ['-d', classes_dir] + java_files
|
| -
|
| - build_utils.CheckOutput(
|
| - cmd,
|
| - print_stdout=options.chromium_code,
|
| - stderr_filter=ColorJavacOutput)
|
| -
|
| - if options.main_class or options.manifest_entry:
|
| - entries = []
|
| - if options.manifest_entry:
|
| - entries = [e.split(':') for e in options.manifest_entry]
|
| - manifest_file = os.path.join(temp_dir, 'manifest')
|
| - _CreateManifest(manifest_file, runtime_classpath, options.main_class,
|
| - entries)
|
| + classpath_inputs.append(path + '.TOC')
|
| else:
|
| - manifest_file = None
|
| - jar.JarDirectory(classes_dir,
|
| - options.jar_excluded_classes,
|
| - options.jar_path,
|
| - manifest_file=manifest_file)
|
| + classpath_inputs.append(path)
|
| +
|
| + # Compute the list of paths that when changed, we need to rebuild.
|
| + input_paths = classpath_inputs + options.java_srcjars + java_files
|
| +
|
| + output_paths = [
|
| + options.jar_path,
|
| + options.jar_path.replace('.jar', '.excluded.jar'),
|
| + ]
|
|
|
| + # An escape hatch to be able to check if incremental compiles are causing
|
| + # problems.
|
| + force = int(os.environ.get('DISABLE_INCREMENTAL_JAVAC', 0))
|
|
|
| # List python deps in input_strings rather than input_paths since the contents
|
| # of them does not change what gets written to the depsfile.
|
| build_utils.CallAndWriteDepfileIfStale(
|
| - on_stale_md5,
|
| + lambda changes: _OnStaleMd5(changes, options, javac_cmd, java_files,
|
| + classpath_inputs, runtime_classpath),
|
| options,
|
| input_paths=input_paths,
|
| input_strings=javac_cmd,
|
| - output_paths=[options.jar_path])
|
| + output_paths=output_paths,
|
| + force=force,
|
| + pass_changes=True)
|
|
|
|
|
| if __name__ == '__main__':
|
|
|