1*9e965d6fSRomain Jobredeaux# Copyright 2019 The Bazel Authors. All rights reserved. 2*9e965d6fSRomain Jobredeaux# 3*9e965d6fSRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License"); 4*9e965d6fSRomain Jobredeaux# you may not use this file except in compliance with the License. 5*9e965d6fSRomain Jobredeaux# You may obtain a copy of the License at 6*9e965d6fSRomain Jobredeaux# 7*9e965d6fSRomain Jobredeaux# http://www.apache.org/licenses/LICENSE-2.0 8*9e965d6fSRomain Jobredeaux# 9*9e965d6fSRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software 10*9e965d6fSRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS, 11*9e965d6fSRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9e965d6fSRomain Jobredeaux# See the License for the specific language governing permissions and 13*9e965d6fSRomain Jobredeaux# limitations under the License. 14*9e965d6fSRomain Jobredeaux 15*9e965d6fSRomain Jobredeaux"""Bazel AAPT Commands.""" 16*9e965d6fSRomain Jobredeaux 17*9e965d6fSRomain Jobredeauxload( 18*9e965d6fSRomain Jobredeaux "//rules:utils.bzl", 19*9e965d6fSRomain Jobredeaux "ANDROID_TOOLCHAIN_TYPE", 20*9e965d6fSRomain Jobredeaux) 21*9e965d6fSRomain Jobredeaux 22*9e965d6fSRomain Jobredeauxdef _link( 23*9e965d6fSRomain Jobredeaux ctx, 24*9e965d6fSRomain Jobredeaux out_r_java, 25*9e965d6fSRomain Jobredeaux out_resource_apk, 26*9e965d6fSRomain Jobredeaux manifest = None, 27*9e965d6fSRomain Jobredeaux java_package = None, 28*9e965d6fSRomain Jobredeaux assets = depset([]), 29*9e965d6fSRomain Jobredeaux assets_dirs = [], 30*9e965d6fSRomain Jobredeaux compiled_resources = depset([]), 31*9e965d6fSRomain Jobredeaux config_filters = [], 32*9e965d6fSRomain Jobredeaux make_r_java_ids_non_final = False, 33*9e965d6fSRomain Jobredeaux compatible_with_resource_shrinking = True, 34*9e965d6fSRomain Jobredeaux enable_debug = False, 35*9e965d6fSRomain Jobredeaux enable_static_lib = False, 36*9e965d6fSRomain Jobredeaux android_jar = None, 37*9e965d6fSRomain Jobredeaux aapt = None): 38*9e965d6fSRomain Jobredeaux """Links compiled Android Resources with AAPT. 39*9e965d6fSRomain Jobredeaux 40*9e965d6fSRomain Jobredeaux Args: 41*9e965d6fSRomain Jobredeaux ctx: The context. 42*9e965d6fSRomain Jobredeaux out_r_java: A File. The R.java outputted by linking resources. 43*9e965d6fSRomain Jobredeaux out_resource_apk: A File. The Resource APK outputted by linking resources. 44*9e965d6fSRomain Jobredeaux manifest: A File. The AndroidManifest.xml. 45*9e965d6fSRomain Jobredeaux java_package: A string. The Java package for the generated R.java. 46*9e965d6fSRomain Jobredeaux assets: A list of Files. The list of assets from the transitive closure of 47*9e965d6fSRomain Jobredeaux the project. 48*9e965d6fSRomain Jobredeaux assets_dirs: A list of strings. The list of asset directories in the 49*9e965d6fSRomain Jobredeaux transitive closure of the project. 50*9e965d6fSRomain Jobredeaux compiled_resources: List of intermediate compiled android resource files. 51*9e965d6fSRomain Jobredeaux config_filters: A list of Strings. The configuration filters. 52*9e965d6fSRomain Jobredeaux make_r_java_ids_non_final: A bool. Makes the R.java produced from linkin 53*9e965d6fSRomain Jobredeaux have non-final values. 54*9e965d6fSRomain Jobredeaux compatible_with_resource_shrinking: A bool. When enabled produces the 55*9e965d6fSRomain Jobredeaux output in proto format which is a requirement for resource shrinking. 56*9e965d6fSRomain Jobredeaux enable_debug: A bool. Enable debugging 57*9e965d6fSRomain Jobredeaux enable_static_lib: A bool. Enable static lib. 58*9e965d6fSRomain Jobredeaux android_jar: A File. The Android Jar. 59*9e965d6fSRomain Jobredeaux aapt: A FilesToRunProvider. The AAPT executable. 60*9e965d6fSRomain Jobredeaux """ 61*9e965d6fSRomain Jobredeaux 62*9e965d6fSRomain Jobredeaux # Output the list of resources in reverse topological order. 63*9e965d6fSRomain Jobredeaux resources_param = ctx.actions.declare_file( 64*9e965d6fSRomain Jobredeaux out_r_java.basename + ".params", 65*9e965d6fSRomain Jobredeaux sibling = out_r_java, 66*9e965d6fSRomain Jobredeaux ) 67*9e965d6fSRomain Jobredeaux args = ctx.actions.args() 68*9e965d6fSRomain Jobredeaux args.use_param_file("%s", use_always = True) 69*9e965d6fSRomain Jobredeaux args.set_param_file_format("multiline") 70*9e965d6fSRomain Jobredeaux args.add_all(compiled_resources, expand_directories = True) 71*9e965d6fSRomain Jobredeaux ctx.actions.run_shell( 72*9e965d6fSRomain Jobredeaux command = """ 73*9e965d6fSRomain Jobredeaux# Reverses the set of inputs that have been topologically ordered to utilize the 74*9e965d6fSRomain Jobredeaux# overlay/override semantics of aapt2. 75*9e965d6fSRomain Jobredeauxset -e 76*9e965d6fSRomain Jobredeaux 77*9e965d6fSRomain Jobredeauxecho $(tac $1) > $2 78*9e965d6fSRomain Jobredeaux""", 79*9e965d6fSRomain Jobredeaux arguments = [args, resources_param.path], 80*9e965d6fSRomain Jobredeaux outputs = [resources_param], 81*9e965d6fSRomain Jobredeaux inputs = compiled_resources, 82*9e965d6fSRomain Jobredeaux ) 83*9e965d6fSRomain Jobredeaux 84*9e965d6fSRomain Jobredeaux args = ctx.actions.args() 85*9e965d6fSRomain Jobredeaux args.add("link") 86*9e965d6fSRomain Jobredeaux if enable_static_lib: 87*9e965d6fSRomain Jobredeaux args.add("--static-lib") 88*9e965d6fSRomain Jobredeaux args.add("--no-version-vectors") 89*9e965d6fSRomain Jobredeaux args.add("--no-static-lib-packages") # Turn off namespaced resource 90*9e965d6fSRomain Jobredeaux 91*9e965d6fSRomain Jobredeaux args.add("--manifest", manifest) 92*9e965d6fSRomain Jobredeaux args.add("--auto-add-overlay") # Enables resource redefinition and merging 93*9e965d6fSRomain Jobredeaux args.add("--override-styles-instead-of-overlaying") # mimic AAPT1. 94*9e965d6fSRomain Jobredeaux if make_r_java_ids_non_final: 95*9e965d6fSRomain Jobredeaux args.add("--non-final-ids") 96*9e965d6fSRomain Jobredeaux if compatible_with_resource_shrinking: 97*9e965d6fSRomain Jobredeaux args.add("--proto-format") 98*9e965d6fSRomain Jobredeaux if enable_debug: 99*9e965d6fSRomain Jobredeaux args.add("--debug-mode") 100*9e965d6fSRomain Jobredeaux args.add("--custom-package", java_package) 101*9e965d6fSRomain Jobredeaux args.add("-I", android_jar) 102*9e965d6fSRomain Jobredeaux args.add_all(assets_dirs, before_each = "-A") 103*9e965d6fSRomain Jobredeaux args.add("-R", resources_param, format = "@%s") 104*9e965d6fSRomain Jobredeaux args.add("-0", ".apk") 105*9e965d6fSRomain Jobredeaux args.add_joined("-c", config_filters, join_with = ",", omit_if_empty = True) 106*9e965d6fSRomain Jobredeaux args.add("--java", out_r_java.path.rpartition(java_package.replace(".", "/"))[0]) 107*9e965d6fSRomain Jobredeaux args.add("-o", out_resource_apk) 108*9e965d6fSRomain Jobredeaux 109*9e965d6fSRomain Jobredeaux ctx.actions.run( 110*9e965d6fSRomain Jobredeaux executable = aapt, 111*9e965d6fSRomain Jobredeaux arguments = [args], 112*9e965d6fSRomain Jobredeaux inputs = depset( 113*9e965d6fSRomain Jobredeaux [android_jar, resources_param] + 114*9e965d6fSRomain Jobredeaux ([manifest] if manifest else []), 115*9e965d6fSRomain Jobredeaux transitive = [assets, compiled_resources], 116*9e965d6fSRomain Jobredeaux ), 117*9e965d6fSRomain Jobredeaux outputs = [out_resource_apk, out_r_java], 118*9e965d6fSRomain Jobredeaux mnemonic = "LinkAndroidResources", 119*9e965d6fSRomain Jobredeaux progress_message = "ResV3 Linking Android Resources to %s" % out_resource_apk.short_path, 120*9e965d6fSRomain Jobredeaux toolchain = ANDROID_TOOLCHAIN_TYPE, 121*9e965d6fSRomain Jobredeaux ) 122*9e965d6fSRomain Jobredeaux 123*9e965d6fSRomain Jobredeauxdef _compile( 124*9e965d6fSRomain Jobredeaux ctx, 125*9e965d6fSRomain Jobredeaux out_dir, 126*9e965d6fSRomain Jobredeaux resource_files, 127*9e965d6fSRomain Jobredeaux aapt): 128*9e965d6fSRomain Jobredeaux """Compile and store resources in a single archive. 129*9e965d6fSRomain Jobredeaux 130*9e965d6fSRomain Jobredeaux Args: 131*9e965d6fSRomain Jobredeaux ctx: The context. 132*9e965d6fSRomain Jobredeaux out_dir: File. A file to store the output. 133*9e965d6fSRomain Jobredeaux resource_files: A list of Files. The list of resource files or directories 134*9e965d6fSRomain Jobredeaux to process. 135*9e965d6fSRomain Jobredeaux aapt: AAPT. Tool for compiling resources. 136*9e965d6fSRomain Jobredeaux """ 137*9e965d6fSRomain Jobredeaux if not out_dir: 138*9e965d6fSRomain Jobredeaux fail("No output directory specified.") 139*9e965d6fSRomain Jobredeaux if not out_dir.is_directory: 140*9e965d6fSRomain Jobredeaux fail("Output directory is not a directory artifact.") 141*9e965d6fSRomain Jobredeaux if not resource_files: 142*9e965d6fSRomain Jobredeaux fail("No resource files given.") 143*9e965d6fSRomain Jobredeaux 144*9e965d6fSRomain Jobredeaux # Retrieves the list of files at runtime when a directory is passed. 145*9e965d6fSRomain Jobredeaux args = ctx.actions.args() 146*9e965d6fSRomain Jobredeaux args.add_all(resource_files, expand_directories = True) 147*9e965d6fSRomain Jobredeaux 148*9e965d6fSRomain Jobredeaux ctx.actions.run_shell( 149*9e965d6fSRomain Jobredeaux command = """ 150*9e965d6fSRomain Jobredeauxset -e 151*9e965d6fSRomain Jobredeaux 152*9e965d6fSRomain JobredeauxAAPT=%s 153*9e965d6fSRomain JobredeauxOUT_DIR=%s 154*9e965d6fSRomain JobredeauxRESOURCE_FILES=$@ 155*9e965d6fSRomain Jobredeaux 156*9e965d6fSRomain Jobredeauxi=0 157*9e965d6fSRomain Jobredeauxdeclare -A out_dir_map 158*9e965d6fSRomain Jobredeauxfor f in ${RESOURCE_FILES}; do 159*9e965d6fSRomain Jobredeaux res_dir="$(dirname $(dirname ${f}))" 160*9e965d6fSRomain Jobredeaux if [ -z "${out_dir_map[${res_dir}]}" ]; then 161*9e965d6fSRomain Jobredeaux out_dir="${OUT_DIR}/$((++i))" 162*9e965d6fSRomain Jobredeaux mkdir -p ${out_dir} 163*9e965d6fSRomain Jobredeaux out_dir_map[${res_dir}]="${out_dir}" 164*9e965d6fSRomain Jobredeaux fi 165*9e965d6fSRomain Jobredeaux # Outputs from multiple directories can overwrite the outputs. As we do not 166*9e965d6fSRomain Jobredeaux # control the outputs for now store each in its own sub directory which will be 167*9e965d6fSRomain Jobredeaux # captured by the over_dir. 168*9e965d6fSRomain Jobredeaux # TODO(b/139757260): Re-evaluate this one compile per file or multiple and zip 169*9e965d6fSRomain Jobredeaux # merge. 170*9e965d6fSRomain Jobredeaux "${AAPT}" compile --legacy "${f}" -o "${out_dir_map[${res_dir}]}" 171*9e965d6fSRomain Jobredeauxdone 172*9e965d6fSRomain Jobredeaux""" % (aapt.executable.path, out_dir.path), 173*9e965d6fSRomain Jobredeaux tools = [aapt], 174*9e965d6fSRomain Jobredeaux arguments = [args], 175*9e965d6fSRomain Jobredeaux inputs = resource_files, 176*9e965d6fSRomain Jobredeaux outputs = [out_dir], 177*9e965d6fSRomain Jobredeaux mnemonic = "CompileAndroidResources", 178*9e965d6fSRomain Jobredeaux progress_message = "ResV3 Compiling Android Resources in %s" % out_dir, 179*9e965d6fSRomain Jobredeaux toolchain = ANDROID_TOOLCHAIN_TYPE, 180*9e965d6fSRomain Jobredeaux ) 181*9e965d6fSRomain Jobredeaux 182*9e965d6fSRomain Jobredeauxdef _convert( 183*9e965d6fSRomain Jobredeaux ctx, 184*9e965d6fSRomain Jobredeaux out = None, 185*9e965d6fSRomain Jobredeaux input = None, 186*9e965d6fSRomain Jobredeaux to_proto = False, 187*9e965d6fSRomain Jobredeaux aapt = None): 188*9e965d6fSRomain Jobredeaux args = ctx.actions.args() 189*9e965d6fSRomain Jobredeaux args.add("convert") 190*9e965d6fSRomain Jobredeaux args.add("--output-format", ("proto" if to_proto else "binary")) 191*9e965d6fSRomain Jobredeaux args.add("-o", out) 192*9e965d6fSRomain Jobredeaux args.add(input) 193*9e965d6fSRomain Jobredeaux 194*9e965d6fSRomain Jobredeaux ctx.actions.run( 195*9e965d6fSRomain Jobredeaux executable = aapt, 196*9e965d6fSRomain Jobredeaux arguments = [args], 197*9e965d6fSRomain Jobredeaux inputs = [input], 198*9e965d6fSRomain Jobredeaux outputs = [out], 199*9e965d6fSRomain Jobredeaux mnemonic = "AaptConvert", 200*9e965d6fSRomain Jobredeaux progress_message = "ResV3 Convert to %s" % out.short_path, 201*9e965d6fSRomain Jobredeaux toolchain = ANDROID_TOOLCHAIN_TYPE, 202*9e965d6fSRomain Jobredeaux ) 203*9e965d6fSRomain Jobredeaux 204*9e965d6fSRomain Jobredeauxaapt = struct( 205*9e965d6fSRomain Jobredeaux link = _link, 206*9e965d6fSRomain Jobredeaux compile = _compile, 207*9e965d6fSRomain Jobredeaux convert = _convert, 208*9e965d6fSRomain Jobredeaux) 209