diff options
author | cjhopman <cjhopman@chromium.org> | 2014-11-17 19:39:38 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-18 03:40:00 +0000 |
commit | 3d85c6dd6a6540699d3baf583780577327a0cd13 (patch) | |
tree | e8cad397fdf00209ec10b3d87b041350e70621d5 /build | |
parent | 81d0f757450f8b652bd2f8844ec0970ab9dbb5b4 (diff) | |
download | chromium_src-3d85c6dd6a6540699d3baf583780577327a0cd13.zip chromium_src-3d85c6dd6a6540699d3baf583780577327a0cd13.tar.gz chromium_src-3d85c6dd6a6540699d3baf583780577327a0cd13.tar.bz2 |
Greatly improve (non-android) java support
This change fixes java_library and java_prebuilt to actually construct a
classpath based on their dependents. It adds java_binary that is similar
to java_library but also creates a script in $root_build_dir/bin/ to
actually run a java jar (it builds in the classpath and main class so
that it can just be run like a normal executable).
Adds the flags "android" and "has_android_platform" to the java_library
template. An android_library can depend on a java_library only if the
java_libary has "android == true". A java_library can depend on an
android_library only if the java_libary has
"has_android_platform == true".
This merges several of the paths for compiling java between android and
non-android implementations into a single one that just takes a flag
controlling it's behavior (enabling/disabling dex, for example).
Adds a very simple java_binary target. This can be run to ensure it works,
output is printed, and exit code is propagated.
TBR=brettw
BUG=359249,383646,417843
Review URL: https://codereview.chromium.org/687633003
Cr-Commit-Position: refs/heads/master@{#304555}
Diffstat (limited to 'build')
-rwxr-xr-x | build/android/gyp/create_java_binary_script.py | 76 | ||||
-rw-r--r-- | build/android/gyp/test/BUILD.gn | 11 | ||||
-rw-r--r-- | build/android/gyp/test/java/org/chromium/helloworld/HelloWorldMain.java | 15 | ||||
-rw-r--r-- | build/android/gyp/test/java/org/chromium/helloworld/HelloWorldPrinter.java | 12 | ||||
-rwxr-xr-x | build/android/gyp/write_build_config.py | 67 | ||||
-rw-r--r-- | build/config/android/internal_rules.gni | 505 | ||||
-rw-r--r-- | build/config/android/rules.gni | 367 |
7 files changed, 694 insertions, 359 deletions
diff --git a/build/android/gyp/create_java_binary_script.py b/build/android/gyp/create_java_binary_script.py new file mode 100755 index 0000000..d632728 --- /dev/null +++ b/build/android/gyp/create_java_binary_script.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Creates a simple script to run a java "binary". + +This creates a script that sets up the java command line for running a java +jar. This includes correctly setting the classpath and the main class. +""" + +import optparse +import os +import sys + +from util import build_utils + +# The java command must be executed in the current directory because there may +# be user-supplied paths in the args. The script receives the classpath relative +# to the directory that the script is written in and then, when run, must +# recalculate the paths relative to the current directory. +script_template = """\ +#!/usr/bin/env python +# +# This file was generated by build/android/gyp/create_java_binary_script.py + +import os +import sys + +self_dir = os.path.dirname(__file__) +classpath = [{classpath}] +if os.getcwd() != self_dir: + offset = os.path.relpath(self_dir, os.getcwd()) + classpath = [os.path.join(offset, p) for p in classpath] +java_args = [ + "java", + "-classpath", ":".join(classpath), + \"{main_class}\"] + sys.argv[1:] +os.execvp("java", java_args) +""" + +def main(argv): + argv = build_utils.ExpandFileArgs(argv) + parser = optparse.OptionParser() + build_utils.AddDepfileOption(parser) + parser.add_option('--output', help='Output path for executable script.') + parser.add_option('--jar-path', help='Path to the main jar.') + parser.add_option('--main-class', + help='Name of the java class with the "main" entry point.') + parser.add_option('--classpath', action='append', + help='Classpath for running the jar.') + options, _ = parser.parse_args(argv) + + classpath = [options.jar_path] + for cp_arg in options.classpath: + classpath += build_utils.ParseGypList(cp_arg) + + run_dir = os.path.dirname(options.output) + classpath = [os.path.relpath(p, run_dir) for p in classpath] + + with open(options.output, 'w') as script: + script.write(script_template.format( + classpath=('"%s"' % '", "'.join(classpath)), + main_class=options.main_class)) + + os.chmod(options.output, 0750) + + if options.depfile: + build_utils.WriteDepfile( + options.depfile, + build_utils.GetPythonDependencies()) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/build/android/gyp/test/BUILD.gn b/build/android/gyp/test/BUILD.gn new file mode 100644 index 0000000..6621489 --- /dev/null +++ b/build/android/gyp/test/BUILD.gn @@ -0,0 +1,11 @@ +import("//build/config/android/rules.gni") + +java_library("hello_world_java") { + java_files = [ "java/org/chromium/helloworld/HelloWorldPrinter.java" ] +} + +java_binary("hello_world") { + deps = [ ":hello_world_java" ] + java_files = [ "java/org/chromium/helloworld/HelloWorldMain.java" ] + main_class = "org.chromium.helloworld.HelloWorldMain" +} diff --git a/build/android/gyp/test/java/org/chromium/helloworld/HelloWorldMain.java b/build/android/gyp/test/java/org/chromium/helloworld/HelloWorldMain.java new file mode 100644 index 0000000..10860d8 --- /dev/null +++ b/build/android/gyp/test/java/org/chromium/helloworld/HelloWorldMain.java @@ -0,0 +1,15 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.helloworld; + +public class HelloWorldMain { + public static void main(String[] args) { + if (args.length > 0) { + System.exit(Integer.parseInt(args[0])); + } + HelloWorldPrinter.print(); + } +} + diff --git a/build/android/gyp/test/java/org/chromium/helloworld/HelloWorldPrinter.java b/build/android/gyp/test/java/org/chromium/helloworld/HelloWorldPrinter.java new file mode 100644 index 0000000..b09673e --- /dev/null +++ b/build/android/gyp/test/java/org/chromium/helloworld/HelloWorldPrinter.java @@ -0,0 +1,12 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.helloworld; + +public class HelloWorldPrinter { + public static void print() { + System.out.println("Hello, world!"); + } +} + diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index 722d18c..d26e6d3 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py @@ -12,10 +12,6 @@ things like: the javac classpath, the list of android resources dependencies, etc. It also includes the information needed to create the build_config for other targets that depend on that one. -There are several different types of build_configs: - android_library: An android library containing java code. - android_resources: A target containing android resources. - Android build scripts should not refer to the build_config directly, and the build specification should instead pass information in using the special file-arg syntax (see build_utils.py:ExpandFileArgs). That syntax allows passing @@ -76,11 +72,17 @@ def main(argv): help='Java package name for these resources.') parser.add_option('--android-manifest', help='Path to android manifest.') - # android_library/apk options + # java library options parser.add_option('--jar-path', help='Path to target\'s jar output.') + parser.add_option('--supports-android', action='store_true', + help='Whether this library supports running on the Android platform.') + parser.add_option('--requires-android', action='store_true', + help='Whether this library requires running on the Android platform.') + + # android library options parser.add_option('--dex-path', help='Path to target\'s dex output.') - # apk native library options + # native library options parser.add_option('--native-libs', help='List of top-level native libs.') parser.add_option('--readelf-path', help='Path to toolchain\'s readelf.') @@ -91,25 +93,31 @@ def main(argv): if not options.type in [ - 'android_library', 'android_resources', 'android_apk']: + 'java_library', 'android_resources', 'android_apk']: raise Exception('Unknown type: <%s>' % options.type) - required_options = ['build_config'] + { - 'android_library': ['jar_path', 'dex_path'], + 'java_library': ['jar_path'], 'android_resources': ['resources_zip'], 'android_apk': ['jar_path', 'dex_path', 'resources_zip'] }[options.type] if options.native_libs: - required_options += ['readelf_path'] + required_options.append('readelf_path') build_utils.CheckOptions(options, parser, required_options) + if options.type == 'java_library': + if options.supports_android and not options.dex_path: + raise Exception('java_library that supports Android requires a dex path.') + + if options.requires_android and not options.supports_android: + raise Exception( + '--supports-android is required when using --requires-android') + possible_deps_config_paths = build_utils.ParseGypList( options.possible_deps_configs) - allow_unknown_deps = options.type == 'android_apk' unknown_deps = [ c for c in possible_deps_config_paths if not os.path.exists(c)] @@ -123,8 +131,8 @@ def main(argv): direct_deps_configs = [GetDepConfig(p) for p in direct_deps_config_paths] all_deps_configs = [GetDepConfig(p) for p in all_deps_config_paths] - direct_library_deps = DepsOfType('android_library', direct_deps_configs) - all_library_deps = DepsOfType('android_library', all_deps_configs) + direct_library_deps = DepsOfType('java_library', direct_deps_configs) + all_library_deps = DepsOfType('java_library', all_deps_configs) direct_resources_deps = DepsOfType('android_resources', direct_deps_configs) all_resources_deps = DepsOfType('android_resources', all_deps_configs) @@ -132,6 +140,7 @@ def main(argv): # Initialize some common config. config = { 'deps_info': { + 'name': os.path.basename(options.build_config), 'path': options.build_config, 'type': options.type, 'deps_configs': direct_deps_config_paths, @@ -139,16 +148,40 @@ def main(argv): } deps_info = config['deps_info'] - if options.type in ['android_library', 'android_apk']: + + if options.type == 'java_library': + deps_info['requires_android'] = options.requires_android + deps_info['supports_android'] = options.supports_android + + deps_require_android = (all_resources_deps + + [d['name'] for d in direct_library_deps if d['requires_android']]) + deps_not_support_android = ( + [d['name'] for d in direct_library_deps if not d['supports_android']]) + + if deps_require_android and not options.requires_android: + raise Exception('Some deps require building for the Android platform: ' + + str(deps_require_android)) + + if deps_not_support_android and options.supports_android: + raise Exception('Not all deps support the Android platform: ' + + str(deps_not_support_android)) + + + if options.type in ['java_library', 'android_apk']: javac_classpath = [c['jar_path'] for c in direct_library_deps] + java_full_classpath = [c['jar_path'] for c in all_library_deps] deps_info['resources_deps'] = [c['path'] for c in all_resources_deps] deps_info['jar_path'] = options.jar_path - deps_info['dex_path'] = options.dex_path + if options.type == 'android_apk' or options.supports_android: + deps_info['dex_path'] = options.dex_path config['javac'] = { 'classpath': javac_classpath, } + config['java'] = { + 'full_classpath': java_full_classpath + } - if options.type == 'android_library': + if options.type == 'java_library': # Only resources might have srcjars (normal srcjar targets are listed in # srcjar_deps). A resource's srcjar contains the R.java file for those # resources, and (like Android's default build system) we allow a library to @@ -157,9 +190,9 @@ def main(argv): c['srcjar'] for c in direct_resources_deps if 'srcjar' in c] if options.type == 'android_apk': + # Apks will get their resources srcjar explicitly passed to the java step. config['javac']['srcjars'] = [] - if options.type == 'android_resources': deps_info['resources_zip'] = options.resources_zip if options.srcjar: diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index d6711b8..7120bac 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni @@ -55,6 +55,79 @@ template("android_lint") { } +template("dex") { + if (defined(invoker.testonly)) { testonly = invoker.testonly } + + assert(defined(invoker.sources)) + assert(defined(invoker.output)) + action(target_name) { + script = "//build/android/gyp/dex.py" + depfile = "$target_gen_dir/$target_name.d" + sources = invoker.sources + outputs = [depfile, invoker.output] + if (defined(invoker.inputs)) { + inputs = invoker.inputs + } + + if (defined(invoker.deps)) { + deps = invoker.deps + } + + rebased_output = rebase_path(invoker.output, root_build_dir) + + args = [ + "--depfile", rebase_path(depfile, root_build_dir), + "--android-sdk-tools", rebased_android_sdk_build_tools, + "--dex-path", rebased_output, + ] + + if (defined(invoker.no_locals) && invoker.no_locals) { + args += [ + "--no-locals=1" + ] + } + + if (defined(invoker.args)) { + args += invoker.args + } + + args += rebase_path(invoker.sources, root_build_dir) + } +} + + +# Creates a zip archive of the inputs. +# If base_dir is provided, the archive paths will be relative to it. +template("zip") { + if (defined(invoker.testonly)) { testonly = invoker.testonly } + + assert(defined(invoker.inputs)) + assert(defined(invoker.output)) + + rebase_inputs = rebase_path(invoker.inputs, root_build_dir) + rebase_output = rebase_path(invoker.output, root_build_dir) + action(target_name) { + script = "//build/android/gn/zip.py" + depfile = "$target_gen_dir/$target_name.d" + inputs = invoker.inputs + outputs = [ + depfile, + invoker.output + ] + args = [ + "--depfile", rebase_path(depfile, root_build_dir), + "--inputs=$rebase_inputs", + "--output=$rebase_output", + ] + if (defined(invoker.base_dir)) { + args += [ + "--base-dir", rebase_path(invoker.base_dir, root_build_dir) + ] + } + } +} + + # Write the target's .build_config file. This is a json file that contains a # dictionary of information about how to build this target (things that # require knowledge about this target's dependencies and cannot be calculated @@ -73,7 +146,7 @@ template("write_build_config") { type = invoker.type build_config = invoker.build_config - assert(type == "android_apk" || type == "android_library" || type == "android_resources") + assert(type == "android_apk" || type == "java_library" || type == "android_resources") action(target_name) { script = "//build/android/gyp/write_build_config.py" @@ -105,14 +178,43 @@ template("write_build_config") { "--build-config", rebase_path(build_config, root_build_dir), ] - if (type == "android_library" || type == "android_apk") { + is_java_library = type == "java_library" + is_apk = type == "android_apk" + is_android_resources = type == "android_resources" + + supports_android = (is_apk || is_android_resources || + (is_java_library && defined(invoker.supports_android) && + invoker.supports_android)) + requires_android = (is_apk || is_android_resources || + (is_java_library && defined(invoker.requires_android) && + invoker.requires_android)) + + assert(!requires_android || supports_android, "requires_android requires" + + " supports_android") + # Mark these variables as used. + assert(is_java_library || true) + assert(is_apk || true) + assert(is_android_resources || true) + + if (is_java_library || is_apk) { args += [ "--jar-path", rebase_path(invoker.jar_path, root_build_dir), + ] + } + + if (is_apk || (is_java_library && supports_android)) { + args += [ "--dex-path", rebase_path(invoker.dex_path, root_build_dir), ] } + if (supports_android) { + args += [ "--supports-android" ] + } + if (requires_android) { + args += [ "--requires-android" ] + } - if (type == "android_resources" || type == "android_apk") { + if (is_android_resources || is_apk) { assert(defined(invoker.resources_zip)) args += [ "--resources-zip", rebase_path(invoker.resources_zip, root_build_dir), @@ -132,7 +234,7 @@ template("write_build_config") { } } - if (type == "android_apk") { + if (is_apk) { if (defined(invoker.native_libs)) { rebased_native_libs = rebase_path(invoker.native_libs, root_build_dir) rebased_android_readelf = rebase_path(android_readelf, root_build_dir) @@ -152,77 +254,75 @@ template("write_build_config") { } -# Creates a zip archive of the inputs. -# If base_dir is provided, the archive paths will be relative to it. -template("zip") { +template("process_java_prebuilt") { if (defined(invoker.testonly)) { testonly = invoker.testonly } - assert(defined(invoker.inputs)) - assert(defined(invoker.output)) + _input_jar_path = invoker.input_jar_path + _output_jar_path = invoker.output_jar_path + _jar_toc_path = _output_jar_path + ".TOC" - rebase_inputs = rebase_path(invoker.inputs, root_build_dir) - rebase_output = rebase_path(invoker.output, root_build_dir) - action(target_name) { - script = "//build/android/gn/zip.py" + assert(invoker.build_config != "") + + if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) { + _proguard_jar_path = "$android_sdk_root/tools/proguard/lib/proguard.jar" + _proguard_config_path = invoker.proguard_config + _build_config = invoker.build_config + _rebased_build_config = rebase_path(_build_config, root_build_dir) + action("${target_name}__proguard_process") { + script = "//build/android/gyp/proguard.py" + inputs = [ + android_sdk_jar, + _proguard_jar_path, + _build_config, + _input_jar_path, + _proguard_config_path, + ] + depfile = "${target_gen_dir}/${target_name}.d" + outputs = [ + depfile, + _output_jar_path, + ] + args = [ + "--depfile", rebase_path(depfile, root_build_dir), + "--proguard-path", rebase_path(_proguard_jar_path, root_build_dir), + "--input-path", rebase_path(_input_jar_path, root_build_dir), + "--output-path", rebase_path(_output_jar_path, root_build_dir), + "--proguard-config", rebase_path(_proguard_config_path, root_build_dir), + "--classpath", rebased_android_sdk_jar, + "--classpath=@FileArg($_rebased_build_config:javac:classpath)", + ] + } + } else { + copy("${target_name}__copy_jar") { + sources = [_input_jar_path] + outputs = [_output_jar_path] + } + } + + action("${target_name}__jar_toc") { + script = "//build/android/gyp/jar_toc.py" depfile = "$target_gen_dir/$target_name.d" - inputs = invoker.inputs outputs = [ depfile, - invoker.output + _jar_toc_path, + _jar_toc_path + ".md5.stamp" ] + inputs = [ _output_jar_path ] args = [ "--depfile", rebase_path(depfile, root_build_dir), - "--inputs=$rebase_inputs", - "--output=$rebase_output", + "--jar-path", rebase_path(_output_jar_path, root_build_dir), + "--toc-path", rebase_path(_jar_toc_path, root_build_dir), ] - if (defined(invoker.base_dir)) { - args += [ - "--base-dir", rebase_path(invoker.base_dir, root_build_dir) - ] - } } -} - -template("dex") { - if (defined(invoker.testonly)) { testonly = invoker.testonly } - - assert(defined(invoker.sources)) - assert(defined(invoker.output)) - action(target_name) { - script = "//build/android/gyp/dex.py" - depfile = "$target_gen_dir/$target_name.d" - sources = invoker.sources - outputs = [depfile, invoker.output] - if (defined(invoker.inputs)) { - inputs = invoker.inputs - } - - if (defined(invoker.deps)) { - deps = invoker.deps - } - - rebased_output = rebase_path(invoker.output, root_build_dir) - args = [ - "--depfile", rebase_path(depfile, root_build_dir), - "--android-sdk-tools", rebased_android_sdk_build_tools, - "--dex-path", rebased_output, + group(target_name) { + deps = [ + ":${target_name}__jar_toc" ] - - if (defined(invoker.no_locals) && invoker.no_locals) { - args += [ - "--no-locals=1" - ] - } - - if (defined(invoker.args)) { - args += invoker.args - } - - args += rebase_path(invoker.sources, root_build_dir) } } + # Packages resources, assets, dex, and native libraries into an apk. Signs and # zipaligns the apk. template("create_apk") { @@ -379,74 +479,68 @@ template("create_apk") { } } -template("java_prebuilt") { +template("java_prebuilt_impl") { if (defined(invoker.testonly)) { testonly = invoker.testonly } + _supports_android = ( + defined(invoker.supports_android) && invoker.supports_android) - _input_jar_path = invoker.input_jar_path - _output_jar_path = invoker.output_jar_path - _jar_toc_path = _output_jar_path + ".TOC" + assert(defined(invoker.jar_path)) + _base_path = "${target_gen_dir}/$target_name" + _jar_path = _base_path + ".jar" + _build_config = _base_path + ".build_config" - assert(invoker.build_config != "") + if (_supports_android) { + _dex_path = _base_path + ".dex.jar" + } - if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) { - _proguard_jar_path = "$android_sdk_root/tools/proguard/lib/proguard.jar" - _proguard_config_path = invoker.proguard_config - _build_config = invoker.build_config - _rebased_build_config = rebase_path(_build_config, root_build_dir) - action("${target_name}__proguard_process") { - script = "//build/android/gyp/proguard.py" - inputs = [ - android_sdk_jar, - _proguard_jar_path, - _build_config, - _input_jar_path, - _proguard_config_path, - ] - depfile = "${target_gen_dir}/${target_name}.d" - outputs = [ - depfile, - _output_jar_path, - ] - args = [ - "--depfile", rebase_path(depfile, root_build_dir), - "--proguard-path", rebase_path(_proguard_jar_path, root_build_dir), - "--input-path", rebase_path(_input_jar_path, root_build_dir), - "--output-path", rebase_path(_output_jar_path, root_build_dir), - "--proguard-config", rebase_path(_proguard_config_path, root_build_dir), - "--classpath", rebased_android_sdk_jar, - "--classpath=@FileArg($_rebased_build_config:javac:classpath)", - ] + _final_deps = [] + _template_name = target_name + + + _final_deps += [ ":${_template_name}__build_config" ] + write_build_config("${_template_name}__build_config") { + type = "java_library" + supports_android = _supports_android + requires_android = (defined(invoker.requires_android) && + invoker.requires_android) + + deps = [] + if (defined(invoker.deps)) { + deps += invoker.deps } - } else { - copy("${target_name}__copy_jar") { - sources = [_input_jar_path] - outputs = [_output_jar_path] + build_config = _build_config + jar_path = _jar_path + if (_supports_android) { + dex_path = _dex_path } } - action("${target_name}__jar_toc") { - script = "//build/android/gyp/jar_toc.py" - depfile = "$target_gen_dir/$target_name.d" - outputs = [ - depfile, - _jar_toc_path, - _jar_toc_path + ".md5.stamp" - ] - inputs = [ _output_jar_path ] - args = [ - "--depfile", rebase_path(depfile, root_build_dir), - "--jar-path", rebase_path(_output_jar_path, root_build_dir), - "--toc-path", rebase_path(_jar_toc_path, root_build_dir), - ] + _final_deps += [ ":${_template_name}__process_jar" ] + process_java_prebuilt("${_template_name}__process_jar") { + if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) { + proguard_preprocess = true + proguard_config = invoker.proguard_config + } + + build_config = _build_config + input_jar_path = invoker.jar_path + output_jar_path = _jar_path + } + + if (_supports_android) { + _final_deps += [ ":${_template_name}__dex" ] + dex("${_template_name}__dex") { + sources = [_jar_path] + output = _dex_path + } } group(target_name) { - deps = [ - ":${target_name}__jar_toc" - ] + deps = _final_deps } } + # Compiles and jars a set of java files. # # Outputs: @@ -502,10 +596,20 @@ template("compile_java") { # Mark srcjar_deps as used. assert(_srcjar_deps == [] || true) - _system_jars = [ android_sdk_jar ] - action("${target_name}__javac") { + _system_jars = [] + if (defined(invoker.android) && invoker.android) { + _system_jars += [ android_sdk_jar ] + } + + _rebased_build_config = rebase_path(_build_config, root_build_dir) + _rebased_jar_path = rebase_path(_intermediate_jar_path, root_build_dir) + + _template_name = target_name + _final_deps = [ ":${_template_name}__javac" ] + action("${_template_name}__javac") { script = "//build/android/gyp/javac.py" depfile = "$target_gen_dir/$target_name.d" + deps = [] outputs = [ depfile, _intermediate_jar_path, @@ -516,9 +620,7 @@ template("compile_java") { _rebased_system_jars = rebase_path(_system_jars, root_build_dir) _rebased_java_srcjars = rebase_path(_java_srcjars, root_build_dir) - _rebased_build_config = rebase_path(_build_config, root_build_dir) _rebased_depfile = rebase_path(depfile, root_build_dir) - _rebased_jar_path = rebase_path(_intermediate_jar_path, root_build_dir) args = [ "--depfile=$_rebased_depfile", "--classpath=$_rebased_system_jars", @@ -529,13 +631,20 @@ template("compile_java") { "--jar-excluded-classes=$_jar_excluded_patterns", ] if (_chromium_code) { - args += [ "--chromium-code" ] + args += [ "--chromium-code=1" ] + } + + if (defined(invoker.main_class)) { + args += [ + "--main-class", invoker.main_class + ] } args += rebase_path(_java_files, root_build_dir) } - java_prebuilt("${target_name}__finish") { + _final_deps += [ ":${_template_name}__finish" ] + process_java_prebuilt("${_template_name}__finish") { build_config = _build_config input_jar_path = _intermediate_jar_path output_jar_path = _final_jar_path @@ -546,26 +655,68 @@ template("compile_java") { } group(target_name) { - deps = [ - ":${target_name}__javac", - ":${target_name}__finish", - ] + deps = _final_deps } } -# This adds Android-specific parts to the java_library template. -# -# Runs Android lint against the compiled java files. -# Dexes the output jar for inclusion in an APK. -template("android_java_library") { +template("java_library_impl") { if (defined(invoker.testonly)) { testonly = invoker.testonly } assert(defined(invoker.java_files) || defined(invoker.DEPRECATED_java_in_dir) || defined(invoker.srcjars) || defined(invoker.srcjar_deps)) - assert(defined(invoker.build_config)) - assert(defined(invoker.jar_path)) - assert(defined(invoker.dex_path)) + _base_path = "$target_gen_dir/$target_name" + _jar_path = _base_path + ".jar" + if (defined(invoker.jar_path)) { + _jar_path = invoker.jar_path + } + _template_name = target_name + + _final_deps = [] + _final_datadeps = [] + if (defined(invoker.datadeps)) { + _final_datadeps = invoker.datadeps + } + + _supports_android = (defined(invoker.supports_android) && + invoker.supports_android) + _requires_android = (defined(invoker.requires_android) && + invoker.requires_android) + + if (_supports_android) { + _dex_path = _base_path + ".dex.jar" + if (defined(invoker.dex_path)) { + _dex_path = invoker.dex_path + } + } + + if (defined(invoker.override_build_config)) { + _build_config = invoker.override_build_config + } else { + _build_config = _base_path + ".build_config" + _final_deps += [ ":${_template_name}__build_config" ] + write_build_config("${_template_name}__build_config") { + type = "java_library" + supports_android = _supports_android + requires_android = _requires_android + + deps = [] + if (defined(invoker.deps)) { + deps += invoker.deps + } + + build_config = _build_config + jar_path = _jar_path + if (_supports_android) { + dex_path = _dex_path + } + } + } + + _chromium_code = true + if (defined(invoker.chromium_code)) { + _chromium_code = invoker.chromium_code + } _srcjar_deps = [] if (defined(invoker.srcjar_deps)) { @@ -602,60 +753,74 @@ template("android_java_library") { } assert(_java_files != [] || _srcjar_deps != [] || _srcjars != []) - _jar_path = invoker.jar_path - _dex_path = invoker.dex_path - - _android_manifest = "//build/android/AndroidManifest.xml" - if (defined(invoker.android_manifest)) { - _android_manifest = invoker.android_manifest - } - assert(_android_manifest != "") - - _final_deps = [] - _final_datadeps = [] - - compile_java("${target_name}__compile_java") { + _final_deps += [ ":${_template_name}__compile_java" ] + compile_java("${_template_name}__compile_java") { jar_path = _jar_path - if (defined(invoker.jar_excluded_patterns)) { - jar_excluded_patterns = invoker.jar_excluded_patterns - } - build_config = invoker.build_config + build_config = _build_config java_files = _java_files srcjar_deps = _srcjar_deps srcjars = _srcjars - - if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) { - proguard_preprocess = invoker.proguard_preprocess - proguard_config = invoker.proguard_config - } - - if (defined(invoker.dist_jar_path)) { - dist_jar_path = invoker.dist_jar_path + chromium_code = _chromium_code + android = _requires_android + + if (defined(invoker.jar_excluded_patterns)) { jar_excluded_patterns = invoker.jar_excluded_patterns } + if (defined(invoker.main_class)) { main_class = invoker.main_class } + if (defined(invoker.proguard_preprocess)) { proguard_preprocess = invoker.proguard_preprocess } + if (defined(invoker.proguard_config)) { proguard_config = invoker.proguard_config } + if (defined(invoker.dist_jar_path)) { dist_jar_path = invoker.dist_jar_path } + } + + if (defined(invoker.main_class)) { + _final_deps += [ ":${_template_name}__binary_script" ] + action("${_template_name}__binary_script") { + script = "//build/android/gyp/create_java_binary_script.py" + depfile = "$target_gen_dir/$target_name.d" + java_script = "$root_build_dir/bin/$_template_name" + inputs = [ _build_config ] + outputs = [ + depfile, + java_script, + ] + _rebased_build_config = rebase_path(_build_config, root_build_dir) + args = [ + "--depfile", rebase_path(depfile, root_build_dir), + "--output", rebase_path(java_script, root_build_dir), + "--classpath=@FileArg($_rebased_build_config:java:full_classpath)", + "--jar-path", rebase_path(_jar_path, root_build_dir), + "--main-class", invoker.main_class, + ] } } - if (defined(invoker.chromium_code) && invoker.chromium_code) { - _final_datadeps += [ ":${target_name}__lint" ] - android_lint("${target_name}__lint") { - android_manifest = _android_manifest - jar_path = _jar_path - java_files = _java_files + if (_supports_android) { + if (defined(invoker.chromium_code) && invoker.chromium_code) { + _android_manifest = "//build/android/AndroidManifest.xml" + if (defined(invoker.android_manifest)) { + _android_manifest = invoker.android_manifest + } + + _final_datadeps += [ ":${_template_name}__lint" ] + android_lint("${_template_name}__lint") { + android_manifest = _android_manifest + jar_path = _jar_path + java_files = _java_files + } } - } - dex("${target_name}__dex") { - sources = [_jar_path] - output = _dex_path + _final_deps += [ ":${_template_name}__dex" ] + dex("${_template_name}__dex") { + sources = [_jar_path] + output = _dex_path + } } group(target_name) { - deps = [ - ":${target_name}__compile_java", - ":${target_name}__dex", - ] + _final_deps + _final_datadeps + deps = _final_deps + datadeps = _final_datadeps } } + # Runs process_resources.py template("process_resources") { if (defined(invoker.testonly)) { testonly = invoker.testonly } diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index c130dd4..3f54c43 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni @@ -640,6 +640,153 @@ template("java_strings_grd_prebuilt") { } } +# Declare a Java executable target +# +# This target creates an executable from java code and libraries. The executable +# will be in the output folder's /bin/ directory. +# +# Variables +# deps: Specifies the dependencies of this target. Java targets in this list +# will be included in the executable (and the javac classpath). +# +# java_files: List of .java files included in this library. +# srcjar_deps: List of srcjar dependencies. The .java files in the srcjars +# will be added to java_files and be included in this library. +# srcjars: List of srcjars to be included in this library, together with the +# ones obtained from srcjar_deps. +# +# chromium_code: If true, extra analysis warning/errors will be enabled. +# +# datadeps, testonly +# +# Example +# java_library("foo") { +# java_files = [ "org/chromium/foo/FooMain.java" ] +# deps = [ ":bar_java" ] +# main_class = "org.chromium.foo.FooMain" +# } +template("java_binary") { + # TODO(cjhopman): This should not act like a java_library for dependents (i.e. + # dependents shouldn't get the jar in their classpath, etc.). + java_library_impl(target_name) { + if (defined(invoker.DEPRECATED_java_in_dir)) { DEPRECATED_java_in_dir = invoker.DEPRECATED_java_in_dir } + if (defined(invoker.chromium_code)) { chromium_code = invoker.chromium_code } + if (defined(invoker.datadeps)) { deps = invoker.datadeps } + if (defined(invoker.deps)) { deps = invoker.deps } + if (defined(invoker.java_files)) { java_files = invoker.java_files } + if (defined(invoker.srcjar_deps)) { srcjar_deps = invoker.srcjar_deps } + if (defined(invoker.srcjars)) { srcjars = invoker.srcjars } + if (defined(invoker.testonly)) { testonly = invoker.testonly } + + main_class = invoker.main_class + } +} + + +# Declare an java library target +# +# Variables +# deps: Specifies the dependencies of this target. Java targets in this list +# will be added to the javac classpath. +# +# java_files: List of .java files included in this library. +# srcjar_deps: List of srcjar dependencies. The .java files in the srcjars +# will be added to java_files and be included in this library. +# srcjars: List of srcjars to be included in this library, together with the +# ones obtained from srcjar_deps. +# DEPRECATED_java_in_dir: Directory containing java files. All .java files in +# this directory will be included in the library. This is only supported to +# ease the gyp->gn conversion and will be removed in the future. +# +# chromium_code: If true, extra analysis warning/errors will be enabled. +# jar_excluded_patterns: List of patterns of .class files to exclude from the +# final jar. +# +# proguard_preprocess: If true, proguard preprocessing will be run. This can +# be used to remove unwanted parts of the library. +# proguard_config: Path to the proguard config for preprocessing. +# +# supports_android: If true, Android targets (android_library, android_apk) +# may depend on this target. Note: if true, this target must only use the +# subset of Java available on Android. +# requires_android_platform: If true, this library may depend on +# android-specific targets. If this is the case, there should be some +# android-platform-like implementation available at runtime (Android, +# robolectric, etc). +# +# datadeps, testonly +# +# Example +# java_library("foo_java") { +# java_files = [ +# "org/chromium/foo/Foo.java", +# "org/chromium/foo/FooInterface.java", +# "org/chromium/foo/FooService.java", +# ] +# deps = [ +# ":bar_java" +# ] +# srcjar_deps = [ +# ":foo_generated_enum" +# ] +# jar_excluded_patterns = [ +# "*/FooService.class", "*/FooService##*.class" +# ] +# } +template("java_library") { + java_library_impl(target_name) { + if (defined(invoker.DEPRECATED_java_in_dir)) { DEPRECATED_java_in_dir = invoker.DEPRECATED_java_in_dir } + if (defined(invoker.chromium_code)) { chromium_code = invoker.chromium_code } + if (defined(invoker.datadeps)) { deps = invoker.datadeps } + if (defined(invoker.deps)) { deps = invoker.deps } + if (defined(invoker.jar_excluded_patterns)) { jar_excluded_patterns = invoker.jar_excluded_patterns } + if (defined(invoker.java_files)) { java_files = invoker.java_files } + if (defined(invoker.proguard_config)) { proguard_config = invoker.proguard_config } + if (defined(invoker.proguard_preprocess)) { proguard_preprocess = invoker.proguard_preprocess } + if (defined(invoker.srcjar_deps)) { srcjar_deps = invoker.srcjar_deps } + if (defined(invoker.srcjars)) { srcjars = invoker.srcjars } + if (defined(invoker.testonly)) { testonly = invoker.testonly } + if (defined(invoker.jar_path)) { jar_path = invoker.jar_path } + + if (defined(invoker.supports_android) && invoker.supports_android) { + supports_android = true + } + if (defined(invoker.requires_android_platform) + && invoker.requires_android_platform) { + supports_android = true + requires_android = true + } + } +} + + +# Declare an java library target for a prebuilt jar +# +# Variables +# deps: Specifies the dependencies of this target. Java targets in this list +# will be added to the javac classpath. +# jar_path: Path to the prebuilt jar. +# proguard_preprocess: If true, proguard preprocessing will be run. This can +# be used to remove unwanted parts of the library. +# proguard_config: Path to the proguard config for preprocessing. +# +# Example +# java_prebuilt("foo_java") { +# jar_path = "foo.jar" +# deps = [ +# ":foo_resources", +# ":bar_java" +# ] +# } +template("java_prebuilt") { + java_prebuilt_impl(target_name) { + jar_path = invoker.jar_path + if (defined(invoker.testonly)) { testonly = invoker.testonly } + if (defined(invoker.deps)) { deps = invoker.deps } + if (defined(invoker.proguard_config)) { proguard_config = invoker.proguard_config } + if (defined(invoker.proguard_preprocess)) { proguard_preprocess = invoker.proguard_preprocess } + } +} # Declare an Android library target # @@ -650,21 +797,24 @@ template("java_strings_grd_prebuilt") { # deps: Specifies the dependencies of this target. Java targets in this list # will be added to the javac classpath. Android resources in dependencies # will be used when building this library. +# # java_files: List of .java files included in this library. # srcjar_deps: List of srcjar dependencies. The .java files in the srcjars # will be added to java_files and be included in this library. # srcjars: List of srcjars to be included in this library, together with the # ones obtained from srcjar_deps. +# DEPRECATED_java_in_dir: Directory containing java files. All .java files in +# this directory will be included in the library. This is only supported to +# ease the gyp->gn conversion and will be removed in the future. +# # chromium_code: If true, extra analysis warning/errors will be enabled. # jar_excluded_patterns: List of patterns of .class files to exclude from the # final jar. +# # proguard_preprocess: If true, proguard preprocessing will be run. This can # be used to remove unwanted parts of the library. # proguard_config: Path to the proguard config for preprocessing. # -# DEPRECATED_java_in_dir: Directory containing java files. All .java files in -# this directory will be included in the library. This is only supported to -# ease the gyp->gn conversion and will be removed in the future. # # Example # android_library("foo_java") { @@ -684,133 +834,33 @@ template("java_strings_grd_prebuilt") { # ] # } template("android_library") { - if (defined(invoker.testonly)) { testonly = invoker.testonly } - - assert(defined(invoker.java_files) || defined(invoker.DEPRECATED_java_in_dir) - || defined(invoker.srcjars) || defined(invoker.srcjar_deps)) - _base_path = "$target_gen_dir/$target_name" - _build_config = _base_path + ".build_config" - _jar_path = _base_path + ".jar" - if (defined(invoker.dex_path)) { - _dex_path = invoker.dex_path - } else { - _dex_path = _base_path + ".dex.jar" - } - - write_build_config("${target_name}__build_config") { - type = "android_library" - - deps = [] - if (defined(invoker.deps)) { - deps += invoker.deps - } - - build_config = _build_config - jar_path = _jar_path - dex_path = _dex_path - } - - _chromium_code = true - if (defined(invoker.chromium_code)) { - _chromium_code = invoker.chromium_code - } - - android_java_library(target_name) { - chromium_code = _chromium_code - if (defined(invoker.java_files)) { - java_files = invoker.java_files - } else if (defined(invoker.DEPRECATED_java_in_dir)) { - DEPRECATED_java_in_dir = invoker.DEPRECATED_java_in_dir - } - build_config = _build_config - jar_path = _jar_path - dex_path = _dex_path - - if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) { - proguard_preprocess = true - proguard_config = invoker.proguard_config - } - - jar_excluded_patterns = [ + assert(!defined(invoker.jar_path), + "android_library does not support a custom jar path") + java_library_impl(target_name) { + if (defined(invoker.DEPRECATED_java_in_dir)) { DEPRECATED_java_in_dir = invoker.DEPRECATED_java_in_dir } + if (defined(invoker.chromium_code)) { chromium_code = invoker.chromium_code } + if (defined(invoker.datadeps)) { deps = invoker.datadeps } + if (defined(invoker.deps)) { deps = invoker.deps } + if (defined(invoker.jar_excluded_patterns)) { jar_excluded_patterns = invoker.jar_excluded_patterns } + if (defined(invoker.java_files)) { java_files = invoker.java_files } + if (defined(invoker.proguard_config)) { proguard_config = invoker.proguard_config } + if (defined(invoker.proguard_preprocess)) { proguard_preprocess = invoker.proguard_preprocess } + if (defined(invoker.srcjar_deps)) { srcjar_deps = invoker.srcjar_deps } + if (defined(invoker.srcjars)) { srcjars = invoker.srcjars } + if (defined(invoker.testonly)) { testonly = invoker.testonly } + if (defined(invoker.dex_path)) { dex_path = invoker.dex_path } + + supports_android = true + requires_android = true + + if (!defined(jar_excluded_patterns)) { jar_excluded_patterns = [] } + jar_excluded_patterns += [ "*/R.class", "*/R##*.class", "*/Manifest.class", "*/Manifest##*.class", ] - if (defined(invoker.jar_excluded_patterns)) { - jar_excluded_patterns += invoker.jar_excluded_patterns - } - - if (defined(invoker.srcjar_deps)) { - srcjar_deps = invoker.srcjar_deps - } - if (defined(invoker.srcjars)) { - srcjars = invoker.srcjars - } } } -template("java_library") { - if (defined(invoker.testonly)) { testonly = invoker.testonly } - - assert(defined(invoker.java_files) || defined(invoker.DEPRECATED_java_in_dir) - || defined(invoker.srcjars)) - - _srcjar_deps = [] - if (defined(invoker.srcjar_deps)) { - _srcjar_deps = invoker.srcjar_deps - } - - _srcjars = [] - if (defined(invoker.srcjars)) { - _srcjars = invoker.srcjars - } - - _java_files = [] - if (defined(invoker.java_files)) { - _java_files = invoker.java_files - } else if (defined(invoker.DEPRECATED_java_in_dir)) { - _src_dir = invoker.DEPRECATED_java_in_dir + "/src" - _src_dir_exists = exec_script("//build/dir_exists.py", - [ rebase_path(_src_dir, root_build_dir) ], - "string") - assert(_src_dir_exists == "False", - "In GN, java_in_dir should be the fully specified java directory " + - "(i.e. including the trailing \"/src\")") - - _java_files_build_rel = exec_script( - "//build/android/gyp/find.py", - [ - "--pattern", - "*.java", - rebase_path(invoker.DEPRECATED_java_in_dir, root_build_dir) - ], - "list lines" - ) - _java_files = rebase_path(_java_files_build_rel, ".", root_build_dir) - } - assert(_java_files != [] || _srcjar_deps != [] || _srcjars != []) - - # TODO(cjhopman): Write a proper build config so that java library - # dependencies work correctly. - _build_config = "$target_gen_dir/$target_name.build_config" - write_file( - _build_config, - "{ \"javac\": { \"classpath\": [], \"srcjars\": [] } }") - - _jar_path = "$root_build_dir/lib.java/$target_name.jar" - if (defined(invoker.jar_path)) { - _jar_path = invoker.jar_path - } - - compile_java(target_name) { - build_config = _build_config - jar_path = _jar_path - java_files = _java_files - srcjar_deps = _srcjar_deps - srcjars = _srcjars - } -} - - # Declare an Android library target for a prebuilt jar # # This target creates an Android library containing java code and Android @@ -834,47 +884,14 @@ template("java_library") { # ] # } template("android_java_prebuilt") { - if (defined(invoker.testonly)) { testonly = invoker.testonly } - - assert(defined(invoker.jar_path)) - _base_path = "${target_gen_dir}/$target_name" - _jar_path = _base_path + ".jar" - _dex_path = _base_path + ".dex.jar" - _build_config = _base_path + ".build_config" - - write_build_config("${target_name}__build_config") { - type = "android_library" - - deps = [] - if (defined(invoker.deps)) { - deps += invoker.deps - } - build_config = _build_config - jar_path = _jar_path - dex_path = _dex_path - } - - java_prebuilt("${target_name}__process_jar") { - if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) { - proguard_preprocess = true - proguard_config = invoker.proguard_config - } - - build_config = _build_config - input_jar_path = invoker.jar_path - output_jar_path = _jar_path - } - - dex("${target_name}__dex") { - sources = [_jar_path] - output = _dex_path - } - - group(target_name) { - deps = [ - ":${target_name}__build_config", - ":${target_name}__dex", - ] + java_prebuilt_impl(target_name) { + jar_path = invoker.jar_path + supports_android = true + requires_android = true + if (defined(invoker.testonly)) { testonly = invoker.testonly } + if (defined(invoker.deps)) { deps = invoker.deps } + if (defined(invoker.proguard_config)) { proguard_config = invoker.proguard_config } + if (defined(invoker.proguard_preprocess)) { proguard_preprocess = invoker.proguard_preprocess } } } @@ -934,7 +951,7 @@ template("android_apk") { assert(defined(invoker.final_apk_path) || defined(invoker.apk_name)) gen_dir = "$target_gen_dir/$target_name" base_path = "$gen_dir/$target_name" - build_config = "$base_path.build_config" + _build_config = "$base_path.build_config" resources_zip_path = "$base_path.resources.zip" all_resources_zip_path = "$base_path.resources.all.zip" jar_path = "$base_path.jar" @@ -1012,12 +1029,13 @@ template("android_apk") { } } - _rebased_build_config = rebase_path(build_config, root_build_dir) + _rebased_build_config = rebase_path(_build_config, root_build_dir) write_build_config("${_template_name}__build_config") { type = "android_apk" dex_path = final_dex_path resources_zip = resources_zip_path + build_config = _build_config if (defined(invoker.deps)) { deps = invoker.deps @@ -1035,6 +1053,7 @@ template("android_apk") { resource_dirs = ["//build/android/ant/empty/res"] zip_path = resources_zip_path generate_constant_ids = true + build_config = _build_config } _srcjar_deps += [":${_template_name}__process_resources"] @@ -1052,7 +1071,7 @@ template("android_apk") { "//base/android/java/templates/NativeLibraries.template", ] inputs = [ - build_config, + _build_config, ] defines = [ @@ -1074,8 +1093,12 @@ template("android_apk") { } final_deps += [ ":${_template_name}__java" ] - android_java_library("${_template_name}__java") { + java_library_impl("${_template_name}__java") { + supports_android = true + requires_android = true + override_build_config = _build_config android_manifest = invoker.android_manifest + chromium_code = true if (defined(invoker.java_files)) { java_files = invoker.java_files } else if (defined(invoker.DEPRECATED_java_in_dir)) { @@ -1095,7 +1118,7 @@ template("android_apk") { action("${_template_name}__create_dist_jar") { script = "//build/android/gyp/create_dist_jar.py" depfile = "$target_gen_dir/$target_name.d" - inputs = [ build_config ] + inputs = [ _build_config ] outputs = [ depfile, _dist_jar_path, @@ -1117,7 +1140,7 @@ template("android_apk") { dex("${_template_name}__final_dex") { deps = [ ":${_template_name}__java" ] sources = [ jar_path ] - inputs = [ build_config ] + inputs = [ _build_config ] output = final_dex_path dex_arg_key = "${_rebased_build_config}:apk_dex:dependency_dex_files" args = [ "--inputs=@FileArg($dex_arg_key)" ] @@ -1132,7 +1155,7 @@ template("android_apk") { depfile ] inputs = [ - build_config + _build_config ] deps = [] skip_packing_list = [ |