Home | History | Annotate | Download | only in android
      1 # Copyright 2014 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import("//build/config/android/config.gni")
      6 import("//build/config/android/internal_rules.gni")
      7 import("//tools/grit/grit_rule.gni")
      8 
      9 assert(is_android)
     10 
     11 
     12 # Declare a jni target
     13 #
     14 # This target generates the native jni bindings for a set of .java files.
     15 #
     16 # See base/android/jni_generator/jni_generator.py for more info about the
     17 # format of generating JNI bindings.
     18 #
     19 # Variables
     20 #   sources: list of .java files to generate jni for
     21 #   jni_package: subdirectory path for generated bindings
     22 #
     23 # Example
     24 #   generate_jni("foo_jni") {
     25 #     sources = [
     26 #       "android/java/src/org/chromium/foo/Foo.java",
     27 #       "android/java/src/org/chromium/foo/FooUtil.java",
     28 #     ]
     29 #     jni_package = "foo"
     30 #   }
     31 template("generate_jni") {
     32   if (defined(invoker.testonly)) { testonly = invoker.testonly }
     33 
     34   assert(defined(invoker.sources))
     35   assert(defined(invoker.jni_package))
     36   jni_package = invoker.jni_package
     37   base_output_dir = "${root_gen_dir}/${target_name}/${jni_package}"
     38   jni_output_dir = "${base_output_dir}/jni"
     39 
     40   jni_generator_include = "//base/android/jni_generator/jni_generator_helper.h"
     41 
     42   foreach_target_name = "${target_name}__jni_gen"
     43   action_foreach(foreach_target_name) {
     44     script = "//base/android/jni_generator/jni_generator.py"
     45     depfile = "$target_gen_dir/$target_name.{{source_name_part}}.d"
     46     sources = invoker.sources
     47     inputs = [ jni_generator_include ]
     48     outputs = [
     49       depfile,
     50       "${jni_output_dir}/{{source_name_part}}_jni.h"
     51     ]
     52 
     53     args = [
     54       "--depfile", rebase_path(depfile, root_build_dir),
     55       "--input_file={{source}}",
     56       "--optimize_generation=1",
     57       "--ptr_type=long",
     58       "--output_dir", rebase_path(jni_output_dir, root_build_dir),
     59       "--includes", rebase_path(jni_generator_include, "//"),
     60     ]
     61     if (defined(invoker.jni_generator_jarjar_file)) {
     62       args += [
     63         "--jarjar", rebase_path(jni_generator_jarjar_file, root_build_dir),
     64       ]
     65     }
     66   }
     67 
     68   config("jni_includes_${target_name}") {
     69     include_dirs = [ base_output_dir ]
     70   }
     71 
     72   group(target_name) {
     73     deps = [ ":$foreach_target_name" ]
     74     public_configs = [ ":jni_includes_${target_name}" ]
     75 
     76     if (defined(invoker.deps)) {
     77       deps += invoker.deps
     78     }
     79     if (defined(invoker.public_deps)) {
     80       public_deps = invoker.public_deps
     81     }
     82   }
     83 }
     84 
     85 
     86 # Declare a jni target for a prebuilt jar
     87 #
     88 # This target generates the native jni bindings for a set of classes in a .jar.
     89 #
     90 # See base/android/jni_generator/jni_generator.py for more info about the
     91 # format of generating JNI bindings.
     92 #
     93 # Variables
     94 #   classes: list of .class files in the jar to generate jni for. These should
     95 #     include the full path to the .class file.
     96 #   jni_package: subdirectory path for generated bindings
     97 #   jar_file: the path to the .jar. If not provided, will default to the sdk's
     98 #     android.jar
     99 #
    100 #   deps, public_deps: As normal
    101 #
    102 # Example
    103 #   generate_jar_jni("foo_jni") {
    104 #     classes = [
    105 #       "android/view/Foo.class",
    106 #     ]
    107 #     jni_package = "foo"
    108 #   }
    109 template("generate_jar_jni") {
    110   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    111 
    112   assert(defined(invoker.classes))
    113   assert(defined(invoker.jni_package))
    114 
    115   if (defined(invoker.jar_file)) {
    116     jar_file = invoker.jar_file
    117   } else {
    118     jar_file = android_sdk_jar
    119   }
    120 
    121   jni_package = invoker.jni_package
    122   base_output_dir = "${root_gen_dir}/${target_name}/${jni_package}"
    123   jni_output_dir = "${base_output_dir}/jni"
    124 
    125   jni_generator_include = "//base/android/jni_generator/jni_generator_helper.h"
    126 
    127   # TODO(cjhopman): make jni_generator.py support generating jni for multiple
    128   # .class files from a .jar.
    129   jni_actions = []
    130   foreach(class, invoker.classes) {
    131     _classname_list = []
    132     _classname_list = process_file_template(
    133         [class], "{{source_name_part}}")
    134     classname = _classname_list[0]
    135     jni_target_name = "${target_name}__jni_${classname}"
    136     jni_actions += [ ":$jni_target_name" ]
    137     action(jni_target_name) {
    138       depfile = "$target_gen_dir/$target_name.d"
    139       script = "//base/android/jni_generator/jni_generator.py"
    140       sources = [
    141         jni_generator_include,
    142         jar_file,
    143       ]
    144       outputs = [
    145         depfile,
    146         "${jni_output_dir}/${classname}_jni.h"
    147       ]
    148 
    149       args = [
    150         "--depfile", rebase_path(depfile, root_build_dir),
    151         "--jar_file", rebase_path(jar_file, root_build_dir),
    152         "--input_file", class,
    153         "--optimize_generation=1",
    154         "--ptr_type=long",
    155         "--output_dir", rebase_path(jni_output_dir, root_build_dir),
    156         "--includes", rebase_path(jni_generator_include, root_build_dir),
    157       ]
    158     }
    159   }
    160 
    161   config("jni_includes_${target_name}") {
    162     include_dirs = [ base_output_dir ]
    163   }
    164 
    165   group(target_name) {
    166     deps = jni_actions
    167     if (defined(invoker.deps)) {
    168       deps += invoker.deps
    169     }
    170     if (defined(invoker.public_deps)) {
    171       public_deps = invoker.public_deps
    172     }
    173     public_configs = [ ":jni_includes_${target_name}" ]
    174   }
    175 }
    176 
    177 
    178 # Declare a target for c-preprocessor-generated java files
    179 #
    180 # This target generates java files using the host C pre-processor. Each file in
    181 # sources will be compiled using the C pre-processor. If include_path is
    182 # specified, it will be passed (with --I) to the pre-processor.
    183 #
    184 # This target will create a single .srcjar. Adding this target to an
    185 # android_library target's srcjar_deps will make the generated java files be
    186 # included in that library's final outputs.
    187 #
    188 # Variables
    189 #   sources: list of files to be processed by the C pre-processor. For each
    190 #     file in sources, there will be one .java file in the final .srcjar. For a
    191 #     file named FooBar.template, a java file will be created with name
    192 #     FooBar.java.
    193 #   inputs: additional compile-time dependencies. Any files
    194 #     `#include`-ed in the templates should be listed here.
    195 #   package_name: this will be the subdirectory for each .java file in the
    196 #     .srcjar.
    197 #
    198 # Example
    199 #   java_cpp_template("foo_generated_enum") {
    200 #     sources = [
    201 #       "android/java/templates/Foo.template",
    202 #     ]
    203 #     inputs = [
    204 #       "android/java/templates/native_foo_header.h",
    205 #     ]
    206 #
    207 #     package_name = "org/chromium/base/library_loader"
    208 #     include_path = "android/java/templates"
    209 #   }
    210 template("java_cpp_template") {
    211   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    212 
    213   assert(defined(invoker.sources))
    214   package_name = invoker.package_name + ""
    215 
    216   if (defined(invoker.include_path)) {
    217     include_path = invoker.include_path + ""
    218   } else {
    219     include_path = "//"
    220   }
    221 
    222   action_foreach("${target_name}__apply_gcc") {
    223     script = "//build/android/gyp/gcc_preprocess.py"
    224     if (defined(invoker.inputs)) {
    225       inputs = invoker.inputs + []
    226     }
    227     depfile = "${target_gen_dir}/${target_name}_{{source_name_part}}.d"
    228 
    229     sources = invoker.sources
    230 
    231     gen_dir = "${target_gen_dir}/${target_name}/java_cpp_template/${package_name}"
    232     gcc_template_output_pattern = "${gen_dir}/{{source_name_part}}.java"
    233 
    234     outputs = [
    235       depfile,
    236       gcc_template_output_pattern
    237     ]
    238 
    239     args = [
    240       "--depfile", rebase_path(depfile, root_build_dir),
    241       "--include-path", rebase_path(include_path, root_build_dir),
    242       "--output", rebase_path(gen_dir, root_build_dir) + "/{{source_name_part}}.java",
    243       "--template={{source}}",
    244     ]
    245 
    246     if (defined(invoker.defines)) {
    247       foreach(def, invoker.defines) {
    248         args += ["--defines", def]
    249       }
    250     }
    251   }
    252 
    253   apply_gcc_outputs = get_target_outputs(":${target_name}__apply_gcc")
    254   base_gen_dir = get_label_info(":${target_name}__apply_gcc", "target_gen_dir")
    255 
    256   srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
    257   zip("${target_name}__zip_srcjar") {
    258     inputs = apply_gcc_outputs
    259     output = srcjar_path
    260     base_dir = base_gen_dir
    261   }
    262 
    263   group(target_name) {
    264     deps = [
    265       ":${target_name}__zip_srcjar"
    266     ]
    267   }
    268 }
    269 
    270 # Declare a target for generating Java classes from C++ enums.
    271 #
    272 # This target generates Java files from C++ enums using a script.
    273 #
    274 # This target will create a single .srcjar. Adding this target to an
    275 # android_library target's srcjar_deps will make the generated java files be
    276 # included in that library's final outputs.
    277 #
    278 # Variables
    279 #   sources: list of files to be processed by the script. For each annotated
    280 #     enum contained in the sources files the script will generate a .java
    281 #     file with the same name as the name of the enum.
    282 #
    283 #   outputs: list of outputs, relative to the output_dir. These paths are
    284 #     verified at build time by the script. To get the list programatically run:
    285 #       python build/android/gyp/java_cpp_enum.py --output_dir=. \
    286 #         --print_output_only path/to/header/file.h
    287 #
    288 # Example
    289 #   java_cpp_enum("foo_generated_enum") {
    290 #     sources = [
    291 #       "src/native_foo_header.h",
    292 #     ]
    293 #     outputs = [
    294 #       "org/chromium/FooEnum.java",
    295 #     ]
    296 #   }
    297 template("java_cpp_enum") {
    298   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    299 
    300   assert(defined(invoker.sources))
    301   assert(defined(invoker.outputs))
    302 
    303   action("${target_name}__generate_enum") {
    304     sources = rebase_path(invoker.sources, root_build_dir)
    305     script = "//build/android/gyp/java_cpp_enum.py"
    306     gen_dir = "${target_gen_dir}/${target_name}/enums"
    307     outputs = get_path_info(
    308         rebase_path(invoker.outputs, ".", gen_dir), "abspath")
    309 
    310     args = [
    311       "--output_dir", rebase_path(gen_dir, root_build_dir),
    312     ]
    313     foreach(output, rebase_path(outputs, root_build_dir)) {
    314       args += ["--assert_file", output]
    315     }
    316     args += sources
    317   }
    318 
    319   generate_enum_outputs = get_target_outputs(":${target_name}__generate_enum")
    320   base_gen_dir = get_label_info(":${target_name}__generate_enum",
    321                                 "target_gen_dir")
    322 
    323   srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
    324   zip("${target_name}__zip_srcjar") {
    325     inputs = generate_enum_outputs
    326     output = srcjar_path
    327     base_dir = base_gen_dir
    328   }
    329 
    330   group(target_name) {
    331     deps = [
    332       ":${target_name}__zip_srcjar"
    333     ]
    334   }
    335 }
    336 
    337 
    338 # Declare an Android resources target
    339 #
    340 # This creates a resources zip file that will be used when building an Android
    341 # library or apk and included into a final apk.
    342 #
    343 # To include these resources in a library/apk, this target should be listed in
    344 # the library's deps. A library/apk will also include any resources used by its
    345 # own dependencies.
    346 #
    347 # Variables
    348 #   deps: Specifies the dependencies of this target. Any Android resources
    349 #     listed in deps will be included by libraries/apks that depend on this
    350 #     target.
    351 #   resource_dirs: List of directories containing resources for this target.
    352 #   android_manifest: AndroidManifest.xml for this target. Defaults to
    353 #     //build/android/AndroidManifest.xml.
    354 #   custom_package: java package for generated .java files.
    355 #   v14_verify_only: If true, don't generate v14/v17 resources and just verify
    356 #     that the resources are v14-compliant (see
    357 #     build/android/gyp/generate_v14_compatible_resources.py). Defaults to
    358 #     false.
    359 #
    360 # Example
    361 #   android_resources("foo_resources") {
    362 #     deps = [":foo_strings_grd"]
    363 #     resource_dirs = ["res"]
    364 #     custom_package = "org.chromium.foo"
    365 #   }
    366 template("android_resources") {
    367   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    368 
    369   assert(defined(invoker.resource_dirs))
    370   assert(defined(invoker.android_manifest) || defined(invoker.custom_package))
    371 
    372   base_path = "$target_gen_dir/$target_name"
    373   zip_path = base_path + ".resources.zip"
    374   srcjar_path = base_path + ".srcjar"
    375   build_config = base_path + ".build_config"
    376 
    377   write_build_config("${target_name}__build_config") {
    378     type = "android_resources"
    379     resources_zip = zip_path
    380     srcjar = srcjar_path
    381     if (defined(invoker.deps)) { deps = invoker.deps }
    382     if (defined(invoker.android_manifest)) { android_manifest = invoker.android_manifest }
    383     if (defined(invoker.custom_package)) { custom_package = invoker.custom_package }
    384   }
    385 
    386   android_manifest = "//build/android/AndroidManifest.xml"
    387   if (defined(invoker.android_manifest)) {
    388     android_manifest = invoker.android_manifest
    389   }
    390 
    391   process_resources("${target_name}__process_resources") {
    392     resource_dirs = invoker.resource_dirs
    393     if (defined(invoker.custom_package)) {
    394       custom_package = invoker.custom_package
    395     }
    396 
    397     if (defined(invoker.v14_verify_only)) {
    398       v14_verify_only = invoker.v14_verify_only
    399     }
    400   }
    401 
    402   group(target_name) {
    403     deps = [
    404       ":${target_name}__build_config",
    405       ":${target_name}__process_resources",
    406     ]
    407   }
    408 }
    409 
    410 
    411 # Declare a target that generates localized strings.xml from a .grd file.
    412 #
    413 # If this target is included in the deps of an android resources/library/apk,
    414 # the strings.xml will be included with that target.
    415 #
    416 # Variables
    417 #   deps: Specifies the dependencies of this target.
    418 #   grd_file: Path to the .grd file to generate strings.xml from.
    419 #   outputs: Expected grit outputs (see grit rule).
    420 #
    421 # Example
    422 #  java_strings_grd("foo_strings_grd") {
    423 #    grd_file = "foo_strings.grd"
    424 #  }
    425 template("java_strings_grd") {
    426   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    427 
    428   base_path = "$target_gen_dir/$target_name"
    429   resources_zip = base_path + ".resources.zip"
    430   build_config = base_path + ".build_config"
    431 
    432   write_build_config("${target_name}__build_config") {
    433     type = "android_resources"
    434     if (defined(invoker.deps)) {
    435       deps = invoker.deps
    436     }
    437   }
    438 
    439   # Put grit files into this subdirectory of target_gen_dir.
    440   extra_output_path = target_name + "_grit_output"
    441 
    442   grit_target_name = "${target_name}__grit"
    443   grit_output_dir = "$target_gen_dir/$extra_output_path"
    444   grit(grit_target_name) {
    445     grit_flags = [
    446       "-E", "ANDROID_JAVA_TAGGED_ONLY=false",
    447     ]
    448     output_dir = grit_output_dir
    449     resource_ids = ""
    450     source = invoker.grd_file
    451     outputs = invoker.outputs
    452   }
    453 
    454   # This needs to get outputs from grit's internal target, not the final
    455   # source_set.
    456   generate_strings_outputs = get_target_outputs(":${grit_target_name}_grit")
    457 
    458   zip("${target_name}__zip") {
    459     base_dir = grit_output_dir
    460     inputs = generate_strings_outputs
    461     output = resources_zip
    462   }
    463 
    464   group(target_name) {
    465     deps = [
    466       ":${target_name}__build_config",
    467       ":${target_name}__zip",
    468     ]
    469   }
    470 }
    471 
    472 
    473 # Declare an Android library target
    474 #
    475 # This target creates an Android library containing java code and Android
    476 # resources.
    477 #
    478 # Variables
    479 #   deps: Specifies the dependencies of this target. Java targets in this list
    480 #     will be added to the javac classpath. Android resources in dependencies
    481 #     will be used when building this library.
    482 #   java_files: List of .java files included in this library.
    483 #   srcjar_deps: List of srcjar dependencies. The .java files in the srcjars
    484 #     will be added to java_files and be included in this library.
    485 #   chromium_code: If true, extra analysis warning/errors will be enabled.
    486 #   jar_excluded_patterns: List of patterns of .class files to exclude from the
    487 #     final jar.
    488 #   proguard_preprocess: If true, proguard preprocessing will be run. This can
    489 #     be used to remove unwanted parts of the library.
    490 #   proguard_config: Path to the proguard config for preprocessing.
    491 #
    492 #   DEPRECATED_java_in_dir: Directory containing java files. All .java files in
    493 #     this directory will be included in the library. This is only supported to
    494 #     ease the gyp->gn conversion and will be removed in the future.
    495 #
    496 # Example
    497 #   android_library("foo_java") {
    498 #     java_files = [
    499 #       "android/org/chromium/foo/Foo.java",
    500 #       "android/org/chromium/foo/FooInterface.java",
    501 #       "android/org/chromium/foo/FooService.java",
    502 #     ]
    503 #     deps = [
    504 #       ":bar_java"
    505 #     ]
    506 #     srcjar_deps = [
    507 #       ":foo_generated_enum"
    508 #     ]
    509 #     jar_excluded_patterns = [
    510 #       "*/FooService.class", "*/FooService##*.class"
    511 #     ]
    512 #   }
    513 template("android_library") {
    514   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    515 
    516   assert(defined(invoker.java_files) || defined(invoker.DEPRECATED_java_in_dir))
    517   _base_path = "$target_gen_dir/$target_name"
    518   _build_config = _base_path + ".build_config"
    519   _jar_path = _base_path + ".jar"
    520   _dex_path = _base_path + ".dex.jar"
    521 
    522   write_build_config("${target_name}__build_config") {
    523     type = "android_library"
    524 
    525     deps = []
    526     if (defined(invoker.deps)) {
    527       deps += invoker.deps
    528     }
    529 
    530     build_config = _build_config
    531     jar_path = _jar_path
    532     dex_path = _dex_path
    533   }
    534 
    535   _chromium_code = true
    536   if (defined(invoker.chromium_code)) {
    537     _chromium_code = invoker.chromium_code
    538   }
    539 
    540   android_java_library(target_name) {
    541     chromium_code = _chromium_code
    542     if (defined(invoker.java_files)) {
    543       java_files = invoker.java_files
    544     } else {
    545       DEPRECATED_java_in_dir = invoker.DEPRECATED_java_in_dir
    546     }
    547     build_config = _build_config
    548     jar_path = _jar_path
    549     dex_path = _dex_path
    550 
    551     if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) {
    552       proguard_preprocess = true
    553       proguard_config = invoker.proguard_config
    554     }
    555 
    556     jar_excluded_patterns = [
    557       "*/R.class", "*/R##*.class",
    558       "*/Manifest.class", "*/Manifest##*.class",
    559     ]
    560     if (defined(invoker.jar_excluded_patterns)) {
    561       jar_excluded_patterns += invoker.jar_excluded_patterns
    562     }
    563 
    564     if (defined(invoker.srcjar_deps)) {
    565       srcjar_deps = invoker.srcjar_deps
    566     }
    567   }
    568 }
    569 
    570 
    571 # Declare an Android library target for a prebuilt jar
    572 #
    573 # This target creates an Android library containing java code and Android
    574 # resources.
    575 #
    576 # Variables
    577 #   deps: Specifies the dependencies of this target. Java targets in this list
    578 #     will be added to the javac classpath. Android resources in dependencies
    579 #     will be used when building this library.
    580 #   jar_path: Path to the prebuilt jar.
    581 #   proguard_preprocess: If true, proguard preprocessing will be run. This can
    582 #     be used to remove unwanted parts of the library.
    583 #   proguard_config: Path to the proguard config for preprocessing.
    584 #
    585 # Example
    586 #   android_java_prebuilt("foo_java") {
    587 #     jar_path = "foo.jar"
    588 #     deps = [
    589 #       ":foo_resources",
    590 #       ":bar_java"
    591 #     ]
    592 #   }
    593 template("android_java_prebuilt") {
    594   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    595 
    596   assert(defined(invoker.jar_path))
    597   _base_path = "${target_gen_dir}/$target_name"
    598   _jar_path = _base_path + ".jar"
    599   _dex_path = _base_path + ".dex.jar"
    600   _build_config = _base_path + ".build_config"
    601 
    602   write_build_config("${target_name}__build_config") {
    603     type = "android_library"
    604 
    605     deps = []
    606     if (defined(invoker.deps)) {
    607       deps += invoker.deps
    608     }
    609     build_config = _build_config
    610     jar_path = _jar_path
    611     dex_path = _dex_path
    612   }
    613 
    614   java_prebuilt("${target_name}__process_jar") {
    615     if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) {
    616       proguard_preprocess = true
    617       proguard_config = invoker.proguard_config
    618     }
    619 
    620     build_config = _build_config
    621     input_jar_path = invoker.jar_path
    622     output_jar_path = _jar_path
    623   }
    624 
    625   dex("${target_name}__dex") {
    626     sources = [_jar_path]
    627     output = _dex_path
    628   }
    629 
    630   group(target_name) {
    631     deps = [
    632       ":${target_name}__dex",
    633     ]
    634   }
    635 }
    636 
    637 
    638 
    639 # Declare an Android apk target
    640 #
    641 # This target creates an Android APK containing java code, resources, assets,
    642 # and (possibly) native libraries.
    643 #
    644 # Variables
    645 #   android_manifest: Path to AndroidManifest.xml.
    646 #   datadeps: List of dependencies needed at runtime. These will be built but
    647 #     won't change the generated .apk in any way (in fact they may be built
    648 #     after the .apk is).
    649 #   deps: List of dependencies. All Android java resources and libraries in the
    650 #     "transitive closure" of these dependencies will be included in the apk.
    651 #     Note: this "transitive closure" actually only includes such targets if
    652 #     they are depended on through android_library or android_resources targets
    653 #     (and so not through builtin targets like 'action', 'group', etc).
    654 #   java_files: List of .java files to include in the apk.
    655 #   srcjar_deps: List of srcjar dependencies. The .java files in the srcjars
    656 #      will be added to java_files and be included in this apk.
    657 #   apk_name: Name for final apk.
    658 #   final_apk_path: Path to final built apk. Default is
    659 #     $root_out_dir/apks/$apk_name.apk. Setting this will override apk_name.
    660 #   native_libs: List paths of native libraries to include in this apk. If these
    661 #     libraries depend on other shared_library targets, those dependencies will
    662 #     also be included in the apk.
    663 #   testonly: Marks this target as "test-only".
    664 #
    665 #   DEPRECATED_java_in_dir: Directory containing java files. All .java files in
    666 #     this directory will be included in the library. This is only supported to
    667 #     ease the gyp->gn conversion and will be removed in the future.
    668 #
    669 # Example
    670 #   android_apk("foo_apk") {
    671 #     android_manifest = "AndroidManifest.xml"
    672 #     java_files = [
    673 #       "android/org/chromium/foo/FooApplication.java",
    674 #       "android/org/chromium/foo/FooActivity.java",
    675 #     ]
    676 #     deps = [
    677 #       ":foo_support_java"
    678 #       ":foo_resources"
    679 #     ]
    680 #     srcjar_deps = [
    681 #       ":foo_generated_enum"
    682 #     ]
    683 #     native_libs = [
    684 #       native_lib_path
    685 #     ]
    686 #   }
    687 template("android_apk") {
    688   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    689 
    690   assert(defined(invoker.final_apk_path) || defined(invoker.apk_name))
    691   gen_dir = "$target_gen_dir/$target_name"
    692   base_path = "$gen_dir/$target_name"
    693   build_config = "$base_path.build_config"
    694   resources_zip_path = "$base_path.resources.zip"
    695   all_resources_zip_path = "$base_path.resources.all.zip"
    696   jar_path = "$base_path.jar"
    697   final_dex_path = "$gen_dir/classes.dex"
    698   _template_name = target_name
    699   _final_apk_path = ""
    700   if (defined(invoker.final_apk_path)) {
    701     _final_apk_path = invoker.final_apk_path
    702   } else if (defined(invoker.apk_name)) {
    703     _final_apk_path = "$root_build_dir/apks/" + invoker.apk_name + ".apk"
    704   }
    705   _dist_jar_path_list = process_file_template(
    706       [ _final_apk_path ],
    707       "$root_build_dir/test.lib.java/{{source_name_part}}.jar"
    708       )
    709   _dist_jar_path = _dist_jar_path_list[0]
    710 
    711   _native_libs = []
    712   if (defined(invoker.native_libs)) {
    713     _native_libs = invoker.native_libs
    714     _native_libs_dir = base_path + "/libs"
    715   }
    716 
    717   _keystore_path = android_default_keystore_path
    718   _keystore_name = android_default_keystore_name
    719   _keystore_password = android_default_keystore_password
    720 
    721   if (defined(invoker.keystore_path)) {
    722     _keystore_path = invoker.keystore_path
    723     _keystore_name = invoker.keystore_name
    724     _keystore_password = invoker.keystore_password
    725   }
    726 
    727   _srcjar_deps = []
    728   if (defined(invoker.srcjar_deps)) {
    729     _srcjar_deps += invoker.srcjar_deps
    730   }
    731 
    732   _rebased_build_config = rebase_path(build_config, root_build_dir)
    733 
    734   write_build_config("${_template_name}__build_config") {
    735     type = "android_apk"
    736     dex_path = final_dex_path
    737     resources_zip = resources_zip_path
    738 
    739     if (defined(invoker.deps)) {
    740       deps = invoker.deps
    741     }
    742 
    743     native_libs = _native_libs
    744   }
    745 
    746   final_deps = []
    747 
    748   final_deps += [":${_template_name}__process_resources"]
    749   process_resources("${_template_name}__process_resources") {
    750     srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
    751     android_manifest = invoker.android_manifest
    752     resource_dirs = ["//build/android/ant/empty/res"]
    753     zip_path = resources_zip_path
    754     generate_constant_ids = true
    755   }
    756   _srcjar_deps += [":${_template_name}__process_resources"]
    757 
    758   if (_native_libs != []) {
    759     _use_chromium_linker = false
    760     _enable_chromium_linker_tests = false
    761     _load_library_from_apk = false
    762     _native_lib_version_name = ""
    763 
    764 
    765     java_cpp_template("${_template_name}__native_libraries_java") {
    766       package_name = "org/chromium/base/library_loader"
    767       sources = [
    768         "//base/android/java/templates/NativeLibraries.template",
    769       ]
    770       inputs = [
    771         build_config,
    772       ]
    773 
    774       defines = [
    775         "NATIVE_LIBRARIES_LIST=" +
    776           "@FileArg($_rebased_build_config:native:java_libraries_list)",
    777         "NATIVE_LIBRARIES_VERSION_NUMBER=\"$_native_lib_version_name\"",
    778       ]
    779       if (_use_chromium_linker) {
    780         defines += ["ENABLED_CHROMIUM_LINKER"]
    781       }
    782       if (_load_library_from_apk) {
    783         defines += ["ENABLE_CHROMIUM_LINKER_LIBRARY_IN_ZIP_FILE"]
    784       }
    785       if (_enable_chromium_linker_tests) {
    786         defines += ["ENABLE_CHROMIUM_LINKER_TESTS"]
    787       }
    788     }
    789     _srcjar_deps += [ ":${_template_name}__native_libraries_java" ]
    790   }
    791 
    792   final_deps += [ ":${_template_name}__java" ]
    793   android_java_library("${_template_name}__java") {
    794     android_manifest = invoker.android_manifest
    795     if (defined(invoker.java_files)) {
    796       java_files = invoker.java_files
    797     } else if (defined(invoker.DEPRECATED_java_in_dir)) {
    798       DEPRECATED_java_in_dir = invoker.DEPRECATED_java_in_dir
    799     } else {
    800       java_files = []
    801     }
    802     srcjar_deps = _srcjar_deps
    803     dex_path = base_path + ".dex.jar"
    804   }
    805 
    806   if (_dist_jar_path != "") {
    807     # TODO(cjhopman): This is only ever needed to calculate the list of tests to
    808     # run. See build/android/pylib/instrumentation/test_jar.py. We should be
    809     # able to just do that calculation at build time instead.
    810     action("${_template_name}__create_dist_jar") {
    811       script = "//build/android/gyp/create_dist_jar.py"
    812       depfile = "$target_gen_dir/$target_name.d"
    813       inputs = [ build_config ]
    814       outputs = [
    815         depfile,
    816         _dist_jar_path,
    817       ]
    818       args = [
    819         "--depfile", rebase_path(depfile, root_build_dir),
    820         "--output", rebase_path(_dist_jar_path, root_build_dir),
    821         "--inputs=@FileArg($_rebased_build_config:dist_jar:dependency_jars)",
    822       ]
    823       inputs += [ jar_path ]
    824       _rebased_jar_path = rebase_path([ jar_path ], root_build_dir)
    825       args += [
    826         "--inputs=$_rebased_jar_path",
    827       ]
    828     }
    829   }
    830 
    831   final_deps += [":${_template_name}__final_dex"]
    832   dex("${_template_name}__final_dex") {
    833     deps = [ ":${_template_name}__java" ]
    834     sources = [ jar_path ]
    835     inputs = [ build_config ]
    836     output = final_dex_path
    837     dex_arg_key = "${_rebased_build_config}:apk_dex:dependency_dex_files"
    838     args = [ "--inputs=@FileArg($dex_arg_key)" ]
    839   }
    840 
    841   if (_native_libs != []) {
    842     copy_ex("${_template_name}__prepare_native") {
    843       clear_dir = true
    844       inputs = [
    845         build_config
    846       ]
    847       dest = "$_native_libs_dir/$android_app_abi"
    848       args = [
    849         "--files=@FileArg(${_rebased_build_config}:native:libraries)",
    850       ]
    851       if (is_debug) {
    852         rebased_gdbserver = rebase_path(android_gdbserver, root_build_dir)
    853         args += [
    854           "--files=[\"$rebased_gdbserver\"]"
    855         ]
    856       }
    857     }
    858   }
    859 
    860   final_deps += [":${_template_name}__create"]
    861   create_apk("${_template_name}__create") {
    862     apk_path = _final_apk_path
    863     android_manifest = invoker.android_manifest
    864     resources_zip = all_resources_zip_path
    865     dex_path = final_dex_path
    866 
    867     if (defined(invoker.asset_location)) {
    868       asset_location = invoker.asset_location
    869     }
    870 
    871     keystore_name = _keystore_name
    872     keystore_path = _keystore_path
    873     keystore_password = _keystore_password
    874 
    875     if (_native_libs != []) {
    876       native_libs_dir = _native_libs_dir
    877       deps = [":${_template_name}__prepare_native"]
    878     }
    879   }
    880 
    881   group(target_name) {
    882     deps = final_deps
    883     if (defined(invoker.datadeps)) {
    884       # TODO(cjhopman): Fix this when group datadeps works.
    885       deps += invoker.datadeps
    886     }
    887   }
    888 }
    889 
    890 
    891 # Declare an Android gtest apk
    892 #
    893 # This target creates an Android apk for running gtest-based unittests.
    894 #
    895 # Variables
    896 #   deps: Specifies the dependencies of this target. These will be passed to
    897 #     the underlying android_apk invocation and should include the java and
    898 #     resource dependencies of the apk.
    899 #   unittests_dep: This should be the label of the gtest native target. This
    900 #     target must be defined previously in the same file.
    901 #   unittests_binary: The name of the binary produced by the unittests_dep
    902 #     target, relative to the root build directory. If unspecified, it assumes
    903 #     the name of the unittests_dep target (which will be correct unless that
    904 #     target specifies an "output_name".
    905 #     TODO(brettw) make this automatic by allowing get_target_outputs to
    906 #     support executables.
    907 #
    908 # Example
    909 #   unittest_apk("foo_unittests_apk") {
    910 #     deps = [ ":foo_java", ":foo_resources" ]
    911 #     unittests_dep = ":foo_unittests"
    912 #   }
    913 template("unittest_apk") {
    914   testonly = true
    915 
    916   assert(defined(invoker.unittests_dep), "Need unittests_dep for $target_name")
    917 
    918   test_suite_name = get_label_info(invoker.unittests_dep, "name")
    919 
    920   if (defined(invoker.unittests_binary)) {
    921     unittests_binary = root_out_dir + "/" + invoker.unittests_binary
    922   } else {
    923     unittests_binary = root_out_dir + "/lib.stripped/lib" + test_suite_name + ".so"
    924   }
    925 
    926   android_apk(target_name) {
    927     _apk_name = test_suite_name
    928     final_apk_path = "$root_build_dir/${_apk_name}_apk/${_apk_name}-debug.apk"
    929     java_files = [
    930       "//testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java"
    931     ]
    932     android_manifest = "//testing/android/java/AndroidManifest.xml"
    933     unittests_outputs = [ unittests_binary ]
    934     native_libs = [unittests_outputs[0]]
    935     if (defined(invoker.deps)) {
    936       deps = invoker.deps
    937     }
    938     datadeps = [
    939       "//tools/android/md5sum",
    940     ]
    941   }
    942 }
    943 
    944 # Generate .java files from .aidl files.
    945 #
    946 # This target will store the .java files in a srcjar and should be included in
    947 # an android_library or android_apk's srcjar_deps.
    948 #
    949 # Variables
    950 #   sources: Paths to .aidl files to compile.
    951 #   import_include: Path to directory containing .java files imported by the
    952 #     .aidl files.
    953 #   interface_file: Preprocessed aidl file to import.
    954 #
    955 # Example
    956 #   android_aidl("foo_aidl") {
    957 #     import_include = "java/src"
    958 #     sources = [
    959 #       "java/src/com/foo/bar/FooBarService.aidl",
    960 #       "java/src/com/foo/bar/FooBarServiceCallback.aidl",
    961 #     ]
    962 #   }
    963 template("android_aidl") {
    964   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    965 
    966   srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
    967   aidl_path = "${android_sdk_build_tools}/aidl"
    968   framework_aidl = "$android_sdk/framework.aidl"
    969 
    970   action(target_name) {
    971     script = "//build/android/gyp/aidl.py"
    972     sources = invoker.sources
    973 
    974     imports = [ framework_aidl ]
    975     if (defined(invoker.interface_file)) {
    976       assert(invoker.interface_file != "")
    977       imports += [ invoker.interface_file ]
    978     }
    979 
    980     inputs = [
    981       aidl_path,
    982     ] + imports
    983 
    984     depfile = "${target_gen_dir}/${target_name}.d"
    985     outputs = [
    986       depfile,
    987       srcjar_path
    988     ]
    989     rebased_imports = rebase_path(imports, root_build_dir)
    990     args = [
    991       "--depfile", rebase_path(depfile, root_build_dir),
    992       "--aidl-path", rebase_path(aidl_path, root_build_dir),
    993       "--imports=$rebased_imports",
    994       "--srcjar", rebase_path(srcjar_path, root_build_dir),
    995     ]
    996     if (defined(invoker.import_include) && invoker.import_include != "") {
    997       # TODO(cjhopman): aidl supports creating a depfile. We should be able to
    998       # switch to constructing a depfile for the overall action from that
    999       # instead of having all the .java files in the include paths as inputs.
   1000       rebased_import_includes = rebase_path(
   1001           [invoker.import_include], root_build_dir)
   1002       args += [ "--includes=$rebased_import_includes" ]
   1003 
   1004       _java_files_build_rel = exec_script(
   1005           "//build/android/gyp/find.py",
   1006           rebase_path([invoker.import_include], root_build_dir),
   1007           "list lines"
   1008           )
   1009       _java_files = rebase_path(_java_files_build_rel, ".", root_build_dir)
   1010       inputs += _java_files
   1011     }
   1012     args += rebase_path(sources, root_build_dir)
   1013   }
   1014 }
   1015 
   1016 # Creates a dist directory for a native executable.
   1017 #
   1018 # Running a native executable on a device requires all the shared library
   1019 # dependencies of that executable. To make it easier to install and run such an
   1020 # executable, this will create a directory containing the native exe and all
   1021 # it's library dependencies.
   1022 #
   1023 # Note: It's usually better to package things as an APK than as a native
   1024 # executable.
   1025 #
   1026 # Variables
   1027 #   dist_dir: Directory for the exe and libraries. Everything in this directory
   1028 #     will be deleted before copying in the exe and libraries.
   1029 #   binary: Path to (stripped) executable.
   1030 #
   1031 # Example
   1032 #   create_native_executable_dist("foo_dist") {
   1033 #     dist_dir = "$root_build_dir/foo_dist"
   1034 #     binary = "$root_build_dir/exe.stripped/foo"
   1035 #   }
   1036 template("create_native_executable_dist") {
   1037   if (defined(invoker.testonly)) { testonly = invoker.testonly }
   1038 
   1039   dist_dir = invoker.dist_dir
   1040   binary = invoker.binary
   1041   final_deps = []
   1042   template_name = target_name
   1043 
   1044   libraries_list = "${target_gen_dir}/${template_name}_library_dependencies.list"
   1045 
   1046   # TODO(gyp)
   1047   #'dependencies': [
   1048   #'<(DEPTH)/build/android/setup.gyp:copy_system_libraries',
   1049   #],
   1050 
   1051   stripped_libraries_dir = "$root_build_dir/lib.stripped"
   1052   final_deps += [ ":${template_name}__find_library_dependencies" ]
   1053   action("${template_name}__find_library_dependencies") {
   1054     script = "//build/android/gyp/write_ordered_libraries.py"
   1055     depfile = "$target_gen_dir/$target_name.d"
   1056     inputs = [
   1057       binary,
   1058       android_readelf,
   1059     ]
   1060     outputs = [
   1061       depfile,
   1062       libraries_list,
   1063     ]
   1064     rebased_binaries = rebase_path([ binary ], root_build_dir)
   1065     args = [
   1066       "--depfile", rebase_path(depfile, root_build_dir),
   1067       "--input-libraries=$rebased_binaries",
   1068       "--libraries-dir", rebase_path(stripped_libraries_dir, root_build_dir),
   1069       "--output", rebase_path(libraries_list, root_build_dir),
   1070       "--readelf", rebase_path(android_readelf, root_build_dir),
   1071     ]
   1072   }
   1073 
   1074   final_deps += [ ":${template_name}__copy_libraries_and_exe" ]
   1075   copy_ex("${template_name}__copy_libraries_and_exe") {
   1076     clear_dir = true
   1077     inputs = [
   1078       binary,
   1079       libraries_list
   1080     ]
   1081     dest = dist_dir
   1082     rebased_binaries_list = rebase_path([ binary ], root_build_dir)
   1083     rebased_libraries_list = rebase_path(libraries_list, root_build_dir)
   1084     args = [
   1085       "--files=$rebased_binaries_list",
   1086       "--files=@FileArg($rebased_libraries_list:libraries)",
   1087     ]
   1088   }
   1089 
   1090   group(target_name) {
   1091     deps = final_deps
   1092   }
   1093 }
   1094