xref: /aosp_15_r20/external/bazelbuild-rules_android/rules/flags/flags.bzl (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
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 Flags."""
16*9e965d6fSRomain Jobredeaux
17*9e965d6fSRomain Jobredeauxload("//rules:utils.bzl", "utils")
18*9e965d6fSRomain Jobredeaux
19*9e965d6fSRomain Jobredeaux_BoolFlagInfo = provider(
20*9e965d6fSRomain Jobredeaux    doc = "Provides information about a boolean flag",
21*9e965d6fSRomain Jobredeaux    fields = dict(
22*9e965d6fSRomain Jobredeaux        name = "flag name",
23*9e965d6fSRomain Jobredeaux        value = "flag value",
24*9e965d6fSRomain Jobredeaux        explicit = "whether value was set explicitly",
25*9e965d6fSRomain Jobredeaux    ),
26*9e965d6fSRomain Jobredeaux)
27*9e965d6fSRomain Jobredeaux_BoolFlagGroupInfo = provider(
28*9e965d6fSRomain Jobredeaux    doc = "Provides information about a boolean flag group",
29*9e965d6fSRomain Jobredeaux    fields = dict(
30*9e965d6fSRomain Jobredeaux        name = "group name",
31*9e965d6fSRomain Jobredeaux        value = "group value",
32*9e965d6fSRomain Jobredeaux        flags = "flag names that belong to this group",
33*9e965d6fSRomain Jobredeaux    ),
34*9e965d6fSRomain Jobredeaux)
35*9e965d6fSRomain Jobredeaux_IntFlagInfo = provider(
36*9e965d6fSRomain Jobredeaux    doc = "Provides information about an integer flag",
37*9e965d6fSRomain Jobredeaux    fields = dict(
38*9e965d6fSRomain Jobredeaux        name = "flag name",
39*9e965d6fSRomain Jobredeaux        value = "flag value",
40*9e965d6fSRomain Jobredeaux    ),
41*9e965d6fSRomain Jobredeaux)
42*9e965d6fSRomain Jobredeaux_NativeBoolFlagInfo = provider(
43*9e965d6fSRomain Jobredeaux    doc = "Provides information about a native boolean flag",
44*9e965d6fSRomain Jobredeaux    fields = dict(
45*9e965d6fSRomain Jobredeaux        name = "flag name, the name of the native flag being accessed.",
46*9e965d6fSRomain Jobredeaux        value = "flag value, derived from config_setting targets that access the value",
47*9e965d6fSRomain Jobredeaux    ),
48*9e965d6fSRomain Jobredeaux)
49*9e965d6fSRomain JobredeauxFlagsInfo = provider(
50*9e965d6fSRomain Jobredeaux    doc = "Provides all flags",
51*9e965d6fSRomain Jobredeaux)
52*9e965d6fSRomain Jobredeaux
53*9e965d6fSRomain Jobredeauxdef _native_bool_impl(ctx):
54*9e965d6fSRomain Jobredeaux    return _NativeBoolFlagInfo(
55*9e965d6fSRomain Jobredeaux        name = ctx.label.name,
56*9e965d6fSRomain Jobredeaux        value = ctx.attr.value,
57*9e965d6fSRomain Jobredeaux    )
58*9e965d6fSRomain Jobredeaux
59*9e965d6fSRomain Jobredeauxnative_bool_flag = rule(
60*9e965d6fSRomain Jobredeaux    implementation = _native_bool_impl,
61*9e965d6fSRomain Jobredeaux    attrs = dict(
62*9e965d6fSRomain Jobredeaux        value = attr.bool(mandatory = True),
63*9e965d6fSRomain Jobredeaux    ),
64*9e965d6fSRomain Jobredeaux    provides = [_NativeBoolFlagInfo],
65*9e965d6fSRomain Jobredeaux)
66*9e965d6fSRomain Jobredeaux
67*9e965d6fSRomain Jobredeauxdef native_bool_flag_macro(name, description):
68*9e965d6fSRomain Jobredeaux    """Provides access to a native boolean flag from Starlark.
69*9e965d6fSRomain Jobredeaux
70*9e965d6fSRomain Jobredeaux    Args:
71*9e965d6fSRomain Jobredeaux      name: The name of the native flag to access.
72*9e965d6fSRomain Jobredeaux      description: The description of the flag.
73*9e965d6fSRomain Jobredeaux    """
74*9e965d6fSRomain Jobredeaux    native.config_setting(
75*9e965d6fSRomain Jobredeaux        name = name + "_on",
76*9e965d6fSRomain Jobredeaux        values = {name: "True"},
77*9e965d6fSRomain Jobredeaux    )
78*9e965d6fSRomain Jobredeaux    native.config_setting(
79*9e965d6fSRomain Jobredeaux        name = name + "_off",
80*9e965d6fSRomain Jobredeaux        values = {name: "False"},
81*9e965d6fSRomain Jobredeaux    )
82*9e965d6fSRomain Jobredeaux    native_bool_flag(
83*9e965d6fSRomain Jobredeaux        name = name,
84*9e965d6fSRomain Jobredeaux        value = select({
85*9e965d6fSRomain Jobredeaux            (":" + name + "_on"): True,
86*9e965d6fSRomain Jobredeaux            (":" + name + "_off"): False,
87*9e965d6fSRomain Jobredeaux        }),
88*9e965d6fSRomain Jobredeaux    )
89*9e965d6fSRomain Jobredeaux
90*9e965d6fSRomain Jobredeauxdef _get_bool(v):
91*9e965d6fSRomain Jobredeaux    v = v.lower()
92*9e965d6fSRomain Jobredeaux    if v == "true":
93*9e965d6fSRomain Jobredeaux        return True
94*9e965d6fSRomain Jobredeaux    if v == "false":
95*9e965d6fSRomain Jobredeaux        return False
96*9e965d6fSRomain Jobredeaux    fail("Unknown bool: " + v)
97*9e965d6fSRomain Jobredeaux
98*9e965d6fSRomain Jobredeauxdef _bool_impl(ctx):
99*9e965d6fSRomain Jobredeaux    if ctx.label.name in ctx.var:
100*9e965d6fSRomain Jobredeaux        value = _get_bool(ctx.var[ctx.label.name])
101*9e965d6fSRomain Jobredeaux        return _BoolFlagInfo(
102*9e965d6fSRomain Jobredeaux            name = ctx.label.name,
103*9e965d6fSRomain Jobredeaux            value = value,
104*9e965d6fSRomain Jobredeaux            explicit = True,
105*9e965d6fSRomain Jobredeaux        )
106*9e965d6fSRomain Jobredeaux    return _BoolFlagInfo(
107*9e965d6fSRomain Jobredeaux        name = ctx.label.name,
108*9e965d6fSRomain Jobredeaux        value = ctx.attr.default,
109*9e965d6fSRomain Jobredeaux        explicit = False,
110*9e965d6fSRomain Jobredeaux    )
111*9e965d6fSRomain Jobredeaux
112*9e965d6fSRomain Jobredeauxbool_flag = rule(
113*9e965d6fSRomain Jobredeaux    implementation = _bool_impl,
114*9e965d6fSRomain Jobredeaux    attrs = dict(
115*9e965d6fSRomain Jobredeaux        default = attr.bool(
116*9e965d6fSRomain Jobredeaux            mandatory = True,
117*9e965d6fSRomain Jobredeaux        ),
118*9e965d6fSRomain Jobredeaux        description = attr.string(
119*9e965d6fSRomain Jobredeaux            mandatory = True,
120*9e965d6fSRomain Jobredeaux        ),
121*9e965d6fSRomain Jobredeaux    ),
122*9e965d6fSRomain Jobredeaux    provides = [_BoolFlagInfo],
123*9e965d6fSRomain Jobredeaux)
124*9e965d6fSRomain Jobredeaux
125*9e965d6fSRomain Jobredeauxdef _bool_group_impl(ctx):
126*9e965d6fSRomain Jobredeaux    if ctx.label.name in ctx.var:
127*9e965d6fSRomain Jobredeaux        value = _get_bool(ctx.var[ctx.label.name])
128*9e965d6fSRomain Jobredeaux        return _BoolFlagGroupInfo(
129*9e965d6fSRomain Jobredeaux            name = ctx.label.name,
130*9e965d6fSRomain Jobredeaux            value = value,
131*9e965d6fSRomain Jobredeaux            flags = [f[_BoolFlagInfo].name for f in ctx.attr.flags],
132*9e965d6fSRomain Jobredeaux        )
133*9e965d6fSRomain Jobredeaux    return _BoolFlagGroupInfo(
134*9e965d6fSRomain Jobredeaux        name = ctx.label.name,
135*9e965d6fSRomain Jobredeaux        value = ctx.attr.default,
136*9e965d6fSRomain Jobredeaux        flags = [f[_BoolFlagInfo].name for f in ctx.attr.flags],
137*9e965d6fSRomain Jobredeaux    )
138*9e965d6fSRomain Jobredeaux
139*9e965d6fSRomain Jobredeauxbool_flag_group = rule(
140*9e965d6fSRomain Jobredeaux    implementation = _bool_group_impl,
141*9e965d6fSRomain Jobredeaux    attrs = dict(
142*9e965d6fSRomain Jobredeaux        default = attr.bool(
143*9e965d6fSRomain Jobredeaux            mandatory = True,
144*9e965d6fSRomain Jobredeaux        ),
145*9e965d6fSRomain Jobredeaux        description = attr.string(
146*9e965d6fSRomain Jobredeaux            mandatory = True,
147*9e965d6fSRomain Jobredeaux        ),
148*9e965d6fSRomain Jobredeaux        flags = attr.label_list(
149*9e965d6fSRomain Jobredeaux            mandatory = True,
150*9e965d6fSRomain Jobredeaux            providers = [_BoolFlagInfo],
151*9e965d6fSRomain Jobredeaux        ),
152*9e965d6fSRomain Jobredeaux    ),
153*9e965d6fSRomain Jobredeaux    provides = [_BoolFlagGroupInfo],
154*9e965d6fSRomain Jobredeaux)
155*9e965d6fSRomain Jobredeaux
156*9e965d6fSRomain Jobredeauxdef _int_impl(ctx):
157*9e965d6fSRomain Jobredeaux    if ctx.label.name in ctx.var:
158*9e965d6fSRomain Jobredeaux        value = int(ctx.var[ctx.label.name])
159*9e965d6fSRomain Jobredeaux    else:
160*9e965d6fSRomain Jobredeaux        value = ctx.attr.default
161*9e965d6fSRomain Jobredeaux    return _IntFlagInfo(
162*9e965d6fSRomain Jobredeaux        name = ctx.label.name,
163*9e965d6fSRomain Jobredeaux        value = value,
164*9e965d6fSRomain Jobredeaux    )
165*9e965d6fSRomain Jobredeaux
166*9e965d6fSRomain Jobredeauxint_flag = rule(
167*9e965d6fSRomain Jobredeaux    implementation = _int_impl,
168*9e965d6fSRomain Jobredeaux    attrs = dict(
169*9e965d6fSRomain Jobredeaux        default = attr.int(
170*9e965d6fSRomain Jobredeaux            mandatory = True,
171*9e965d6fSRomain Jobredeaux        ),
172*9e965d6fSRomain Jobredeaux        description = attr.string(
173*9e965d6fSRomain Jobredeaux            mandatory = True,
174*9e965d6fSRomain Jobredeaux        ),
175*9e965d6fSRomain Jobredeaux    ),
176*9e965d6fSRomain Jobredeaux    provides = [_IntFlagInfo],
177*9e965d6fSRomain Jobredeaux)
178*9e965d6fSRomain Jobredeaux
179*9e965d6fSRomain Jobredeauxdef _flags_impl_internal(bool_flags, bool_flag_groups, int_flags, native_bool_flags):
180*9e965d6fSRomain Jobredeaux    flags = dict()
181*9e965d6fSRomain Jobredeaux
182*9e965d6fSRomain Jobredeaux    # For each group, set all flags to the group value
183*9e965d6fSRomain Jobredeaux    for fg in bool_flag_groups:
184*9e965d6fSRomain Jobredeaux        for f in fg.flags:
185*9e965d6fSRomain Jobredeaux            if f in flags:
186*9e965d6fSRomain Jobredeaux                fail("Flag '%s' referenced in multiple flag groups" % f)
187*9e965d6fSRomain Jobredeaux            flags[f] = fg.value
188*9e965d6fSRomain Jobredeaux
189*9e965d6fSRomain Jobredeaux    # Set booleans
190*9e965d6fSRomain Jobredeaux    for b in bool_flags:
191*9e965d6fSRomain Jobredeaux        # Always set explicitly specified flags
192*9e965d6fSRomain Jobredeaux        if b.explicit:
193*9e965d6fSRomain Jobredeaux            flags[b.name] = b.value
194*9e965d6fSRomain Jobredeaux            # If not explicit, only set when not set by a group
195*9e965d6fSRomain Jobredeaux
196*9e965d6fSRomain Jobredeaux        elif b.name not in flags:
197*9e965d6fSRomain Jobredeaux            flags[b.name] = b.value
198*9e965d6fSRomain Jobredeaux
199*9e965d6fSRomain Jobredeaux    # Set ints
200*9e965d6fSRomain Jobredeaux    for i in int_flags:
201*9e965d6fSRomain Jobredeaux        flags[i.name] = i.value
202*9e965d6fSRomain Jobredeaux
203*9e965d6fSRomain Jobredeaux    # Set native bool flags
204*9e965d6fSRomain Jobredeaux    for n in native_bool_flags:
205*9e965d6fSRomain Jobredeaux        if n.name in flags:
206*9e965d6fSRomain Jobredeaux            fail("Flag '%s' defined as both native and non-native flag type" % n.name)
207*9e965d6fSRomain Jobredeaux        flags[n.name] = n.value
208*9e965d6fSRomain Jobredeaux
209*9e965d6fSRomain Jobredeaux    return FlagsInfo(**flags)
210*9e965d6fSRomain Jobredeaux
211*9e965d6fSRomain Jobredeauxdef _flags_impl(ctx):
212*9e965d6fSRomain Jobredeaux    return _flags_impl_internal(
213*9e965d6fSRomain Jobredeaux        utils.collect_providers(_BoolFlagInfo, ctx.attr.targets),
214*9e965d6fSRomain Jobredeaux        utils.collect_providers(_BoolFlagGroupInfo, ctx.attr.targets),
215*9e965d6fSRomain Jobredeaux        utils.collect_providers(_IntFlagInfo, ctx.attr.targets),
216*9e965d6fSRomain Jobredeaux        utils.collect_providers(_NativeBoolFlagInfo, ctx.attr.targets),
217*9e965d6fSRomain Jobredeaux    )
218*9e965d6fSRomain Jobredeaux
219*9e965d6fSRomain Jobredeauxflags_rule = rule(
220*9e965d6fSRomain Jobredeaux    implementation = _flags_impl,
221*9e965d6fSRomain Jobredeaux    attrs = dict(
222*9e965d6fSRomain Jobredeaux        targets = attr.label_list(),
223*9e965d6fSRomain Jobredeaux    ),
224*9e965d6fSRomain Jobredeaux)
225*9e965d6fSRomain Jobredeaux
226*9e965d6fSRomain Jobredeauxdef _flags_macro():
227*9e965d6fSRomain Jobredeaux    flags_rule(
228*9e965d6fSRomain Jobredeaux        name = "flags",
229*9e965d6fSRomain Jobredeaux        targets = native.existing_rules().keys(),
230*9e965d6fSRomain Jobredeaux        visibility = ["//visibility:public"],
231*9e965d6fSRomain Jobredeaux    )
232*9e965d6fSRomain Jobredeaux
233*9e965d6fSRomain Jobredeauxdef _get_flags(ctx):
234*9e965d6fSRomain Jobredeaux    return ctx.attr._flags[FlagsInfo]
235*9e965d6fSRomain Jobredeaux
236*9e965d6fSRomain Jobredeauxflags = struct(
237*9e965d6fSRomain Jobredeaux    DEFINE_bool = bool_flag,
238*9e965d6fSRomain Jobredeaux    DEFINE_bool_group = bool_flag_group,
239*9e965d6fSRomain Jobredeaux    DEFINE_int = int_flag,
240*9e965d6fSRomain Jobredeaux    EXPOSE_native_bool = native_bool_flag_macro,
241*9e965d6fSRomain Jobredeaux    FLAGS = _flags_macro,
242*9e965d6fSRomain Jobredeaux    FlagsInfo = FlagsInfo,
243*9e965d6fSRomain Jobredeaux    get = _get_flags,
244*9e965d6fSRomain Jobredeaux)
245*9e965d6fSRomain Jobredeaux
246*9e965d6fSRomain Jobredeauxexported_for_test = struct(
247*9e965d6fSRomain Jobredeaux    BoolFlagGroupInfo = _BoolFlagGroupInfo,
248*9e965d6fSRomain Jobredeaux    BoolFlagInfo = _BoolFlagInfo,
249*9e965d6fSRomain Jobredeaux    IntFlagInfo = _IntFlagInfo,
250*9e965d6fSRomain Jobredeaux    NativeBoolFlagInfo = _NativeBoolFlagInfo,
251*9e965d6fSRomain Jobredeaux    bool_impl = _bool_impl,
252*9e965d6fSRomain Jobredeaux    flags_impl_internal = _flags_impl_internal,
253*9e965d6fSRomain Jobredeaux    int_impl = _int_impl,
254*9e965d6fSRomain Jobredeaux    native_bool_flag_macro = native_bool_flag_macro,
255*9e965d6fSRomain Jobredeaux)
256