xref: /aosp_15_r20/external/bazelbuild-rules_android/mobile_install/resources.bzl (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1*9e965d6fSRomain Jobredeaux# Copyright 2018 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"""Methods to process Android resources."""
15*9e965d6fSRomain Jobredeaux
16*9e965d6fSRomain Jobredeauxload(":constants.bzl", "constants")
17*9e965d6fSRomain Jobredeauxload(":utils.bzl", "utils")
18*9e965d6fSRomain Jobredeaux
19*9e965d6fSRomain Jobredeaux# Android resource types, see https://android.googlesource.com/platform/frameworks/base/+/refs/heads/main/tools/aapt2/Resource.h
20*9e965d6fSRomain Jobredeauxres_types = [
21*9e965d6fSRomain Jobredeaux    "anim",
22*9e965d6fSRomain Jobredeaux    "animator",
23*9e965d6fSRomain Jobredeaux    "array",
24*9e965d6fSRomain Jobredeaux    "attr",
25*9e965d6fSRomain Jobredeaux    "^attr-private",
26*9e965d6fSRomain Jobredeaux    "bool",
27*9e965d6fSRomain Jobredeaux    "color",
28*9e965d6fSRomain Jobredeaux    "configVarying",  #  Not really a type, but it shows up in some CTS tests
29*9e965d6fSRomain Jobredeaux    "dimen",
30*9e965d6fSRomain Jobredeaux    "drawable",
31*9e965d6fSRomain Jobredeaux    "font",
32*9e965d6fSRomain Jobredeaux    "fraction",
33*9e965d6fSRomain Jobredeaux    "id",
34*9e965d6fSRomain Jobredeaux    "integer",
35*9e965d6fSRomain Jobredeaux    "interpolator",
36*9e965d6fSRomain Jobredeaux    "layout",
37*9e965d6fSRomain Jobredeaux    "macro",
38*9e965d6fSRomain Jobredeaux    "menu",
39*9e965d6fSRomain Jobredeaux    "mipmap",
40*9e965d6fSRomain Jobredeaux    "navigation",
41*9e965d6fSRomain Jobredeaux    "plurals",
42*9e965d6fSRomain Jobredeaux    "raw",
43*9e965d6fSRomain Jobredeaux    "string",
44*9e965d6fSRomain Jobredeaux    "style",
45*9e965d6fSRomain Jobredeaux    "styleable",
46*9e965d6fSRomain Jobredeaux    "transition",
47*9e965d6fSRomain Jobredeaux    "xml",
48*9e965d6fSRomain Jobredeaux]
49*9e965d6fSRomain Jobredeaux
50*9e965d6fSRomain Jobredeauxdef get_assets_dir(asset, base_dir):
51*9e965d6fSRomain Jobredeaux    """Build the full assets directory sanitizing the input first."""
52*9e965d6fSRomain Jobredeaux    if base_dir == "":
53*9e965d6fSRomain Jobredeaux        # some targets specify assets files and set assets_dirs = ""
54*9e965d6fSRomain Jobredeaux        return asset.dirname
55*9e965d6fSRomain Jobredeaux    asset_path = asset.path.rstrip("/")
56*9e965d6fSRomain Jobredeaux    base_dir = base_dir.rstrip("/")
57*9e965d6fSRomain Jobredeaux    if asset_path.endswith("/" + base_dir):
58*9e965d6fSRomain Jobredeaux        return asset_path
59*9e965d6fSRomain Jobredeaux    return "%s/%s" % (asset_path.rpartition("/%s/" % base_dir)[0], base_dir)
60*9e965d6fSRomain Jobredeaux
61*9e965d6fSRomain Jobredeauxdef compile_resources(ctx, lib_strategy = True):
62*9e965d6fSRomain Jobredeaux    """Compiles android resources using aapt2
63*9e965d6fSRomain Jobredeaux
64*9e965d6fSRomain Jobredeaux    Args:
65*9e965d6fSRomain Jobredeaux      ctx: The context.
66*9e965d6fSRomain Jobredeaux      lib_strategy: If to use library strategy or bucket. Default is lib strategy.
67*9e965d6fSRomain Jobredeaux
68*9e965d6fSRomain Jobredeaux    Returns:
69*9e965d6fSRomain Jobredeaux      A list of compiled android resource archives (.flata) files, otherwise None
70*9e965d6fSRomain Jobredeaux      if data is None or empty.
71*9e965d6fSRomain Jobredeaux    """
72*9e965d6fSRomain Jobredeaux    res_dir_file_map = partition_by_res_dirs(ctx.rule.files.resource_files)
73*9e965d6fSRomain Jobredeaux    if lib_strategy:
74*9e965d6fSRomain Jobredeaux        return _compile_library_resouces(ctx, res_dir_file_map)
75*9e965d6fSRomain Jobredeaux    res_dir_buckets_map = _bucketize_resources(ctx, res_dir_file_map)
76*9e965d6fSRomain Jobredeaux    return _compile_bucketized_resources(ctx, res_dir_buckets_map)
77*9e965d6fSRomain Jobredeaux
78*9e965d6fSRomain Jobredeauxdef partition_by_res_dirs(res_files):
79*9e965d6fSRomain Jobredeaux    """Partitions the resources by res directories.
80*9e965d6fSRomain Jobredeaux
81*9e965d6fSRomain Jobredeaux    Args:
82*9e965d6fSRomain Jobredeaux      res_files: A list of resource artifacts files.
83*9e965d6fSRomain Jobredeaux
84*9e965d6fSRomain Jobredeaux    Returns:
85*9e965d6fSRomain Jobredeaux      A map of "res" directories to files corresponding to the directory.
86*9e965d6fSRomain Jobredeaux    """
87*9e965d6fSRomain Jobredeaux    if not res_files:
88*9e965d6fSRomain Jobredeaux        return None
89*9e965d6fSRomain Jobredeaux
90*9e965d6fSRomain Jobredeaux    # Given the fact that res directories can be named anything and
91*9e965d6fSRomain Jobredeaux    # its not possible to distinguish between directories and regular files
92*9e965d6fSRomain Jobredeaux    # during analysis time, we use file extensions as an heuristic to group
93*9e965d6fSRomain Jobredeaux    # resource files. All Android resource files have the following form
94*9e965d6fSRomain Jobredeaux    # res-dir/type-dir/res_file. When we see a regular file (by looking at
95*9e965d6fSRomain Jobredeaux    # the extesion) we use the directory two levels up as the grouping dir.
96*9e965d6fSRomain Jobredeaux    # Most of the resource directories will contain at least one file with
97*9e965d6fSRomain Jobredeaux    # and extension, so this heuristic will generally result in good groupings.
98*9e965d6fSRomain Jobredeaux    res_non_values_file_map = {}
99*9e965d6fSRomain Jobredeaux    res_value_file_map = {}
100*9e965d6fSRomain Jobredeaux    res_dir_map = {}
101*9e965d6fSRomain Jobredeaux    for res_file in res_files:
102*9e965d6fSRomain Jobredeaux        if res_file.is_directory:
103*9e965d6fSRomain Jobredeaux            res_dir_map.setdefault(res_file.path, []).append(res_file)
104*9e965d6fSRomain Jobredeaux        else:
105*9e965d6fSRomain Jobredeaux            path_segments = res_file.dirname.rsplit("/", 1)
106*9e965d6fSRomain Jobredeaux            root_dir = path_segments[0]
107*9e965d6fSRomain Jobredeaux            if path_segments[1].startswith("values"):
108*9e965d6fSRomain Jobredeaux                res_value_file_map.setdefault(root_dir, []).append(res_file)
109*9e965d6fSRomain Jobredeaux            else:
110*9e965d6fSRomain Jobredeaux                res_non_values_file_map.setdefault(root_dir, []).append(res_file)
111*9e965d6fSRomain Jobredeaux    return {
112*9e965d6fSRomain Jobredeaux        "values": res_value_file_map,
113*9e965d6fSRomain Jobredeaux        "non-values": res_non_values_file_map,
114*9e965d6fSRomain Jobredeaux        "res_dir": res_dir_map,
115*9e965d6fSRomain Jobredeaux    }
116*9e965d6fSRomain Jobredeaux
117*9e965d6fSRomain Jobredeauxdef _bucketize_resources(ctx, data):
118*9e965d6fSRomain Jobredeaux    """Bucketizes resources by type.
119*9e965d6fSRomain Jobredeaux
120*9e965d6fSRomain Jobredeaux    Args:
121*9e965d6fSRomain Jobredeaux      ctx: The context.
122*9e965d6fSRomain Jobredeaux      data: A map of "res" directories to files corresponding to the directory.
123*9e965d6fSRomain Jobredeaux
124*9e965d6fSRomain Jobredeaux    Returns:
125*9e965d6fSRomain Jobredeaux      A map of "res" directories to "res" buckets, None when there no resource
126*9e965d6fSRomain Jobredeaux      files to compile.
127*9e965d6fSRomain Jobredeaux    """
128*9e965d6fSRomain Jobredeaux    if not data:
129*9e965d6fSRomain Jobredeaux        return None
130*9e965d6fSRomain Jobredeaux
131*9e965d6fSRomain Jobredeaux    # Create backing files for the resource sharder.
132*9e965d6fSRomain Jobredeaux    res_dir_buckets_map = {}
133*9e965d6fSRomain Jobredeaux    for i, res_dir in enumerate(data.keys()):
134*9e965d6fSRomain Jobredeaux        res_buckets = []
135*9e965d6fSRomain Jobredeaux        typed_outputs = []
136*9e965d6fSRomain Jobredeaux
137*9e965d6fSRomain Jobredeaux        for r_type in res_types:
138*9e965d6fSRomain Jobredeaux            for idx in range(ctx.attr._mi_res_shards):
139*9e965d6fSRomain Jobredeaux                res_bucket = utils.isolated_declare_file(
140*9e965d6fSRomain Jobredeaux                    ctx,
141*9e965d6fSRomain Jobredeaux                    ctx.label.name + "_mi/resources/buckets/%d/%s_%s.zip" % (i, r_type, idx),
142*9e965d6fSRomain Jobredeaux                )
143*9e965d6fSRomain Jobredeaux                res_buckets.append(res_bucket)
144*9e965d6fSRomain Jobredeaux                typed_outputs.append(r_type + ":" + res_bucket.path)
145*9e965d6fSRomain Jobredeaux
146*9e965d6fSRomain Jobredeaux        args = ctx.actions.args()
147*9e965d6fSRomain Jobredeaux        args.use_param_file(param_file_arg = "-flagfile=%s")
148*9e965d6fSRomain Jobredeaux        args.set_param_file_format("multiline")
149*9e965d6fSRomain Jobredeaux        args.add_joined("-typed_outputs", typed_outputs, join_with = ",")
150*9e965d6fSRomain Jobredeaux        if data[res_dir]:
151*9e965d6fSRomain Jobredeaux            args.add_joined("-res_paths", data[res_dir], join_with = ",")
152*9e965d6fSRomain Jobredeaux
153*9e965d6fSRomain Jobredeaux        ctx.actions.run(
154*9e965d6fSRomain Jobredeaux            executable = ctx.executable._android_kit,
155*9e965d6fSRomain Jobredeaux            arguments = ["bucketize", args],
156*9e965d6fSRomain Jobredeaux            inputs = data[res_dir],
157*9e965d6fSRomain Jobredeaux            outputs = res_buckets,
158*9e965d6fSRomain Jobredeaux            mnemonic = "BucketizeRes",
159*9e965d6fSRomain Jobredeaux            progress_message = "MI Bucketize resources for %s" % res_dir,
160*9e965d6fSRomain Jobredeaux        )
161*9e965d6fSRomain Jobredeaux        res_dir_buckets_map[res_dir] = res_buckets
162*9e965d6fSRomain Jobredeaux    return res_dir_buckets_map
163*9e965d6fSRomain Jobredeaux
164*9e965d6fSRomain Jobredeauxdef _compile_bucketized_resources(ctx, data):
165*9e965d6fSRomain Jobredeaux    """Compiles android resources using aapt2
166*9e965d6fSRomain Jobredeaux
167*9e965d6fSRomain Jobredeaux    Args:
168*9e965d6fSRomain Jobredeaux      ctx: The context.
169*9e965d6fSRomain Jobredeaux      data: A map of res directories to resource buckets.
170*9e965d6fSRomain Jobredeaux
171*9e965d6fSRomain Jobredeaux    Returns:
172*9e965d6fSRomain Jobredeaux      A list of compiled android resource archives (.flata) files, otherwise None
173*9e965d6fSRomain Jobredeaux      if data is None or empty.
174*9e965d6fSRomain Jobredeaux    """
175*9e965d6fSRomain Jobredeaux    if not data:
176*9e965d6fSRomain Jobredeaux        return constants.EMPTY_LIST
177*9e965d6fSRomain Jobredeaux
178*9e965d6fSRomain Jobredeaux    # TODO(mauriciogg): use no-crunch. We are using crunch to process 9-patch
179*9e965d6fSRomain Jobredeaux    # pngs should be disabled in general either by having a more granular flag
180*9e965d6fSRomain Jobredeaux    # in aapt2 or bucketizing 9patch pngs. See (b/70578281)
181*9e965d6fSRomain Jobredeaux    compiled_res_buckets = []
182*9e965d6fSRomain Jobredeaux    for res_dir, res_buckets in data.items():
183*9e965d6fSRomain Jobredeaux        for res_bucket in res_buckets:
184*9e965d6fSRomain Jobredeaux            # Note that extension matters for aapt2.
185*9e965d6fSRomain Jobredeaux            out = utils.isolated_declare_file(
186*9e965d6fSRomain Jobredeaux                ctx,
187*9e965d6fSRomain Jobredeaux                res_bucket.basename + ".flata",
188*9e965d6fSRomain Jobredeaux                sibling = res_bucket,
189*9e965d6fSRomain Jobredeaux            )
190*9e965d6fSRomain Jobredeaux            ctx.actions.run(
191*9e965d6fSRomain Jobredeaux                executable = ctx.executable._android_kit,
192*9e965d6fSRomain Jobredeaux                arguments = [
193*9e965d6fSRomain Jobredeaux                    "compile",
194*9e965d6fSRomain Jobredeaux                    "--aapt2=" + utils.first(ctx.attr._aapt2.files).path,
195*9e965d6fSRomain Jobredeaux                    "--in=" + res_bucket.path,
196*9e965d6fSRomain Jobredeaux                    "--out=" + out.path,
197*9e965d6fSRomain Jobredeaux                ],
198*9e965d6fSRomain Jobredeaux                inputs = [res_bucket] + ctx.attr._aapt2.files.to_list(),
199*9e965d6fSRomain Jobredeaux                outputs = [out],
200*9e965d6fSRomain Jobredeaux                mnemonic = "CompileRes",
201*9e965d6fSRomain Jobredeaux                progress_message = "MI Compiling resources for %s" % res_dir,
202*9e965d6fSRomain Jobredeaux            )
203*9e965d6fSRomain Jobredeaux            compiled_res_buckets.append(out)
204*9e965d6fSRomain Jobredeaux
205*9e965d6fSRomain Jobredeaux    return compiled_res_buckets
206*9e965d6fSRomain Jobredeaux
207*9e965d6fSRomain Jobredeauxdef _compile_library_resouces(ctx, data):
208*9e965d6fSRomain Jobredeaux    """Compiles android resources using aapt2
209*9e965d6fSRomain Jobredeaux
210*9e965d6fSRomain Jobredeaux    Args:
211*9e965d6fSRomain Jobredeaux      ctx: The context.
212*9e965d6fSRomain Jobredeaux      data: A map of res directories to resource buckets.
213*9e965d6fSRomain Jobredeaux
214*9e965d6fSRomain Jobredeaux    Returns:
215*9e965d6fSRomain Jobredeaux      A list of compiled android resource archives (.flata) files, otherwise None
216*9e965d6fSRomain Jobredeaux      if data is None or empty.
217*9e965d6fSRomain Jobredeaux    """
218*9e965d6fSRomain Jobredeaux    if not data:
219*9e965d6fSRomain Jobredeaux        return constants.EMPTY_LIST
220*9e965d6fSRomain Jobredeaux
221*9e965d6fSRomain Jobredeaux    # TODO(mauriciogg): use no-crunch. We are using crunch to process 9-patch
222*9e965d6fSRomain Jobredeaux    # pngs should be disabled in general either by having a more granular flag
223*9e965d6fSRomain Jobredeaux    # in aapt2 or bucketizing 9patch pngs. See (b/70578281)
224*9e965d6fSRomain Jobredeaux    compiled_res_dirs = []
225*9e965d6fSRomain Jobredeaux    for res_type in data.keys():
226*9e965d6fSRomain Jobredeaux        for res_dir in data[res_type].keys():
227*9e965d6fSRomain Jobredeaux            # Note that extension matters for aapt2.
228*9e965d6fSRomain Jobredeaux            out = utils.isolated_declare_file(
229*9e965d6fSRomain Jobredeaux                ctx,
230*9e965d6fSRomain Jobredeaux                ctx.label.name + "_mi/resources/%s_%s.flata" % (res_dir.replace("/", "_"), res_type),
231*9e965d6fSRomain Jobredeaux            )
232*9e965d6fSRomain Jobredeaux            compiled_res_dirs.append(out)
233*9e965d6fSRomain Jobredeaux
234*9e965d6fSRomain Jobredeaux            args = ctx.actions.args()
235*9e965d6fSRomain Jobredeaux            args.use_param_file(param_file_arg = "--flagfile=%s", use_always = True)
236*9e965d6fSRomain Jobredeaux            args.set_param_file_format("multiline")
237*9e965d6fSRomain Jobredeaux            args.add("-aapt2", ctx.file._aapt2)
238*9e965d6fSRomain Jobredeaux            args.add("-in", res_dir)
239*9e965d6fSRomain Jobredeaux            args.add("-out", out)
240*9e965d6fSRomain Jobredeaux            ctx.actions.run(
241*9e965d6fSRomain Jobredeaux                executable = ctx.executable._android_kit,
242*9e965d6fSRomain Jobredeaux                arguments = ["compile", args],
243*9e965d6fSRomain Jobredeaux                inputs = data[res_type][res_dir] + ctx.attr._aapt2.files.to_list(),
244*9e965d6fSRomain Jobredeaux                outputs = [out],
245*9e965d6fSRomain Jobredeaux                mnemonic = "CompileRes",
246*9e965d6fSRomain Jobredeaux                progress_message = "MI Compiling resources for %s" % res_dir,
247*9e965d6fSRomain Jobredeaux            )
248*9e965d6fSRomain Jobredeaux    return compiled_res_dirs
249*9e965d6fSRomain Jobredeaux
250*9e965d6fSRomain Jobredeauxdef link_resources(
251*9e965d6fSRomain Jobredeaux        ctx,
252*9e965d6fSRomain Jobredeaux        manifest,
253*9e965d6fSRomain Jobredeaux        java_package,
254*9e965d6fSRomain Jobredeaux        android_jar,
255*9e965d6fSRomain Jobredeaux        resource_archives,
256*9e965d6fSRomain Jobredeaux        assets,
257*9e965d6fSRomain Jobredeaux        assets_dirs):
258*9e965d6fSRomain Jobredeaux    """Links android resources using aapt2
259*9e965d6fSRomain Jobredeaux
260*9e965d6fSRomain Jobredeaux    Args:
261*9e965d6fSRomain Jobredeaux      ctx: The context.
262*9e965d6fSRomain Jobredeaux      manifest: The AndroidManifest.xml file
263*9e965d6fSRomain Jobredeaux      java_package: The package to use to generate R.java
264*9e965d6fSRomain Jobredeaux      android_jar: The android jar
265*9e965d6fSRomain Jobredeaux      resource_archives: List of intermediate compiled android resource files.
266*9e965d6fSRomain Jobredeaux      assets: The list of assets.
267*9e965d6fSRomain Jobredeaux      assets_dirs: The list of directories for the assets.
268*9e965d6fSRomain Jobredeaux
269*9e965d6fSRomain Jobredeaux    Returns:
270*9e965d6fSRomain Jobredeaux      The resource apk and the R java file generated by aapt2.
271*9e965d6fSRomain Jobredeaux    """
272*9e965d6fSRomain Jobredeaux    if not resource_archives:
273*9e965d6fSRomain Jobredeaux        return None
274*9e965d6fSRomain Jobredeaux
275*9e965d6fSRomain Jobredeaux    resource_apk = utils.isolated_declare_file(ctx, ctx.label.name + "_mi/resources/resource.apk")
276*9e965d6fSRomain Jobredeaux    rjava_zip = utils.isolated_declare_file(ctx, "R.zip", sibling = resource_apk)
277*9e965d6fSRomain Jobredeaux
278*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
279*9e965d6fSRomain Jobredeaux    args.use_param_file(param_file_arg = "-flagfile=%s", use_always = True)
280*9e965d6fSRomain Jobredeaux    args.add("-aapt2", ctx.executable._aapt2)
281*9e965d6fSRomain Jobredeaux    args.add("-sdk_jar", android_jar)
282*9e965d6fSRomain Jobredeaux    args.add("-manifest", manifest)
283*9e965d6fSRomain Jobredeaux    args.add("-pkg", java_package)
284*9e965d6fSRomain Jobredeaux    args.add("-src_jar", rjava_zip)
285*9e965d6fSRomain Jobredeaux    args.add("-out", resource_apk)
286*9e965d6fSRomain Jobredeaux    args.add_joined("-res_dirs", resource_archives, join_with = ",")
287*9e965d6fSRomain Jobredeaux    args.add_joined("-asset_dirs", assets_dirs, join_with = ",")
288*9e965d6fSRomain Jobredeaux
289*9e965d6fSRomain Jobredeaux    ctx.actions.run(
290*9e965d6fSRomain Jobredeaux        executable = ctx.executable._android_kit,
291*9e965d6fSRomain Jobredeaux        arguments = ["link", args],
292*9e965d6fSRomain Jobredeaux        inputs = depset(
293*9e965d6fSRomain Jobredeaux            [manifest, android_jar, ctx.executable._aapt2] + resource_archives,
294*9e965d6fSRomain Jobredeaux            transitive = [assets],
295*9e965d6fSRomain Jobredeaux        ),
296*9e965d6fSRomain Jobredeaux        outputs = [resource_apk, rjava_zip],
297*9e965d6fSRomain Jobredeaux        mnemonic = "LinkRes",
298*9e965d6fSRomain Jobredeaux        progress_message = "MI Linking resources for %s" % ctx.label,
299*9e965d6fSRomain Jobredeaux    )
300*9e965d6fSRomain Jobredeaux    return resource_apk, rjava_zip
301*9e965d6fSRomain Jobredeaux
302*9e965d6fSRomain Jobredeauxdef liteparse(ctx):
303*9e965d6fSRomain Jobredeaux    """Creates an R.pb which contains the resource ids gotten from a light parse.
304*9e965d6fSRomain Jobredeaux
305*9e965d6fSRomain Jobredeaux    Args:
306*9e965d6fSRomain Jobredeaux      ctx: The context.
307*9e965d6fSRomain Jobredeaux
308*9e965d6fSRomain Jobredeaux    Returns:
309*9e965d6fSRomain Jobredeaux      The resource pb file object.
310*9e965d6fSRomain Jobredeaux    """
311*9e965d6fSRomain Jobredeaux    if not hasattr(ctx.rule.files, "resource_files"):
312*9e965d6fSRomain Jobredeaux        return None
313*9e965d6fSRomain Jobredeaux
314*9e965d6fSRomain Jobredeaux    r_pb = utils.isolated_declare_file(ctx, ctx.label.name + "_mi/resources/R.pb")
315*9e965d6fSRomain Jobredeaux
316*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
317*9e965d6fSRomain Jobredeaux    args.use_param_file(param_file_arg = "--flagfile=%s", use_always = True)
318*9e965d6fSRomain Jobredeaux    args.set_param_file_format("multiline")
319*9e965d6fSRomain Jobredeaux    args.add_joined("--res_files", ctx.rule.files.resource_files, join_with = ",")
320*9e965d6fSRomain Jobredeaux    args.add("--out", r_pb)
321*9e965d6fSRomain Jobredeaux
322*9e965d6fSRomain Jobredeaux    ctx.actions.run(
323*9e965d6fSRomain Jobredeaux        executable = ctx.executable._android_kit,
324*9e965d6fSRomain Jobredeaux        arguments = ["liteparse", args],
325*9e965d6fSRomain Jobredeaux        inputs = ctx.rule.files.resource_files,
326*9e965d6fSRomain Jobredeaux        outputs = [r_pb],
327*9e965d6fSRomain Jobredeaux        mnemonic = "ResLiteParse",
328*9e965d6fSRomain Jobredeaux        progress_message = "MI Lite parse Android Resources %s" % ctx.label,
329*9e965d6fSRomain Jobredeaux    )
330*9e965d6fSRomain Jobredeaux    return r_pb
331*9e965d6fSRomain Jobredeaux
332*9e965d6fSRomain Jobredeauxdef compiletime_r_srcjar(ctx, output_srcjar, r_pbs, package):
333*9e965d6fSRomain Jobredeaux    """Create R.srcjar from the given R.pb files in the transitive closure.
334*9e965d6fSRomain Jobredeaux
335*9e965d6fSRomain Jobredeaux    Args:
336*9e965d6fSRomain Jobredeaux      ctx: The context.
337*9e965d6fSRomain Jobredeaux      output_srcjar: The output R source jar artifact.
338*9e965d6fSRomain Jobredeaux      r_pbs: Transitive  set of resource pbs.
339*9e965d6fSRomain Jobredeaux      package: The package name of the compile-time R.java.
340*9e965d6fSRomain Jobredeaux    """
341*9e965d6fSRomain Jobredeaux    args = ctx.actions.args()
342*9e965d6fSRomain Jobredeaux    args.use_param_file(param_file_arg = "--flagfile=%s", use_always = True)
343*9e965d6fSRomain Jobredeaux    args.set_param_file_format("multiline")
344*9e965d6fSRomain Jobredeaux    args.add("-rJavaOutput", output_srcjar)
345*9e965d6fSRomain Jobredeaux    args.add("-packageForR", package)
346*9e965d6fSRomain Jobredeaux    args.add_joined("-resourcePbs", r_pbs, join_with = ",")
347*9e965d6fSRomain Jobredeaux
348*9e965d6fSRomain Jobredeaux    ctx.actions.run(
349*9e965d6fSRomain Jobredeaux        executable = ctx.executable._android_kit,
350*9e965d6fSRomain Jobredeaux        arguments = ["rstub", args],
351*9e965d6fSRomain Jobredeaux        inputs = r_pbs,
352*9e965d6fSRomain Jobredeaux        outputs = [output_srcjar],
353*9e965d6fSRomain Jobredeaux        mnemonic = "CompileTimeRSrcjar",
354*9e965d6fSRomain Jobredeaux        progress_message = "MI Make compile-time R.srcjar %s" % ctx.label,
355*9e965d6fSRomain Jobredeaux    )
356