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 
      7 assert(is_android)
      8 
      9 
     10 rebased_android_sdk = rebase_path(android_sdk, root_build_dir)
     11 rebased_android_sdk_root = rebase_path(android_sdk_root, root_build_dir)
     12 rebased_android_sdk_build_tools = rebase_path(android_sdk_build_tools, root_build_dir)
     13 
     14 android_sdk_jar = "$android_sdk/android.jar"
     15 rebased_android_sdk_jar = rebase_path(android_sdk_jar, root_build_dir)
     16 
     17 template("android_lint") {
     18   if (defined(invoker.testonly)) { testonly = invoker.testonly }
     19 
     20   jar_path = invoker.jar_path
     21   android_manifest = invoker.android_manifest
     22   java_files = invoker.java_files
     23   base_path = "$target_gen_dir/$target_name"
     24 
     25   action(target_name) {
     26     script = "//build/android/gyp/lint.py"
     27     result_path = base_path + "/result.xml"
     28     config_path = base_path + "/config.xml"
     29     suppressions_file = "//build/android/lint/suppressions.xml"
     30     inputs = [
     31       suppressions_file,
     32       android_manifest,
     33       jar_path,
     34     ] + java_files
     35 
     36     outputs = [
     37       config_path,
     38       result_path
     39     ]
     40 
     41     rebased_java_files = rebase_path(java_files, root_build_dir)
     42 
     43     args = [
     44       "--lint-path=$rebased_android_sdk_root/tools/lint",
     45       "--config-path", rebase_path(suppressions_file, root_build_dir),
     46       "--manifest-path", rebase_path(android_manifest, root_build_dir),
     47       "--product-dir=.",
     48       "--jar-path", rebase_path(jar_path, root_build_dir),
     49       "--processed-config-path", rebase_path(config_path, root_build_dir),
     50       "--result-path", rebase_path(result_path, root_build_dir),
     51       "--java-files=$rebased_java_files",
     52       "--enable",
     53     ]
     54   }
     55 }
     56 
     57 
     58 # Write the target's .build_config file. This is a json file that contains a
     59 # dictionary of information about how to build this target (things that
     60 # require knowledge about this target's dependencies and cannot be calculated
     61 # at gn-time). There is a special syntax to add a value in that dictionary to
     62 # an action/action_foreachs args:
     63 #   --python-arg=@FileArg($rebased_build_config_path:key0:key1)
     64 # At runtime, such an arg will be replaced by the value in the build_config.
     65 # See build/android/gyp/write_build_config.py and
     66 # build/android/gyp/util/build_utils.py:ExpandFileArgs
     67 template("write_build_config") {
     68   if (defined(invoker.testonly)) { testonly = invoker.testonly }
     69 
     70   assert(defined(invoker.type))
     71   assert(defined(invoker.build_config))
     72 
     73   type = invoker.type
     74   build_config = invoker.build_config
     75 
     76   assert(type == "android_apk" || type == "android_library" || type == "android_resources")
     77 
     78   action(target_name) {
     79     script = "//build/android/gyp/write_build_config.py"
     80     depfile = "$target_gen_dir/$target_name.d"
     81     inputs = []
     82 
     83     deps = []
     84     if (defined(invoker.deps)) {
     85       deps += invoker.deps
     86     }
     87 
     88     outputs = [
     89       depfile,
     90       build_config
     91     ]
     92 
     93     possible_deps_configs = []
     94     foreach(d, deps) {
     95       dep_gen_dir = get_label_info(d, "target_gen_dir")
     96       dep_name = get_label_info(d, "name")
     97       possible_deps_configs += [ "$dep_gen_dir/$dep_name.build_config" ]
     98     }
     99     rebase_possible_deps_configs = rebase_path(possible_deps_configs)
    100 
    101     args = [
    102       "--type", type,
    103       "--depfile", rebase_path(depfile, root_build_dir),
    104       "--possible-deps-configs=$rebase_possible_deps_configs",
    105       "--build-config", rebase_path(build_config, root_build_dir),
    106     ]
    107 
    108     if (type == "android_library" || type == "android_apk") {
    109       args += [
    110         "--jar-path", rebase_path(invoker.jar_path, root_build_dir),
    111         "--dex-path", rebase_path(invoker.dex_path, root_build_dir),
    112       ]
    113     }
    114 
    115     if (type == "android_resources" || type == "android_apk") {
    116       assert(defined(invoker.resources_zip))
    117       args += [
    118         "--resources-zip", rebase_path(invoker.resources_zip, root_build_dir),
    119       ]
    120       if (defined(invoker.android_manifest)) {
    121         inputs += [
    122           invoker.android_manifest
    123         ]
    124         args += [
    125           "--android-manifest", rebase_path(invoker.android_manifest, root_build_dir),
    126         ]
    127       }
    128       if (defined(invoker.custom_package)) {
    129         args += [
    130           "--package-name", invoker.custom_package
    131         ]
    132       }
    133     }
    134 
    135     if (type == "android_apk") {
    136       if (defined(invoker.native_libs)) {
    137         rebased_native_libs = rebase_path(invoker.native_libs, root_build_dir)
    138         rebased_android_readelf = rebase_path(android_readelf, root_build_dir)
    139         args += [
    140           "--native-libs=$rebased_native_libs",
    141           "--readelf-path=$rebased_android_readelf",
    142         ]
    143       }
    144     }
    145 
    146     if (defined(invoker.srcjar)) {
    147       args += [
    148         "--srcjar", rebase_path(invoker.srcjar, root_build_dir)
    149       ]
    150     }
    151   }
    152 }
    153 
    154 
    155 # Creates a zip archive of the inputs.
    156 # If base_dir is provided, the archive paths will be relative to it.
    157 template("zip") {
    158   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    159 
    160   assert(defined(invoker.inputs))
    161   assert(defined(invoker.output))
    162 
    163   rebase_inputs = rebase_path(invoker.inputs, root_build_dir)
    164   rebase_output = rebase_path(invoker.output, root_build_dir)
    165   action(target_name) {
    166     script = "//build/android/gn/zip.py"
    167     depfile = "$target_gen_dir/$target_name.d"
    168     inputs = invoker.inputs
    169     outputs = [
    170       depfile,
    171       invoker.output
    172     ]
    173     args = [
    174       "--depfile", rebase_path(depfile, root_build_dir),
    175       "--inputs=$rebase_inputs",
    176       "--output=$rebase_output",
    177     ]
    178     if (defined(invoker.base_dir)) {
    179       args += [
    180         "--base-dir", rebase_path(invoker.base_dir, root_build_dir)
    181       ]
    182     }
    183   }
    184 }
    185 
    186 template("dex") {
    187   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    188 
    189   assert(defined(invoker.sources))
    190   assert(defined(invoker.output))
    191   action(target_name) {
    192     script = "//build/android/gyp/dex.py"
    193     depfile = "$target_gen_dir/$target_name.d"
    194     sources = invoker.sources
    195     outputs = [depfile, invoker.output]
    196     if (defined(invoker.inputs)) {
    197       inputs = invoker.inputs
    198     }
    199 
    200     if (defined(invoker.deps)) {
    201       deps = invoker.deps
    202     }
    203 
    204     rebased_output = rebase_path(invoker.output, root_build_dir)
    205 
    206     args = [
    207       "--depfile", rebase_path(depfile, root_build_dir),
    208       "--android-sdk-tools", rebased_android_sdk_build_tools,
    209       "--dex-path", rebased_output,
    210     ]
    211 
    212     if (defined(invoker.no_locals) && invoker.no_locals) {
    213       args += [
    214         "--no-locals=1"
    215       ]
    216     }
    217 
    218     if (defined(invoker.args)) {
    219       args += invoker.args
    220     }
    221 
    222     args += rebase_path(invoker.sources, root_build_dir)
    223   }
    224 }
    225 
    226 # Packages resources, assets, dex, and native libraries into an apk. Signs and
    227 # zipaligns the apk.
    228 template("create_apk") {
    229   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    230 
    231   _android_manifest = invoker.android_manifest
    232   _base_path = invoker.base_path
    233   _final_apk_path = invoker.apk_path
    234   _resources_zip = invoker.resources_zip
    235   _dex_path = invoker.dex_path
    236   _keystore_path = invoker.keystore_path
    237   _keystore_name = invoker.keystore_name
    238   _keystore_password = invoker.keystore_password
    239 
    240   _deps = []
    241   if (defined(invoker.deps)) {
    242     _deps = invoker.deps
    243   }
    244 
    245   _native_libs_dir = "//build/android/empty/res"
    246   if (defined(invoker.native_libs_dir)) {
    247       _native_libs_dir = invoker.native_libs_dir
    248   }
    249 
    250   _asset_location = "//build/android/empty/res"
    251   if (defined(invoker.asset_location)) {
    252     _asset_location = invoker.asset_location
    253   }
    254 
    255   _version_code = "0"
    256   _version_name = "Developer Build"
    257 
    258   _base_apk_path = _base_path + ".apk_intermediates"
    259 
    260   _resource_packaged_apk_path = _base_apk_path + ".ap_"
    261   _packaged_apk_path = _base_apk_path + ".unfinished.apk"
    262 
    263 
    264   _configuration_name = "Release"
    265   if (is_debug) {
    266     _configuration_name = "Debug"
    267   }
    268 
    269   action("${target_name}__package_resources") {
    270     deps = _deps
    271 
    272     script = "//build/android/gyp/package_resources.py"
    273     depfile = "${target_gen_dir}/${target_name}.d"
    274     source_prereqs = [
    275       _android_manifest,
    276       _resources_zip,
    277     ]
    278     outputs = [depfile, _resource_packaged_apk_path]
    279 
    280     _rebased_resources_zips = [rebase_path(_resources_zip, root_build_dir)]
    281     args = [
    282         "--depfile", rebase_path(depfile, root_build_dir),
    283         "--android-sdk", rebased_android_sdk,
    284         "--android-sdk-tools", rebased_android_sdk_build_tools,
    285 
    286         "--configuration-name=$_configuration_name",
    287 
    288         "--android-manifest", rebase_path(_android_manifest, root_build_dir),
    289         "--version-code", _version_code,
    290         "--version-name", _version_name,
    291 
    292         "--asset-dir", rebase_path(_asset_location, root_build_dir),
    293         "--resource-zips=$_rebased_resources_zips",
    294 
    295         "--apk-path", rebase_path(_resource_packaged_apk_path, root_build_dir),
    296       ]
    297   }
    298 
    299   action("${target_name}__package") {
    300     script = "//build/android/gyp/ant.py"
    301     _ant_script = "//build/android/ant/apk-package.xml"
    302 
    303     depfile = "$target_gen_dir/$target_name.d"
    304 
    305     source_prereqs = [
    306       _dex_path,
    307       _resource_packaged_apk_path,
    308       _ant_script
    309     ]
    310 
    311     outputs = [
    312       depfile,
    313       _packaged_apk_path,
    314     ]
    315 
    316     _rebased_emma_jar = ""
    317     _rebased_resource_packaged_apk_path = rebase_path(
    318         _resource_packaged_apk_path, root_build_dir)
    319     _rebased_packaged_apk_path = rebase_path(_packaged_apk_path, root_build_dir)
    320     _rebased_native_libs_dir = rebase_path(_native_libs_dir, root_build_dir)
    321     _rebased_dex_path = rebase_path(_dex_path, root_build_dir)
    322     args = [
    323       "--depfile", rebase_path(depfile, root_build_dir),
    324       "--",
    325       "-quiet",
    326       "-DANDROID_SDK_ROOT=$rebased_android_sdk_root",
    327       "-DANDROID_SDK_TOOLS=$rebased_android_sdk_build_tools",
    328       "-DRESOURCE_PACKAGED_APK_NAME=$_rebased_resource_packaged_apk_path",
    329       "-DCONFIGURATION_NAME=$_configuration_name",
    330       "-DNATIVE_LIBS_DIR=$_rebased_native_libs_dir",
    331       "-DOUT_DIR=",
    332       "-DUNSIGNED_APK_PATH=$_rebased_packaged_apk_path",
    333       "-DEMMA_INSTRUMENT=0",
    334       "-DEMMA_DEVICE_JAR=$_rebased_emma_jar",
    335       "-DDEX_FILE_PATH=$_rebased_dex_path",
    336 
    337       "-Dbasedir=.",
    338       "-buildfile", rebase_path(_ant_script, root_build_dir)
    339     ]
    340   }
    341 
    342   action("${target_name}__finalize") {
    343     script = "//build/android/gyp/finalize_apk.py"
    344     depfile = "$target_gen_dir/$target_name.d"
    345 
    346     sources = [_packaged_apk_path]
    347     source_prereqs = [_keystore_path]
    348     outputs = [depfile, _final_apk_path]
    349 
    350     args = [
    351       "--depfile", rebase_path(depfile, root_build_dir),
    352       "--zipalign-path", rebase_path(zipalign_path, root_build_dir),
    353       "--unsigned-apk-path", rebase_path(_packaged_apk_path, root_build_dir),
    354       "--final-apk-path", rebase_path(_final_apk_path, root_build_dir),
    355       "--key-path", rebase_path(_keystore_path, root_build_dir),
    356       "--key-name", _keystore_name,
    357       "--key-passwd", _keystore_password,
    358     ]
    359   }
    360 
    361   group(target_name) {
    362     deps = [":${target_name}__finalize"]
    363   }
    364 }
    365 
    366 template("java_prebuilt") {
    367   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    368 
    369   _input_jar_path = invoker.input_jar_path
    370   _output_jar_path = invoker.output_jar_path
    371   _jar_toc_path = _output_jar_path + ".TOC"
    372 
    373   assert(invoker.build_config != "")
    374 
    375   if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) {
    376     _proguard_jar_path = "$android_sdk_root/tools/proguard/lib/proguard.jar"
    377     _proguard_config_path = invoker.proguard_config
    378     _build_config = invoker.build_config
    379     _rebased_build_config = rebase_path(_build_config, root_build_dir)
    380     action("${target_name}__proguard_process") {
    381       script = "//build/android/gyp/proguard.py"
    382       inputs = [
    383         android_sdk_jar,
    384         _proguard_jar_path,
    385         _build_config,
    386         _input_jar_path,
    387         _proguard_config_path,
    388       ]
    389       depfile = "${target_gen_dir}/${target_name}.d"
    390       outputs = [
    391         depfile,
    392         _output_jar_path,
    393       ]
    394       args = [
    395         "--depfile", rebase_path(depfile, root_build_dir),
    396         "--proguard-path", rebase_path(_proguard_jar_path, root_build_dir),
    397         "--input-path", rebase_path(_input_jar_path, root_build_dir),
    398         "--output-path", rebase_path(_output_jar_path, root_build_dir),
    399         "--proguard-config", rebase_path(_proguard_config_path, root_build_dir),
    400         "--classpath", rebased_android_sdk_jar,
    401         "--classpath=@FileArg($_rebased_build_config:javac:classpath)",
    402       ]
    403     }
    404   } else {
    405     copy("${target_name}__copy_jar") {
    406       sources = [_input_jar_path]
    407       outputs = [_output_jar_path]
    408     }
    409   }
    410 
    411   action("${target_name}__jar_toc") {
    412     script = "//build/android/gyp/jar_toc.py"
    413     depfile = "$target_gen_dir/$target_name.d"
    414     outputs = [
    415       depfile,
    416       _jar_toc_path,
    417       _jar_toc_path + ".md5.stamp"
    418     ]
    419     inputs = [ _output_jar_path ]
    420     args = [
    421       "--depfile", rebase_path(depfile, root_build_dir),
    422       "--jar-path", rebase_path(_output_jar_path, root_build_dir),
    423       "--toc-path", rebase_path(_jar_toc_path, root_build_dir),
    424     ]
    425   }
    426 
    427   group(target_name) {
    428     deps = [
    429       ":${target_name}__jar_toc"
    430     ]
    431   }
    432 }
    433 
    434 # Compiles and jars a set of java files.
    435 #
    436 # Outputs:
    437 #  $jar_path.jar
    438 #  $jar_path.jar.TOC
    439 #
    440 # Variables
    441 #   java_files: List of .java files to compile.
    442 #   java_deps: List of java dependencies. These should all have a .jar output
    443 #     at "${target_gen_dir}/${target_name}.jar.
    444 #   chromium_code: If true, enable extra warnings.
    445 #   srcjar_deps: List of srcjar dependencies. The .java files contained in the
    446 #     dependencies srcjar outputs will be compiled and added to the output jar.
    447 #   jar_path: Use this to explicitly set the output jar path. Defaults to
    448 #     "${target_gen_dir}/${target_name}.jar.
    449 template("java_library") {
    450   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    451 
    452   assert(defined(invoker.java_files))
    453   assert(defined(invoker.build_config))
    454   assert(defined(invoker.jar_path))
    455 
    456   _java_files = invoker.java_files
    457   _final_jar_path = invoker.jar_path
    458   _intermediate_jar_path = "$target_gen_dir/$target_name.initial.jar"
    459 
    460   _build_config = invoker.build_config
    461 
    462   _jar_excluded_patterns = []
    463   if (defined(invoker.jar_excluded_patterns)) {
    464     _jar_excluded_patterns += invoker.jar_excluded_patterns
    465   }
    466 
    467   _chromium_code = false
    468   if (defined(invoker.chromium_code)) {
    469     _chromium_code = invoker.chromium_code
    470   }
    471 
    472   _srcjar_deps = []
    473   if (defined(invoker.srcjar_deps)) {
    474     _srcjar_deps += invoker.srcjar_deps
    475   }
    476 
    477   _java_srcjars = []
    478   foreach(dep, _srcjar_deps) {
    479     _dep_gen_dir = get_label_info(dep, "target_gen_dir")
    480     _dep_name = get_label_info(dep, "name")
    481     _java_srcjars += [ "$_dep_gen_dir/$_dep_name.srcjar" ]
    482   }
    483   # Mark srcjar_deps as used.
    484   assert(_srcjar_deps == [] || true)
    485 
    486   _system_jars = [ android_sdk_jar ]
    487   action("${target_name}__javac") {
    488     script = "//build/android/gyp/javac.py"
    489     depfile = "$target_gen_dir/$target_name.d"
    490     outputs = [
    491       depfile,
    492       _intermediate_jar_path,
    493       _intermediate_jar_path + ".md5.stamp"
    494     ]
    495     sources = _java_files + _java_srcjars
    496     inputs = _system_jars + [ _build_config ]
    497 
    498     _rebased_system_jars = rebase_path(_system_jars, root_build_dir)
    499     _rebased_java_srcjars = rebase_path(_java_srcjars, root_build_dir)
    500     _rebased_build_config = rebase_path(_build_config, root_build_dir)
    501     _rebased_depfile = rebase_path(depfile, root_build_dir)
    502     _rebased_jar_path = rebase_path(_intermediate_jar_path, root_build_dir)
    503     args = [
    504       "--depfile=$_rebased_depfile",
    505       "--classpath=$_rebased_system_jars",
    506       "--classpath=@FileArg($_rebased_build_config:javac:classpath)",
    507       "--jar-path=$_rebased_jar_path",
    508       "--java-srcjars=$_rebased_java_srcjars",
    509       "--java-srcjars=@FileArg($_rebased_build_config:javac:srcjars)",
    510       "--jar-excluded-classes=$_jar_excluded_patterns",
    511     ]
    512     if (_chromium_code) {
    513       args += [ "--chromium-code" ]
    514     }
    515 
    516     args += rebase_path(_java_files, root_build_dir)
    517   }
    518 
    519   java_prebuilt("${target_name}__finish") {
    520     build_config = _build_config
    521     input_jar_path = _intermediate_jar_path
    522     output_jar_path = _final_jar_path
    523     if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) {
    524       proguard_preprocess = invoker.proguard_preprocess
    525       proguard_config = invoker.proguard_config
    526     }
    527   }
    528 
    529   group(target_name) {
    530     deps = [
    531       ":${target_name}__javac",
    532       ":${target_name}__finish",
    533     ]
    534   }
    535 }
    536 
    537 
    538 # This adds Android-specific parts to the java_library template.
    539 #
    540 # Runs Android lint against the compiled java files.
    541 # Dexes the output jar for inclusion in an APK.
    542 template("android_java_library") {
    543   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    544 
    545   assert(defined(invoker.java_files) || defined(invoker.DEPRECATED_java_in_dir))
    546   assert(defined(invoker.build_config))
    547   assert(defined(invoker.jar_path))
    548   assert(defined(invoker.dex_path))
    549 
    550   _srcjar_deps = []
    551   if (defined(invoker.srcjar_deps)) {
    552     _srcjar_deps = invoker.srcjar_deps
    553   }
    554 
    555   _java_files = []
    556   if (defined(invoker.java_files)) {
    557     _java_files = invoker.java_files
    558   } else {
    559     _java_files_build_rel = exec_script(
    560         "//build/android/gyp/find.py",
    561         [
    562           "--pattern",
    563           "*.java",
    564           rebase_path(invoker.DEPRECATED_java_in_dir, root_build_dir)
    565         ],
    566         "list lines"
    567         )
    568     _java_files = rebase_path(_java_files_build_rel, ".", root_build_dir)
    569   }
    570   assert(_java_files != [] || _srcjar_deps != [])
    571 
    572   _jar_path = invoker.jar_path
    573   _dex_path = invoker.dex_path
    574 
    575   _android_manifest = "//build/android/AndroidManifest.xml"
    576   if (defined(invoker.android_manifest)) {
    577     _android_manifest = invoker.android_manifest
    578   }
    579   assert(_android_manifest != "")
    580 
    581   _final_deps = []
    582   _final_datadeps = []
    583 
    584   java_library("${target_name}__java_library") {
    585     jar_path = _jar_path
    586     if (defined(invoker.jar_excluded_patterns)) {
    587       jar_excluded_patterns = invoker.jar_excluded_patterns
    588     }
    589     build_config = invoker.build_config
    590     java_files = _java_files
    591     srcjar_deps = _srcjar_deps
    592 
    593     if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) {
    594       proguard_preprocess = invoker.proguard_preprocess
    595       proguard_config = invoker.proguard_config
    596     }
    597 
    598     if (defined(invoker.dist_jar_path)) {
    599       dist_jar_path = invoker.dist_jar_path
    600     }
    601   }
    602 
    603   if (defined(invoker.chromium_code) && invoker.chromium_code) {
    604     _final_datadeps += [ ":${target_name}__lint" ]
    605     android_lint("${target_name}__lint") {
    606       android_manifest = _android_manifest
    607       jar_path = _jar_path
    608       java_files = _java_files
    609     }
    610   }
    611 
    612   dex("${target_name}__dex") {
    613     sources = [_jar_path]
    614     output = _dex_path
    615   }
    616 
    617   group(target_name) {
    618     deps = [
    619       ":${target_name}__java_library",
    620       ":${target_name}__dex",
    621     ] + _final_deps + _final_datadeps
    622   }
    623 }
    624 
    625 # Runs process_resources.py
    626 template("process_resources") {
    627   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    628 
    629   zip_path = invoker.zip_path
    630   srcjar_path = invoker.srcjar_path
    631   build_config = invoker.build_config
    632   resource_dirs = invoker.resource_dirs
    633   android_manifest = invoker.android_manifest
    634 
    635   non_constant_id = true
    636   if (defined(invoker.generate_constant_ids) && invoker.generate_constant_ids) {
    637     non_constant_id = false
    638   }
    639 
    640   action(target_name) {
    641     script = "//build/android/gyp/process_resources.py"
    642 
    643     depfile = "$target_gen_dir/$target_name.d"
    644     outputs = [
    645       depfile,
    646       zip_path,
    647       srcjar_path,
    648     ]
    649 
    650     sources_build_rel = exec_script(
    651         "//build/android/gyp/find.py",
    652         rebase_path(resource_dirs, root_build_dir),
    653         "list lines"
    654         )
    655     sources = rebase_path(sources_build_rel, ".", root_build_dir)
    656 
    657     source_prereqs = [
    658       build_config,
    659       android_manifest,
    660     ]
    661 
    662     rebase_resource_dirs = rebase_path(resource_dirs, root_build_dir)
    663     rebase_build_config = rebase_path(build_config, root_build_dir)
    664     args = [
    665       "--depfile", rebase_path(depfile, root_build_dir),
    666       "--android-sdk", rebase_path(android_sdk, root_build_dir),
    667       "--android-sdk-tools", rebase_path(android_sdk_build_tools, root_build_dir),
    668       "--android-manifest", rebase_path(android_manifest, root_build_dir),
    669 
    670       "--resource-dirs=$rebase_resource_dirs",
    671       "--srcjar-out", rebase_path(srcjar_path, root_build_dir),
    672       "--resource-zip-out", rebase_path(zip_path, root_build_dir),
    673 
    674       "--dependencies-res-zips=@FileArg($rebase_build_config:resources:dependency_zips)",
    675       "--extra-res-packages=@FileArg($rebase_build_config:resources:extra_package_names)",
    676     ]
    677 
    678     if (non_constant_id) {
    679       args += [ "--non-constant-id" ]
    680     }
    681 
    682     if (defined(invoker.custom_package)) {
    683       args += [
    684         "--custom-package", invoker.custom_package,
    685       ]
    686     }
    687 
    688     if (defined(invoker.v14_verify_only) && invoker.v14_verify_only) {
    689       args += ["--v14-verify-only"]
    690     }
    691 
    692     if (defined(invoker.all_resources_zip_path)) {
    693       all_resources_zip = invoker.all_resources_zip_path
    694       outputs += [ all_resources_zip ]
    695       args += [
    696         "--all-resources-zip-out", rebase_path(all_resources_zip, root_build_dir)
    697       ]
    698     }
    699 
    700     if (defined(invoker.args)) {
    701       args += invoker.args
    702     }
    703   }
    704 }
    705 
    706 template("copy_ex") {
    707   if (defined(invoker.testonly)) { testonly = invoker.testonly }
    708 
    709   action(target_name) {
    710     script = "//build/android/gyp/copy_ex.py"
    711     depfile = "$target_gen_dir/$target_name.d"
    712     outputs = [
    713       depfile,
    714     ]
    715     sources = []
    716     if (defined(invoker.sources)) {
    717       sources += invoker.sources
    718     }
    719 
    720     inputs = []
    721     if (defined(invoker.inputs)) {
    722       inputs += invoker.inputs
    723     }
    724 
    725     args = [
    726       "--depfile", rebase_path(depfile, root_build_dir),
    727       "--dest", rebase_path(invoker.dest, root_build_dir),
    728     ]
    729     if (defined(invoker.args)) {
    730       args += invoker.args
    731     }
    732     rebased_sources = rebase_path(sources, root_build_dir)
    733     args += [ "--files=$rebased_sources" ]
    734 
    735     if (defined(invoker.clear_dir) && invoker.clear_dir) {
    736       args += ["--clear"]
    737     }
    738   }
    739 }
    740