xref: /aosp_15_r20/external/bazel-skylib/rules/private/maprule_util.bzl (revision bcb5dc7965af6ee42bf2f21341a2ec00233a8c8a)
1*bcb5dc79SHONG Yifan# Copyright 2019 The Bazel Authors. All rights reserved.
2*bcb5dc79SHONG Yifan#
3*bcb5dc79SHONG Yifan# Licensed under the Apache License, Version 2.0 (the "License");
4*bcb5dc79SHONG Yifan# you may not use this file except in compliance with the License.
5*bcb5dc79SHONG Yifan# You may obtain a copy of the License at
6*bcb5dc79SHONG Yifan#
7*bcb5dc79SHONG Yifan#    http://www.apache.org/licenses/LICENSE-2.0
8*bcb5dc79SHONG Yifan#
9*bcb5dc79SHONG Yifan# Unless required by applicable law or agreed to in writing, software
10*bcb5dc79SHONG Yifan# distributed under the License is distributed on an "AS IS" BASIS,
11*bcb5dc79SHONG Yifan# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*bcb5dc79SHONG Yifan# See the License for the specific language governing permissions and
13*bcb5dc79SHONG Yifan# limitations under the License.
14*bcb5dc79SHONG Yifan
15*bcb5dc79SHONG Yifan"""Utilities for maprule."""
16*bcb5dc79SHONG Yifan
17*bcb5dc79SHONG Yifandef resolve_locations(ctx, strategy, d):
18*bcb5dc79SHONG Yifan    """Resolve $(location) references in the values of a dictionary.
19*bcb5dc79SHONG Yifan
20*bcb5dc79SHONG Yifan    Args:
21*bcb5dc79SHONG Yifan      ctx: the 'ctx' argument of the rule implementation function
22*bcb5dc79SHONG Yifan      strategy: a struct with an 'as_path(string) -> string' function
23*bcb5dc79SHONG Yifan      d: {string: string} dictionary; values may contain $(location) references
24*bcb5dc79SHONG Yifan        for labels declared in the rule's 'srcs' and 'tools' attributes
25*bcb5dc79SHONG Yifan
26*bcb5dc79SHONG Yifan    Returns:
27*bcb5dc79SHONG Yifan      {string: string} dict, same as 'd' except "$(location)" references are
28*bcb5dc79SHONG Yifan      resolved.
29*bcb5dc79SHONG Yifan    """
30*bcb5dc79SHONG Yifan    location_expressions = []
31*bcb5dc79SHONG Yifan    parts = {}
32*bcb5dc79SHONG Yifan    was_anything_to_resolve = False
33*bcb5dc79SHONG Yifan    for k, v in d.items():
34*bcb5dc79SHONG Yifan        # Look for "$(location ...)" or "$(locations ...)", resolve if found.
35*bcb5dc79SHONG Yifan        # _validate_attributes already ensured that there's at most one $(location/s ...) in "v".
36*bcb5dc79SHONG Yifan        if "$(location" in v:
37*bcb5dc79SHONG Yifan            tokens = v.split("$(location")
38*bcb5dc79SHONG Yifan            was_anything_to_resolve = True
39*bcb5dc79SHONG Yifan            closing_paren = tokens[1].find(")")
40*bcb5dc79SHONG Yifan            location_expressions.append("$(location" + tokens[1][:closing_paren + 1])
41*bcb5dc79SHONG Yifan            parts[k] = (tokens[0], tokens[1][closing_paren + 1:])
42*bcb5dc79SHONG Yifan        else:
43*bcb5dc79SHONG Yifan            location_expressions.append("")
44*bcb5dc79SHONG Yifan
45*bcb5dc79SHONG Yifan    resolved = {}
46*bcb5dc79SHONG Yifan    if was_anything_to_resolve:
47*bcb5dc79SHONG Yifan        # Resolve all $(location) expressions in one go.  Should be faster than resolving them
48*bcb5dc79SHONG Yifan        # one-by-one.
49*bcb5dc79SHONG Yifan        all_location_expressions = "<split_here>".join(location_expressions)
50*bcb5dc79SHONG Yifan        all_resolved_locations = ctx.expand_location(all_location_expressions)
51*bcb5dc79SHONG Yifan        resolved_locations = strategy.as_path(all_resolved_locations).split("<split_here>")
52*bcb5dc79SHONG Yifan
53*bcb5dc79SHONG Yifan        i = 0
54*bcb5dc79SHONG Yifan
55*bcb5dc79SHONG Yifan        # Starlark dictionaries have a deterministic order of iteration, so the element order in
56*bcb5dc79SHONG Yifan        # "resolved_locations" matches the order in "location_expressions", i.e. the previous
57*bcb5dc79SHONG Yifan        # iteration order of "d".
58*bcb5dc79SHONG Yifan        for k, v in d.items():
59*bcb5dc79SHONG Yifan            if location_expressions[i]:
60*bcb5dc79SHONG Yifan                head, tail = parts[k]
61*bcb5dc79SHONG Yifan                resolved[k] = head + resolved_locations[i] + tail
62*bcb5dc79SHONG Yifan            else:
63*bcb5dc79SHONG Yifan                resolved[k] = v
64*bcb5dc79SHONG Yifan            i += 1
65*bcb5dc79SHONG Yifan    else:
66*bcb5dc79SHONG Yifan        resolved = d
67*bcb5dc79SHONG Yifan
68*bcb5dc79SHONG Yifan    return resolved
69*bcb5dc79SHONG Yifan
70*bcb5dc79SHONG Yifandef fail_if_errors(errors):
71*bcb5dc79SHONG Yifan    """Reports errors and fails the rule.
72*bcb5dc79SHONG Yifan
73*bcb5dc79SHONG Yifan    Args:
74*bcb5dc79SHONG Yifan        errors: list of strings; the errors to report. At most 10 are reported.
75*bcb5dc79SHONG Yifan    """
76*bcb5dc79SHONG Yifan    if errors:
77*bcb5dc79SHONG Yifan        # Don't overwhelm the user; report up to ten errors.
78*bcb5dc79SHONG Yifan        fail("\n".join(errors[:10]))
79*bcb5dc79SHONG Yifan
80*bcb5dc79SHONG Yifandef _as_windows_path(s):
81*bcb5dc79SHONG Yifan    """Returns the input path as a Windows path (replaces all of "/" with "\")."""
82*bcb5dc79SHONG Yifan    return s.replace("/", "\\")
83*bcb5dc79SHONG Yifan
84*bcb5dc79SHONG Yifandef _unchanged_path(s):
85*bcb5dc79SHONG Yifan    """Returns the input string (path) unchanged."""
86*bcb5dc79SHONG Yifan    return s
87*bcb5dc79SHONG Yifan
88*bcb5dc79SHONG Yifandef _create_cmd_action(
89*bcb5dc79SHONG Yifan        ctx,
90*bcb5dc79SHONG Yifan        outputs,
91*bcb5dc79SHONG Yifan        command,
92*bcb5dc79SHONG Yifan        inputs = None,
93*bcb5dc79SHONG Yifan        env = None,
94*bcb5dc79SHONG Yifan        progress_message = None,
95*bcb5dc79SHONG Yifan        mnemonic = None,
96*bcb5dc79SHONG Yifan        manifests_from_tools = None):
97*bcb5dc79SHONG Yifan    """Create one action using cmd.exe."""
98*bcb5dc79SHONG Yifan    ctx.actions.run(
99*bcb5dc79SHONG Yifan        inputs = inputs or [],
100*bcb5dc79SHONG Yifan        outputs = outputs,
101*bcb5dc79SHONG Yifan        executable = "cmd.exe",
102*bcb5dc79SHONG Yifan        env = env,
103*bcb5dc79SHONG Yifan        arguments = ["/C", command],
104*bcb5dc79SHONG Yifan        progress_message = progress_message or "Running cmd.exe command",
105*bcb5dc79SHONG Yifan        mnemonic = mnemonic or "CmdExeCommand",
106*bcb5dc79SHONG Yifan        input_manifests = manifests_from_tools,
107*bcb5dc79SHONG Yifan    )
108*bcb5dc79SHONG Yifan
109*bcb5dc79SHONG Yifandef _create_bash_action(
110*bcb5dc79SHONG Yifan        ctx,
111*bcb5dc79SHONG Yifan        outputs,
112*bcb5dc79SHONG Yifan        command,
113*bcb5dc79SHONG Yifan        inputs = None,
114*bcb5dc79SHONG Yifan        env = None,
115*bcb5dc79SHONG Yifan        progress_message = None,
116*bcb5dc79SHONG Yifan        mnemonic = None,
117*bcb5dc79SHONG Yifan        manifests_from_tools = None):
118*bcb5dc79SHONG Yifan    """Create one action using Bash."""
119*bcb5dc79SHONG Yifan    ctx.actions.run_shell(
120*bcb5dc79SHONG Yifan        inputs = inputs or [],
121*bcb5dc79SHONG Yifan        outputs = outputs,
122*bcb5dc79SHONG Yifan        env = env,
123*bcb5dc79SHONG Yifan        command = command,
124*bcb5dc79SHONG Yifan        progress_message = progress_message or "Running Bash command",
125*bcb5dc79SHONG Yifan        mnemonic = mnemonic or "BashCommand",
126*bcb5dc79SHONG Yifan        input_manifests = manifests_from_tools,
127*bcb5dc79SHONG Yifan    )
128*bcb5dc79SHONG Yifan
129*bcb5dc79SHONG Yifan# Action creation utilities for cmd.exe actions.
130*bcb5dc79SHONG YifanCMD_STRATEGY = struct(
131*bcb5dc79SHONG Yifan    as_path = _as_windows_path,
132*bcb5dc79SHONG Yifan    create_action = _create_cmd_action,
133*bcb5dc79SHONG Yifan)
134*bcb5dc79SHONG Yifan
135*bcb5dc79SHONG Yifan# Action creation utilities for Bash actions.
136*bcb5dc79SHONG YifanBASH_STRATEGY = struct(
137*bcb5dc79SHONG Yifan    as_path = _unchanged_path,
138*bcb5dc79SHONG Yifan    create_action = _create_bash_action,
139*bcb5dc79SHONG Yifan)
140