xref: /aosp_15_r20/external/bazelbuild-rules_android/rules/utils.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
15*9e965d6fSRomain Jobredeaux"""Utilities for the Android rules."""
16*9e965d6fSRomain Jobredeaux
17*9e965d6fSRomain Jobredeauxload(":providers.bzl", "FailureInfo")
18*9e965d6fSRomain Jobredeaux
19*9e965d6fSRomain JobredeauxANDROID_TOOLCHAIN_TYPE = Label("//toolchains/android:toolchain_type")
20*9e965d6fSRomain Jobredeaux
21*9e965d6fSRomain Jobredeaux_CUU = "\033[A"
22*9e965d6fSRomain Jobredeaux_EL = "\033[K"
23*9e965d6fSRomain Jobredeaux_DEFAULT = "\033[0m"
24*9e965d6fSRomain Jobredeaux_BOLD = "\033[1m"
25*9e965d6fSRomain Jobredeaux_RED = "\033[31m"
26*9e965d6fSRomain Jobredeaux_GREEN = "\033[32m"
27*9e965d6fSRomain Jobredeaux_MAGENTA = "\033[35m"
28*9e965d6fSRomain Jobredeaux_ERASE_PREV_LINE = "\n" + _CUU + _EL
29*9e965d6fSRomain Jobredeaux
30*9e965d6fSRomain Jobredeaux_INFO = _ERASE_PREV_LINE + _GREEN + "INFO: " + _DEFAULT + "%s"
31*9e965d6fSRomain Jobredeaux_WARNING = _ERASE_PREV_LINE + _MAGENTA + "WARNING: " + _DEFAULT + "%s"
32*9e965d6fSRomain Jobredeaux_ERROR = _ERASE_PREV_LINE + _BOLD + _RED + "ERROR: " + _DEFAULT + "%s"
33*9e965d6fSRomain Jobredeaux
34*9e965d6fSRomain Jobredeaux_WORD_CHARS = {
35*9e965d6fSRomain Jobredeaux    "A": True,
36*9e965d6fSRomain Jobredeaux    "B": True,
37*9e965d6fSRomain Jobredeaux    "C": True,
38*9e965d6fSRomain Jobredeaux    "D": True,
39*9e965d6fSRomain Jobredeaux    "E": True,
40*9e965d6fSRomain Jobredeaux    "F": True,
41*9e965d6fSRomain Jobredeaux    "G": True,
42*9e965d6fSRomain Jobredeaux    "H": True,
43*9e965d6fSRomain Jobredeaux    "I": True,
44*9e965d6fSRomain Jobredeaux    "J": True,
45*9e965d6fSRomain Jobredeaux    "K": True,
46*9e965d6fSRomain Jobredeaux    "L": True,
47*9e965d6fSRomain Jobredeaux    "M": True,
48*9e965d6fSRomain Jobredeaux    "N": True,
49*9e965d6fSRomain Jobredeaux    "O": True,
50*9e965d6fSRomain Jobredeaux    "P": True,
51*9e965d6fSRomain Jobredeaux    "Q": True,
52*9e965d6fSRomain Jobredeaux    "R": True,
53*9e965d6fSRomain Jobredeaux    "S": True,
54*9e965d6fSRomain Jobredeaux    "T": True,
55*9e965d6fSRomain Jobredeaux    "U": True,
56*9e965d6fSRomain Jobredeaux    "V": True,
57*9e965d6fSRomain Jobredeaux    "W": True,
58*9e965d6fSRomain Jobredeaux    "X": True,
59*9e965d6fSRomain Jobredeaux    "Y": True,
60*9e965d6fSRomain Jobredeaux    "Z": True,
61*9e965d6fSRomain Jobredeaux    "a": True,
62*9e965d6fSRomain Jobredeaux    "b": True,
63*9e965d6fSRomain Jobredeaux    "c": True,
64*9e965d6fSRomain Jobredeaux    "d": True,
65*9e965d6fSRomain Jobredeaux    "e": True,
66*9e965d6fSRomain Jobredeaux    "f": True,
67*9e965d6fSRomain Jobredeaux    "g": True,
68*9e965d6fSRomain Jobredeaux    "h": True,
69*9e965d6fSRomain Jobredeaux    "i": True,
70*9e965d6fSRomain Jobredeaux    "j": True,
71*9e965d6fSRomain Jobredeaux    "k": True,
72*9e965d6fSRomain Jobredeaux    "l": True,
73*9e965d6fSRomain Jobredeaux    "m": True,
74*9e965d6fSRomain Jobredeaux    "n": True,
75*9e965d6fSRomain Jobredeaux    "o": True,
76*9e965d6fSRomain Jobredeaux    "p": True,
77*9e965d6fSRomain Jobredeaux    "q": True,
78*9e965d6fSRomain Jobredeaux    "r": True,
79*9e965d6fSRomain Jobredeaux    "s": True,
80*9e965d6fSRomain Jobredeaux    "t": True,
81*9e965d6fSRomain Jobredeaux    "u": True,
82*9e965d6fSRomain Jobredeaux    "v": True,
83*9e965d6fSRomain Jobredeaux    "w": True,
84*9e965d6fSRomain Jobredeaux    "x": True,
85*9e965d6fSRomain Jobredeaux    "y": True,
86*9e965d6fSRomain Jobredeaux    "z": True,
87*9e965d6fSRomain Jobredeaux    "0": True,
88*9e965d6fSRomain Jobredeaux    "1": True,
89*9e965d6fSRomain Jobredeaux    "2": True,
90*9e965d6fSRomain Jobredeaux    "3": True,
91*9e965d6fSRomain Jobredeaux    "4": True,
92*9e965d6fSRomain Jobredeaux    "5": True,
93*9e965d6fSRomain Jobredeaux    "6": True,
94*9e965d6fSRomain Jobredeaux    "7": True,
95*9e965d6fSRomain Jobredeaux    "8": True,
96*9e965d6fSRomain Jobredeaux    "9": True,
97*9e965d6fSRomain Jobredeaux    "_": True,
98*9e965d6fSRomain Jobredeaux}
99*9e965d6fSRomain Jobredeaux
100*9e965d6fSRomain Jobredeaux_HEX_CHAR = {
101*9e965d6fSRomain Jobredeaux    0x0: "0",
102*9e965d6fSRomain Jobredeaux    0x1: "1",
103*9e965d6fSRomain Jobredeaux    0x2: "2",
104*9e965d6fSRomain Jobredeaux    0x3: "3",
105*9e965d6fSRomain Jobredeaux    0x4: "4",
106*9e965d6fSRomain Jobredeaux    0x5: "5",
107*9e965d6fSRomain Jobredeaux    0x6: "6",
108*9e965d6fSRomain Jobredeaux    0x7: "7",
109*9e965d6fSRomain Jobredeaux    0x8: "8",
110*9e965d6fSRomain Jobredeaux    0x9: "9",
111*9e965d6fSRomain Jobredeaux    0xA: "A",
112*9e965d6fSRomain Jobredeaux    0xB: "B",
113*9e965d6fSRomain Jobredeaux    0xC: "C",
114*9e965d6fSRomain Jobredeaux    0xD: "D",
115*9e965d6fSRomain Jobredeaux    0xE: "E",
116*9e965d6fSRomain Jobredeaux    0xF: "F",
117*9e965d6fSRomain Jobredeaux}
118*9e965d6fSRomain Jobredeaux
119*9e965d6fSRomain Jobredeaux_JAVA_RESERVED = {
120*9e965d6fSRomain Jobredeaux    "abstract": True,
121*9e965d6fSRomain Jobredeaux    "assert": True,
122*9e965d6fSRomain Jobredeaux    "boolean": True,
123*9e965d6fSRomain Jobredeaux    "break": True,
124*9e965d6fSRomain Jobredeaux    "byte": True,
125*9e965d6fSRomain Jobredeaux    "case": True,
126*9e965d6fSRomain Jobredeaux    "catch": True,
127*9e965d6fSRomain Jobredeaux    "char": True,
128*9e965d6fSRomain Jobredeaux    "class": True,
129*9e965d6fSRomain Jobredeaux    "const": True,
130*9e965d6fSRomain Jobredeaux    "continue": True,
131*9e965d6fSRomain Jobredeaux    "default": True,
132*9e965d6fSRomain Jobredeaux    "do": True,
133*9e965d6fSRomain Jobredeaux    "double": True,
134*9e965d6fSRomain Jobredeaux    "else": True,
135*9e965d6fSRomain Jobredeaux    "enum": True,
136*9e965d6fSRomain Jobredeaux    "extends": True,
137*9e965d6fSRomain Jobredeaux    "final": True,
138*9e965d6fSRomain Jobredeaux    "finally": True,
139*9e965d6fSRomain Jobredeaux    "float": True,
140*9e965d6fSRomain Jobredeaux    "for": True,
141*9e965d6fSRomain Jobredeaux    "goto": True,
142*9e965d6fSRomain Jobredeaux    "if": True,
143*9e965d6fSRomain Jobredeaux    "implements": True,
144*9e965d6fSRomain Jobredeaux    "import": True,
145*9e965d6fSRomain Jobredeaux    "instanceof": True,
146*9e965d6fSRomain Jobredeaux    "int": True,
147*9e965d6fSRomain Jobredeaux    "interface": True,
148*9e965d6fSRomain Jobredeaux    "long": True,
149*9e965d6fSRomain Jobredeaux    "native": True,
150*9e965d6fSRomain Jobredeaux    "new": True,
151*9e965d6fSRomain Jobredeaux    "package": True,
152*9e965d6fSRomain Jobredeaux    "private": True,
153*9e965d6fSRomain Jobredeaux    "protected": True,
154*9e965d6fSRomain Jobredeaux    "public": True,
155*9e965d6fSRomain Jobredeaux    "return": True,
156*9e965d6fSRomain Jobredeaux    "short": True,
157*9e965d6fSRomain Jobredeaux    "static": True,
158*9e965d6fSRomain Jobredeaux    "strictfp": True,
159*9e965d6fSRomain Jobredeaux    "super": True,
160*9e965d6fSRomain Jobredeaux    "switch": True,
161*9e965d6fSRomain Jobredeaux    "synchronized": True,
162*9e965d6fSRomain Jobredeaux    "this": True,
163*9e965d6fSRomain Jobredeaux    "throw": True,
164*9e965d6fSRomain Jobredeaux    "throws": True,
165*9e965d6fSRomain Jobredeaux    "transient": True,
166*9e965d6fSRomain Jobredeaux    "try": True,
167*9e965d6fSRomain Jobredeaux    "void": True,
168*9e965d6fSRomain Jobredeaux    "volatile": True,
169*9e965d6fSRomain Jobredeaux    "while": True,
170*9e965d6fSRomain Jobredeaux    "true": True,
171*9e965d6fSRomain Jobredeaux    "false": True,
172*9e965d6fSRomain Jobredeaux    "null": True,
173*9e965d6fSRomain Jobredeaux}
174*9e965d6fSRomain Jobredeaux
175*9e965d6fSRomain Jobredeauxdef _collect_providers(provider, *all_deps):
176*9e965d6fSRomain Jobredeaux    """Collects the requested providers from the given list of deps."""
177*9e965d6fSRomain Jobredeaux    providers = []
178*9e965d6fSRomain Jobredeaux    for deps in all_deps:
179*9e965d6fSRomain Jobredeaux        for dep in deps:
180*9e965d6fSRomain Jobredeaux            if provider in dep:
181*9e965d6fSRomain Jobredeaux                providers.append(dep[provider])
182*9e965d6fSRomain Jobredeaux    return providers
183*9e965d6fSRomain Jobredeaux
184*9e965d6fSRomain Jobredeauxdef _join_depsets(providers, attr, order = "default"):
185*9e965d6fSRomain Jobredeaux    """Returns a merged depset using 'attr' from each provider in 'providers'."""
186*9e965d6fSRomain Jobredeaux    return depset(transitive = [getattr(p, attr) for p in providers], order = order)
187*9e965d6fSRomain Jobredeaux
188*9e965d6fSRomain Jobredeauxdef _first(collection):
189*9e965d6fSRomain Jobredeaux    """Returns the first item in the collection."""
190*9e965d6fSRomain Jobredeaux    for i in collection:
191*9e965d6fSRomain Jobredeaux        return i
192*9e965d6fSRomain Jobredeaux    return _error("The collection is empty.")
193*9e965d6fSRomain Jobredeaux
194*9e965d6fSRomain Jobredeauxdef _only(collection):
195*9e965d6fSRomain Jobredeaux    """Returns the only item in the collection."""
196*9e965d6fSRomain Jobredeaux    if len(collection) != 1:
197*9e965d6fSRomain Jobredeaux        _error("Expected one element, has %s." % len(collection))
198*9e965d6fSRomain Jobredeaux    return _first(collection)
199*9e965d6fSRomain Jobredeaux
200*9e965d6fSRomain Jobredeauxdef _list_or_depset_to_list(list_or_depset):
201*9e965d6fSRomain Jobredeaux    if type(list_or_depset) == "list":
202*9e965d6fSRomain Jobredeaux        return list_or_depset
203*9e965d6fSRomain Jobredeaux    elif type(list_or_depset) == "depset":
204*9e965d6fSRomain Jobredeaux        return list_or_depset.to_list()
205*9e965d6fSRomain Jobredeaux    else:
206*9e965d6fSRomain Jobredeaux        return _error("Expected a list or a depset. Got %s" % type(list_or_depset))
207*9e965d6fSRomain Jobredeaux
208*9e965d6fSRomain Jobredeauxdef _copy_file(ctx, src, dest):
209*9e965d6fSRomain Jobredeaux    if src.is_directory or dest.is_directory:
210*9e965d6fSRomain Jobredeaux        fail("Cannot use copy_file with directories")
211*9e965d6fSRomain Jobredeaux    ctx.actions.run_shell(
212*9e965d6fSRomain Jobredeaux        command = "cp --reflink=auto $1 $2",
213*9e965d6fSRomain Jobredeaux        arguments = [src.path, dest.path],
214*9e965d6fSRomain Jobredeaux        inputs = [src],
215*9e965d6fSRomain Jobredeaux        outputs = [dest],
216*9e965d6fSRomain Jobredeaux        mnemonic = "CopyFile",
217*9e965d6fSRomain Jobredeaux        progress_message = "Copy %s to %s" % (src.short_path, dest.short_path),
218*9e965d6fSRomain Jobredeaux    )
219*9e965d6fSRomain Jobredeaux
220*9e965d6fSRomain Jobredeauxdef _copy_dir(ctx, src, dest):
221*9e965d6fSRomain Jobredeaux    if not src.is_directory:
222*9e965d6fSRomain Jobredeaux        fail("copy_dir src must be a directory")
223*9e965d6fSRomain Jobredeaux    ctx.actions.run_shell(
224*9e965d6fSRomain Jobredeaux        command = "cp -r --reflink=auto $1 $2",
225*9e965d6fSRomain Jobredeaux        arguments = [src.path, dest.path],
226*9e965d6fSRomain Jobredeaux        inputs = [src],
227*9e965d6fSRomain Jobredeaux        outputs = [dest],
228*9e965d6fSRomain Jobredeaux        mnemonic = "CopyDir",
229*9e965d6fSRomain Jobredeaux        progress_message = "Copy %s to %s" % (src.short_path, dest.short_path),
230*9e965d6fSRomain Jobredeaux    )
231*9e965d6fSRomain Jobredeaux
232*9e965d6fSRomain Jobredeauxdef _info(msg):
233*9e965d6fSRomain Jobredeaux    """Print info."""
234*9e965d6fSRomain Jobredeaux    print(_INFO % msg)
235*9e965d6fSRomain Jobredeaux
236*9e965d6fSRomain Jobredeauxdef _warn(msg):
237*9e965d6fSRomain Jobredeaux    """Print warning."""
238*9e965d6fSRomain Jobredeaux    print(_WARNING % msg)
239*9e965d6fSRomain Jobredeaux
240*9e965d6fSRomain Jobredeauxdef _debug(msg):
241*9e965d6fSRomain Jobredeaux    """Print debug."""
242*9e965d6fSRomain Jobredeaux    print("\n%s" % msg)
243*9e965d6fSRomain Jobredeaux
244*9e965d6fSRomain Jobredeauxdef _error(msg):
245*9e965d6fSRomain Jobredeaux    """Print error and fail."""
246*9e965d6fSRomain Jobredeaux    fail(_ERASE_PREV_LINE + _CUU + _ERASE_PREV_LINE + _CUU + _ERROR % msg)
247*9e965d6fSRomain Jobredeaux
248*9e965d6fSRomain Jobredeauxdef _expand_var(config_vars, value):
249*9e965d6fSRomain Jobredeaux    """Expands make variables of the form $(SOME_VAR_NAME) for a single value.
250*9e965d6fSRomain Jobredeaux
251*9e965d6fSRomain Jobredeaux    "$$(SOME_VAR_NAME)" is escaped to a literal value of "$(SOME_VAR_NAME)" instead of being
252*9e965d6fSRomain Jobredeaux    expanded.
253*9e965d6fSRomain Jobredeaux
254*9e965d6fSRomain Jobredeaux    Args:
255*9e965d6fSRomain Jobredeaux      config_vars: String dictionary which maps config variables to their expanded values.
256*9e965d6fSRomain Jobredeaux      value: The string to apply substitutions to.
257*9e965d6fSRomain Jobredeaux
258*9e965d6fSRomain Jobredeaux    Returns:
259*9e965d6fSRomain Jobredeaux      The string value with substitutions applied.
260*9e965d6fSRomain Jobredeaux    """
261*9e965d6fSRomain Jobredeaux    parts = value.split("$(")
262*9e965d6fSRomain Jobredeaux    replacement = parts[0]
263*9e965d6fSRomain Jobredeaux    last_char = replacement[-1] if replacement else ""
264*9e965d6fSRomain Jobredeaux    for part in parts[1:]:
265*9e965d6fSRomain Jobredeaux        var_end = part.find(")")
266*9e965d6fSRomain Jobredeaux        if last_char == "$":
267*9e965d6fSRomain Jobredeaux            # If "$$(..." is found, treat it as "$(..."
268*9e965d6fSRomain Jobredeaux            replacement += "(" + part
269*9e965d6fSRomain Jobredeaux        elif var_end == -1 or part[:var_end] not in config_vars:
270*9e965d6fSRomain Jobredeaux            replacement += "$(" + part
271*9e965d6fSRomain Jobredeaux        else:
272*9e965d6fSRomain Jobredeaux            replacement += config_vars[part[:var_end]] + part[var_end + 1:]
273*9e965d6fSRomain Jobredeaux        last_char = replacement[-1] if replacement else ""
274*9e965d6fSRomain Jobredeaux    return replacement
275*9e965d6fSRomain Jobredeaux
276*9e965d6fSRomain Jobredeauxdef _expand_make_vars(ctx, vals):
277*9e965d6fSRomain Jobredeaux    """Expands make variables of the form $(SOME_VAR_NAME).
278*9e965d6fSRomain Jobredeaux
279*9e965d6fSRomain Jobredeaux    Args:
280*9e965d6fSRomain Jobredeaux      ctx: The rules context.
281*9e965d6fSRomain Jobredeaux      vals: Dictionary. Values of the form $(...) will be replaced.
282*9e965d6fSRomain Jobredeaux
283*9e965d6fSRomain Jobredeaux    Returns:
284*9e965d6fSRomain Jobredeaux      A dictionary containing vals.keys() and the expanded values.
285*9e965d6fSRomain Jobredeaux    """
286*9e965d6fSRomain Jobredeaux    res = {}
287*9e965d6fSRomain Jobredeaux    for k, v in vals.items():
288*9e965d6fSRomain Jobredeaux        res[k] = _expand_var(ctx.var, v)
289*9e965d6fSRomain Jobredeaux    return res
290*9e965d6fSRomain Jobredeaux
291*9e965d6fSRomain Jobredeauxdef _dedupe_split_attr(attr):
292*9e965d6fSRomain Jobredeaux    if not attr:
293*9e965d6fSRomain Jobredeaux        return []
294*9e965d6fSRomain Jobredeaux    arch = _first(sorted(attr.keys()))
295*9e965d6fSRomain Jobredeaux    return attr[arch]
296*9e965d6fSRomain Jobredeaux
297*9e965d6fSRomain Jobredeauxdef _get_runfiles(ctx, attrs):
298*9e965d6fSRomain Jobredeaux    runfiles = ctx.runfiles()
299*9e965d6fSRomain Jobredeaux    for attr in attrs:
300*9e965d6fSRomain Jobredeaux        executable = attr[DefaultInfo].files_to_run.executable
301*9e965d6fSRomain Jobredeaux        if executable:
302*9e965d6fSRomain Jobredeaux            runfiles = runfiles.merge(ctx.runfiles([executable]))
303*9e965d6fSRomain Jobredeaux        runfiles = runfiles.merge(
304*9e965d6fSRomain Jobredeaux            ctx.runfiles(
305*9e965d6fSRomain Jobredeaux                # Wrap DefaultInfo.files in depset to strip ordering.
306*9e965d6fSRomain Jobredeaux                transitive_files = depset(
307*9e965d6fSRomain Jobredeaux                    transitive = [attr[DefaultInfo].files],
308*9e965d6fSRomain Jobredeaux                ),
309*9e965d6fSRomain Jobredeaux            ),
310*9e965d6fSRomain Jobredeaux        )
311*9e965d6fSRomain Jobredeaux        runfiles = runfiles.merge(attr[DefaultInfo].default_runfiles)
312*9e965d6fSRomain Jobredeaux    return runfiles
313*9e965d6fSRomain Jobredeaux
314*9e965d6fSRomain Jobredeauxdef _sanitize_string(s, replacement = ""):
315*9e965d6fSRomain Jobredeaux    """Sanitizes a string by replacing all non-word characters.
316*9e965d6fSRomain Jobredeaux
317*9e965d6fSRomain Jobredeaux    This matches the \\w regex character class [A_Za-z0-9_].
318*9e965d6fSRomain Jobredeaux
319*9e965d6fSRomain Jobredeaux    Args:
320*9e965d6fSRomain Jobredeaux      s: String to sanitize.
321*9e965d6fSRomain Jobredeaux      replacement: Replacement for all non-word characters. Optional.
322*9e965d6fSRomain Jobredeaux
323*9e965d6fSRomain Jobredeaux    Returns:
324*9e965d6fSRomain Jobredeaux      The original string with all non-word characters replaced.
325*9e965d6fSRomain Jobredeaux    """
326*9e965d6fSRomain Jobredeaux    return "".join([s[i] if s[i] in _WORD_CHARS else replacement for i in range(len(s))])
327*9e965d6fSRomain Jobredeaux
328*9e965d6fSRomain Jobredeauxdef _hex(n, pad = True):
329*9e965d6fSRomain Jobredeaux    """Convert an integer number to an uppercase hexadecimal string.
330*9e965d6fSRomain Jobredeaux
331*9e965d6fSRomain Jobredeaux    Args:
332*9e965d6fSRomain Jobredeaux      n: Integer number.
333*9e965d6fSRomain Jobredeaux      pad: Optional. Pad the result to 8 characters with leading zeroes. Default = True.
334*9e965d6fSRomain Jobredeaux
335*9e965d6fSRomain Jobredeaux    Returns:
336*9e965d6fSRomain Jobredeaux      Return a representation of an integer number as a hexadecimal string.
337*9e965d6fSRomain Jobredeaux    """
338*9e965d6fSRomain Jobredeaux    hex_str = ""
339*9e965d6fSRomain Jobredeaux    for _ in range(8):
340*9e965d6fSRomain Jobredeaux        r = n % 16
341*9e965d6fSRomain Jobredeaux        n = n // 16
342*9e965d6fSRomain Jobredeaux        hex_str = _HEX_CHAR[r] + hex_str
343*9e965d6fSRomain Jobredeaux    if pad:
344*9e965d6fSRomain Jobredeaux        return hex_str
345*9e965d6fSRomain Jobredeaux    else:
346*9e965d6fSRomain Jobredeaux        return hex_str.lstrip("0")
347*9e965d6fSRomain Jobredeaux
348*9e965d6fSRomain Jobredeauxdef _sanitize_java_package(pkg):
349*9e965d6fSRomain Jobredeaux    return ".".join(["xxx" if p in _JAVA_RESERVED else p for p in pkg.split(".")])
350*9e965d6fSRomain Jobredeaux
351*9e965d6fSRomain Jobredeauxdef _check_for_failures(label, *all_deps):
352*9e965d6fSRomain Jobredeaux    """Collects FailureInfo providers from the given list of deps and fails if there's at least one."""
353*9e965d6fSRomain Jobredeaux    failure_infos = _collect_providers(FailureInfo, *all_deps)
354*9e965d6fSRomain Jobredeaux    if failure_infos:
355*9e965d6fSRomain Jobredeaux        error = "in label '%s':" % label
356*9e965d6fSRomain Jobredeaux        for failure_info in failure_infos:
357*9e965d6fSRomain Jobredeaux            error += "\n\t" + failure_info.error
358*9e965d6fSRomain Jobredeaux        _error(error)
359*9e965d6fSRomain Jobredeaux
360*9e965d6fSRomain Jobredeauxdef _run_validation(
361*9e965d6fSRomain Jobredeaux        ctx,
362*9e965d6fSRomain Jobredeaux        validation_out,
363*9e965d6fSRomain Jobredeaux        executable,
364*9e965d6fSRomain Jobredeaux        outputs = [],
365*9e965d6fSRomain Jobredeaux        tools = [],
366*9e965d6fSRomain Jobredeaux        **args):
367*9e965d6fSRomain Jobredeaux    """Creates an action that runs an executable as a validation.
368*9e965d6fSRomain Jobredeaux
369*9e965d6fSRomain Jobredeaux    Note: When the validation executable fails, it should return a non-zero
370*9e965d6fSRomain Jobredeaux    value to signify a validation failure.
371*9e965d6fSRomain Jobredeaux
372*9e965d6fSRomain Jobredeaux    Args:
373*9e965d6fSRomain Jobredeaux      ctx: The context.
374*9e965d6fSRomain Jobredeaux      validation_out: A File. The output of the executable is piped to the
375*9e965d6fSRomain Jobredeaux        file. This artifact should then be propagated to "validations" in the
376*9e965d6fSRomain Jobredeaux        OutputGroupInfo.
377*9e965d6fSRomain Jobredeaux      executable: See ctx.actions.run#executable.
378*9e965d6fSRomain Jobredeaux      outputs: See ctx.actions.run#outputs.
379*9e965d6fSRomain Jobredeaux      tools: See ctx.actions.run#tools.
380*9e965d6fSRomain Jobredeaux      **args: Remaining args are directly propagated to ctx.actions.run_shell.
381*9e965d6fSRomain Jobredeaux        See ctx.actions.run_shell for further documentation.
382*9e965d6fSRomain Jobredeaux    """
383*9e965d6fSRomain Jobredeaux    exec_type = type(executable)
384*9e965d6fSRomain Jobredeaux    exec_bin = None
385*9e965d6fSRomain Jobredeaux    exec_bin_path = None
386*9e965d6fSRomain Jobredeaux    if exec_type == "FilesToRunProvider":
387*9e965d6fSRomain Jobredeaux        exec_bin = executable.executable
388*9e965d6fSRomain Jobredeaux        exec_bin_path = exec_bin.path
389*9e965d6fSRomain Jobredeaux    elif exec_type == "File":
390*9e965d6fSRomain Jobredeaux        exec_bin = executable
391*9e965d6fSRomain Jobredeaux        exec_bin_path = exec_bin.path
392*9e965d6fSRomain Jobredeaux    elif exec_type == type(""):
393*9e965d6fSRomain Jobredeaux        exec_bin_path = executable
394*9e965d6fSRomain Jobredeaux    else:
395*9e965d6fSRomain Jobredeaux        fail(
396*9e965d6fSRomain Jobredeaux            "Error, executable should be a File, FilesToRunProvider or a " +
397*9e965d6fSRomain Jobredeaux            "string that represents a path to a tool, got: %s" % exec_type,
398*9e965d6fSRomain Jobredeaux        )
399*9e965d6fSRomain Jobredeaux
400*9e965d6fSRomain Jobredeaux    ctx.actions.run_shell(
401*9e965d6fSRomain Jobredeaux        command = """#!/bin/bash
402*9e965d6fSRomain Jobredeauxset -eu
403*9e965d6fSRomain Jobredeauxset -o pipefail # Returns the executables failure code, if it fails.
404*9e965d6fSRomain Jobredeaux
405*9e965d6fSRomain JobredeauxEXECUTABLE={executable}
406*9e965d6fSRomain JobredeauxVALIDATION_OUT={validation_out}
407*9e965d6fSRomain Jobredeaux
408*9e965d6fSRomain Jobredeaux"${{EXECUTABLE}}" $@ 2>&1 | tee -a "${{VALIDATION_OUT}}"
409*9e965d6fSRomain Jobredeaux""".format(
410*9e965d6fSRomain Jobredeaux            executable = exec_bin_path,
411*9e965d6fSRomain Jobredeaux            validation_out = validation_out.path,
412*9e965d6fSRomain Jobredeaux        ),
413*9e965d6fSRomain Jobredeaux        tools = tools + ([exec_bin] if exec_bin else []),
414*9e965d6fSRomain Jobredeaux        outputs = [validation_out] + outputs,
415*9e965d6fSRomain Jobredeaux        **args
416*9e965d6fSRomain Jobredeaux    )
417*9e965d6fSRomain Jobredeaux
418*9e965d6fSRomain Jobredeauxdef get_android_toolchain(ctx):
419*9e965d6fSRomain Jobredeaux    return ctx.toolchains[ANDROID_TOOLCHAIN_TYPE]
420*9e965d6fSRomain Jobredeaux
421*9e965d6fSRomain Jobredeauxdef get_android_sdk(ctx):
422*9e965d6fSRomain Jobredeaux    if hasattr(ctx.fragments.android, "incompatible_use_toolchain_resolution") and ctx.fragments.android.incompatible_use_toolchain_resolution:
423*9e965d6fSRomain Jobredeaux        return ctx.toolchains["//toolchains/android_sdk:toolchain_type"].android_sdk_info
424*9e965d6fSRomain Jobredeaux    else:
425*9e965d6fSRomain Jobredeaux        return ctx.attr._android_sdk[AndroidSdkInfo]
426*9e965d6fSRomain Jobredeaux
427*9e965d6fSRomain Jobredeauxdef _get_compilation_mode(ctx):
428*9e965d6fSRomain Jobredeaux    """Retrieves the compilation mode from the context.
429*9e965d6fSRomain Jobredeaux
430*9e965d6fSRomain Jobredeaux    Returns:
431*9e965d6fSRomain Jobredeaux      A string that represents the compilation mode.
432*9e965d6fSRomain Jobredeaux    """
433*9e965d6fSRomain Jobredeaux    return ctx.var["COMPILATION_MODE"]
434*9e965d6fSRomain Jobredeaux
435*9e965d6fSRomain Jobredeauxcompilation_mode = struct(
436*9e965d6fSRomain Jobredeaux    DBG = "dbg",
437*9e965d6fSRomain Jobredeaux    FASTBUILD = "fastbuild",
438*9e965d6fSRomain Jobredeaux    OPT = "opt",
439*9e965d6fSRomain Jobredeaux    get = _get_compilation_mode,
440*9e965d6fSRomain Jobredeaux)
441*9e965d6fSRomain Jobredeaux
442*9e965d6fSRomain Jobredeauxutils = struct(
443*9e965d6fSRomain Jobredeaux    check_for_failures = _check_for_failures,
444*9e965d6fSRomain Jobredeaux    collect_providers = _collect_providers,
445*9e965d6fSRomain Jobredeaux    copy_file = _copy_file,
446*9e965d6fSRomain Jobredeaux    copy_dir = _copy_dir,
447*9e965d6fSRomain Jobredeaux    expand_make_vars = _expand_make_vars,
448*9e965d6fSRomain Jobredeaux    first = _first,
449*9e965d6fSRomain Jobredeaux    dedupe_split_attr = _dedupe_split_attr,
450*9e965d6fSRomain Jobredeaux    get_runfiles = _get_runfiles,
451*9e965d6fSRomain Jobredeaux    join_depsets = _join_depsets,
452*9e965d6fSRomain Jobredeaux    only = _only,
453*9e965d6fSRomain Jobredeaux    run_validation = _run_validation,
454*9e965d6fSRomain Jobredeaux    sanitize_string = _sanitize_string,
455*9e965d6fSRomain Jobredeaux    sanitize_java_package = _sanitize_java_package,
456*9e965d6fSRomain Jobredeaux    hex = _hex,
457*9e965d6fSRomain Jobredeaux    list_or_depset_to_list = _list_or_depset_to_list,
458*9e965d6fSRomain Jobredeaux)
459*9e965d6fSRomain Jobredeaux
460*9e965d6fSRomain Jobredeauxlog = struct(
461*9e965d6fSRomain Jobredeaux    debug = _debug,
462*9e965d6fSRomain Jobredeaux    error = _error,
463*9e965d6fSRomain Jobredeaux    info = _info,
464*9e965d6fSRomain Jobredeaux    warn = _warn,
465*9e965d6fSRomain Jobredeaux)
466*9e965d6fSRomain Jobredeaux
467*9e965d6fSRomain Jobredeauxtesting = struct(
468*9e965d6fSRomain Jobredeaux    expand_var = _expand_var,
469*9e965d6fSRomain Jobredeaux)
470