You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
6.7 KiB
256 lines
6.7 KiB
# Copyright 2019 The Bazel Authors. All rights reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""Bazel Flags."""
|
|
|
|
load("@rules_android//rules:utils.bzl", "utils")
|
|
|
|
_BoolFlagInfo = provider(
|
|
doc = "Provides information about a boolean flag",
|
|
fields = dict(
|
|
name = "flag name",
|
|
value = "flag value",
|
|
explicit = "whether value was set explicitly",
|
|
),
|
|
)
|
|
_BoolFlagGroupInfo = provider(
|
|
doc = "Provides information about a boolean flag group",
|
|
fields = dict(
|
|
name = "group name",
|
|
value = "group value",
|
|
flags = "flag names that belong to this group",
|
|
),
|
|
)
|
|
_IntFlagInfo = provider(
|
|
doc = "Provides information about an integer flag",
|
|
fields = dict(
|
|
name = "flag name",
|
|
value = "flag value",
|
|
),
|
|
)
|
|
_NativeBoolFlagInfo = provider(
|
|
doc = "Provides information about a native boolean flag",
|
|
fields = dict(
|
|
name = "flag name, the name of the native flag being accessed.",
|
|
value = "flag value, derived from config_setting targets that access the value",
|
|
),
|
|
)
|
|
FlagsInfo = provider(
|
|
doc = "Provides all flags",
|
|
)
|
|
|
|
def _native_bool_impl(ctx):
|
|
return _NativeBoolFlagInfo(
|
|
name = ctx.label.name,
|
|
value = ctx.attr.value,
|
|
)
|
|
|
|
native_bool_flag = rule(
|
|
implementation = _native_bool_impl,
|
|
attrs = dict(
|
|
value = attr.bool(mandatory = True),
|
|
),
|
|
provides = [_NativeBoolFlagInfo],
|
|
)
|
|
|
|
def native_bool_flag_macro(name, description):
|
|
"""Provides access to a native boolean flag from Starlark.
|
|
|
|
Args:
|
|
name: The name of the native flag to access.
|
|
description: The description of the flag.
|
|
"""
|
|
native.config_setting(
|
|
name = name + "_on",
|
|
values = {name: "True"},
|
|
)
|
|
native.config_setting(
|
|
name = name + "_off",
|
|
values = {name: "False"},
|
|
)
|
|
native_bool_flag(
|
|
name = name,
|
|
value = select({
|
|
(":" + name + "_on"): True,
|
|
(":" + name + "_off"): False,
|
|
}),
|
|
)
|
|
|
|
def _get_bool(v):
|
|
v = v.lower()
|
|
if v == "true":
|
|
return True
|
|
if v == "false":
|
|
return False
|
|
fail("Unknown bool: " + v)
|
|
|
|
def _bool_impl(ctx):
|
|
if ctx.label.name in ctx.var:
|
|
value = _get_bool(ctx.var[ctx.label.name])
|
|
return _BoolFlagInfo(
|
|
name = ctx.label.name,
|
|
value = value,
|
|
explicit = True,
|
|
)
|
|
return _BoolFlagInfo(
|
|
name = ctx.label.name,
|
|
value = ctx.attr.default,
|
|
explicit = False,
|
|
)
|
|
|
|
bool_flag = rule(
|
|
implementation = _bool_impl,
|
|
attrs = dict(
|
|
default = attr.bool(
|
|
mandatory = True,
|
|
),
|
|
description = attr.string(
|
|
mandatory = True,
|
|
),
|
|
),
|
|
provides = [_BoolFlagInfo],
|
|
)
|
|
|
|
def _bool_group_impl(ctx):
|
|
if ctx.label.name in ctx.var:
|
|
value = _get_bool(ctx.var[ctx.label.name])
|
|
return _BoolFlagGroupInfo(
|
|
name = ctx.label.name,
|
|
value = value,
|
|
flags = [f[_BoolFlagInfo].name for f in ctx.attr.flags],
|
|
)
|
|
return _BoolFlagGroupInfo(
|
|
name = ctx.label.name,
|
|
value = ctx.attr.default,
|
|
flags = [f[_BoolFlagInfo].name for f in ctx.attr.flags],
|
|
)
|
|
|
|
bool_flag_group = rule(
|
|
implementation = _bool_group_impl,
|
|
attrs = dict(
|
|
default = attr.bool(
|
|
mandatory = True,
|
|
),
|
|
description = attr.string(
|
|
mandatory = True,
|
|
),
|
|
flags = attr.label_list(
|
|
mandatory = True,
|
|
providers = [_BoolFlagInfo],
|
|
),
|
|
),
|
|
provides = [_BoolFlagGroupInfo],
|
|
)
|
|
|
|
def _int_impl(ctx):
|
|
if ctx.label.name in ctx.var:
|
|
value = int(ctx.var[ctx.label.name])
|
|
else:
|
|
value = ctx.attr.default
|
|
return _IntFlagInfo(
|
|
name = ctx.label.name,
|
|
value = value,
|
|
)
|
|
|
|
int_flag = rule(
|
|
implementation = _int_impl,
|
|
attrs = dict(
|
|
default = attr.int(
|
|
mandatory = True,
|
|
),
|
|
description = attr.string(
|
|
mandatory = True,
|
|
),
|
|
),
|
|
provides = [_IntFlagInfo],
|
|
)
|
|
|
|
def _flags_impl_internal(bool_flags, bool_flag_groups, int_flags, native_bool_flags):
|
|
flags = dict()
|
|
|
|
# For each group, set all flags to the group value
|
|
for fg in bool_flag_groups:
|
|
for f in fg.flags:
|
|
if f in flags:
|
|
fail("Flag '%s' referenced in multiple flag groups" % f)
|
|
flags[f] = fg.value
|
|
|
|
# Set booleans
|
|
for b in bool_flags:
|
|
# Always set explicitly specified flags
|
|
if b.explicit:
|
|
flags[b.name] = b.value
|
|
# If not explicit, only set when not set by a group
|
|
|
|
elif b.name not in flags:
|
|
flags[b.name] = b.value
|
|
|
|
# Set ints
|
|
for i in int_flags:
|
|
flags[i.name] = i.value
|
|
|
|
# Set native bool flags
|
|
for n in native_bool_flags:
|
|
if n.name in flags:
|
|
fail("Flag '%s' defined as both native and non-native flag type" % n.name)
|
|
flags[n.name] = n.value
|
|
|
|
return FlagsInfo(**flags)
|
|
|
|
def _flags_impl(ctx):
|
|
return _flags_impl_internal(
|
|
utils.collect_providers(_BoolFlagInfo, ctx.attr.targets),
|
|
utils.collect_providers(_BoolFlagGroupInfo, ctx.attr.targets),
|
|
utils.collect_providers(_IntFlagInfo, ctx.attr.targets),
|
|
utils.collect_providers(_NativeBoolFlagInfo, ctx.attr.targets),
|
|
)
|
|
|
|
flags_rule = rule(
|
|
implementation = _flags_impl,
|
|
attrs = dict(
|
|
targets = attr.label_list(),
|
|
),
|
|
)
|
|
|
|
def _flags_macro():
|
|
flags_rule(
|
|
name = "flags",
|
|
targets = native.existing_rules().keys(),
|
|
visibility = ["//visibility:public"],
|
|
)
|
|
|
|
def _get_flags(ctx):
|
|
return ctx.attr._flags[FlagsInfo]
|
|
|
|
flags = struct(
|
|
DEFINE_bool = bool_flag,
|
|
DEFINE_bool_group = bool_flag_group,
|
|
DEFINE_int = int_flag,
|
|
EXPOSE_native_bool = native_bool_flag_macro,
|
|
FLAGS = _flags_macro,
|
|
FlagsInfo = FlagsInfo,
|
|
get = _get_flags,
|
|
)
|
|
|
|
exported_for_test = struct(
|
|
BoolFlagGroupInfo = _BoolFlagGroupInfo,
|
|
BoolFlagInfo = _BoolFlagInfo,
|
|
IntFlagInfo = _IntFlagInfo,
|
|
NativeBoolFlagInfo = _NativeBoolFlagInfo,
|
|
bool_impl = _bool_impl,
|
|
flags_impl_internal = _flags_impl_internal,
|
|
int_impl = _int_impl,
|
|
native_bool_flag_macro = native_bool_flag_macro,
|
|
)
|