Switch to predetermined `constraint_value` targets
This commit is contained in:
parent
ded484cd0a
commit
8d07e16678
|
@ -20,6 +20,7 @@ bzl_library(
|
|||
srcs = ["compatibility.bzl"],
|
||||
deps = [
|
||||
":selects",
|
||||
"//lib/compatibility:defs",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -10,51 +10,7 @@ more information.
|
|||
"""
|
||||
|
||||
load(":selects.bzl", "selects")
|
||||
|
||||
def _get_name_from_target_list(targets, joiner = " or "):
|
||||
"""Join a list of strings into a string which is suitable as a target name.
|
||||
|
||||
The return value has a hash appended so that it is different between multiple "targets" values
|
||||
that have the same name portion. For readability, we keep only the name portion of the
|
||||
specified targets. But for uniqueness we need the hash. For example, the following two calls
|
||||
may return strings as follows. The hashes are arbitrary in this example.
|
||||
|
||||
>>> _get_name_from_target_list(["@platforms//os:linux", "@platforms//cpu:x86_64"])
|
||||
"linux or x86_64 (3ef2349)"
|
||||
>>> _get_name_from_target_list(["//some/custom:linux", "//some/custom:x86_64"])
|
||||
"linux or x86_64 (98ab64)"
|
||||
|
||||
Args:
|
||||
targets: A list of target names.
|
||||
joiner: An optional string to use for joining the list.
|
||||
|
||||
Returns:
|
||||
A string which is a valid target name.
|
||||
"""
|
||||
|
||||
# Compute absolute labels from the user-specified ones. They can be
|
||||
# relative or absolute. We do this to make the final name as unique as
|
||||
# possible via a hash.
|
||||
package_label = Label("//" + native.package_name())
|
||||
absolute_targets = sorted([package_label.relative(target) for target in targets])
|
||||
joined_names = joiner.join([target.name for target in absolute_targets])
|
||||
name = "%s (%x)" % (joined_names, hash(str(absolute_targets)))
|
||||
return name
|
||||
|
||||
def _maybe_make_unique_incompatible_value(name):
|
||||
"""Creates a `native.constraint_value` which is "incompatible."
|
||||
|
||||
When composing selects which could all resolve to "incompatible" we need distinct labels.
|
||||
This will create a `constraint_value` with the given name, if it does not already exist.
|
||||
|
||||
Args:
|
||||
name: A target name to check and use.
|
||||
"""
|
||||
if not native.existing_rule(name):
|
||||
native.constraint_value(
|
||||
name = name,
|
||||
constraint_setting = "@platforms//:incompatible_setting",
|
||||
)
|
||||
load("//lib/compatibility:defs.bzl", "MAX_NUM_ALL_OF_SETTINGS")
|
||||
|
||||
def _none_of(*settings):
|
||||
"""Create a `select()` for `target_compatible_with` which matches none of the given settings.
|
||||
|
@ -83,12 +39,9 @@ def _none_of(*settings):
|
|||
Returns:
|
||||
A native `select()` which maps any of the settings to the incompatible target.
|
||||
"""
|
||||
compat_name = " incompatible with " + _get_name_from_target_list(settings)
|
||||
_maybe_make_unique_incompatible_value(compat_name)
|
||||
|
||||
return selects.with_or({
|
||||
"//conditions:default": [],
|
||||
tuple(settings): [":" + compat_name],
|
||||
tuple(settings): ["@bazel_skylib//lib/compatibility:none_of"],
|
||||
})
|
||||
|
||||
def _any_of(*settings):
|
||||
|
@ -118,12 +71,9 @@ def _any_of(*settings):
|
|||
Returns:
|
||||
A native `select()` which maps any of the settings an empty list.
|
||||
"""
|
||||
compat_name = " compatible with any of " + _get_name_from_target_list(settings)
|
||||
_maybe_make_unique_incompatible_value(compat_name)
|
||||
|
||||
return selects.with_or({
|
||||
tuple(settings): [],
|
||||
"//conditions:default": [":" + compat_name],
|
||||
"//conditions:default": ["@bazel_skylib//lib/compatibility:any_of"],
|
||||
})
|
||||
|
||||
def _all_of(*settings):
|
||||
|
@ -160,23 +110,18 @@ def _all_of(*settings):
|
|||
*settings: The `config_setting` or `constraint_value` targets.
|
||||
|
||||
Returns:
|
||||
A native `select()` which is "incompatible" unless all settings are true.
|
||||
A native series of `select()`s. The result is "incompatible" unless all settings are true.
|
||||
"""
|
||||
group_name = _get_name_from_target_list(settings, joiner = " and ")
|
||||
compat_name = " compatible with all of " + group_name
|
||||
_maybe_make_unique_incompatible_value(compat_name)
|
||||
if len(settings) > MAX_NUM_ALL_OF_SETTINGS:
|
||||
fail("Cannot support more than {} arguments. Use selects.config_setting_group() instead.".format(MAX_NUM_ALL_OF_SETTINGS))
|
||||
|
||||
# all_of can only be accomplished with a config_setting_group.match_all.
|
||||
if not native.existing_rule(group_name):
|
||||
selects.config_setting_group(
|
||||
name = group_name,
|
||||
match_all = settings,
|
||||
)
|
||||
|
||||
return select({
|
||||
":" + group_name: [],
|
||||
"//conditions:default": [":" + compat_name],
|
||||
})
|
||||
result = []
|
||||
for i, setting in enumerate(settings):
|
||||
result += select({
|
||||
setting: [],
|
||||
"//conditions:default": ["@bazel_skylib//lib/compatibility:all_of_{}".format(i)],
|
||||
})
|
||||
return result
|
||||
|
||||
compatibility = struct(
|
||||
all_of = _all_of,
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
load(":defs.bzl", "MAX_NUM_ALL_OF_SETTINGS")
|
||||
load("//:bzl_library.bzl", "bzl_library")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
bzl_library(
|
||||
name = "defs",
|
||||
srcs = ["defs.bzl"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "build_file",
|
||||
testonly = True,
|
||||
srcs = ["BUILD"],
|
||||
)
|
||||
|
||||
constraint_value(
|
||||
name = "none_of",
|
||||
constraint_setting = "@platforms//:incompatible_setting",
|
||||
)
|
||||
|
||||
constraint_value(
|
||||
name = "any_of",
|
||||
constraint_setting = "@platforms//:incompatible_setting",
|
||||
)
|
||||
|
||||
[constraint_value(
|
||||
name = "all_of_" + str(i),
|
||||
constraint_setting = "@platforms//:incompatible_setting",
|
||||
) for i in range(50)]
|
|
@ -0,0 +1,2 @@
|
|||
# The maximum number of arguments we support for compatibility.all_of().
|
||||
MAX_NUM_ALL_OF_SETTINGS = 50
|
|
@ -98,6 +98,7 @@ sh_test(
|
|||
data = [
|
||||
":unittest.bash",
|
||||
"//lib:compatibility",
|
||||
"//lib/compatibility:build_file",
|
||||
],
|
||||
tags = ["local"],
|
||||
deps = [
|
||||
|
|
|
@ -67,11 +67,21 @@ EOF
|
|||
workspace(name = 'bazel_skylib')
|
||||
EOF
|
||||
|
||||
cat > BUILD <<EOF
|
||||
EOF
|
||||
cat > bzl_library.bzl <<EOF
|
||||
def bzl_library(**kwargs):
|
||||
"""A dummy implementation of bzl_library()."""
|
||||
pass
|
||||
EOF
|
||||
|
||||
mkdir -p lib
|
||||
cat > lib/BUILD <<EOF
|
||||
EOF
|
||||
|
||||
for file in compatibility.bzl selects.bzl; do
|
||||
for file in compatibility.bzl selects.bzl compatibility/BUILD compatibility/defs.bzl; do
|
||||
mkdir -p "$(dirname "lib/${file}")" \
|
||||
|| fail "couldn't mkdir for ${file}"
|
||||
ln -sf "$(rlocation "bazel_skylib/lib/${file}")" "lib/${file}" \
|
||||
|| fail "couldn't symlink ${file}."
|
||||
done
|
||||
|
@ -217,7 +227,7 @@ EOF
|
|||
|
||||
ensure_that_target_doesnt_build_for_platforms \
|
||||
//target_skipping:pass_on_foo1_or_foo2_but_not_on_foo3 \
|
||||
"didn't satisfy constraint //target_skipping: compatible with any of foo1 or foo2 (" \
|
||||
"didn't satisfy constraint //lib/compatibility:any_of$" \
|
||||
//target_skipping:foo3_platform \
|
||||
//target_skipping:bar1_platform
|
||||
}
|
||||
|
@ -240,7 +250,7 @@ EOF
|
|||
|
||||
ensure_that_target_doesnt_build_for_platforms \
|
||||
//target_skipping:pass_on_everything_but_foo1_and_foo2 \
|
||||
"didn't satisfy constraint //target_skipping: incompatible with foo1 or foo2 (" \
|
||||
"didn't satisfy constraint //lib/compatibility:none_of$" \
|
||||
//target_skipping:foo1_bar1_platform \
|
||||
//target_skipping:foo2_bar1_platform \
|
||||
//target_skipping:foo2_bar2_platform
|
||||
|
@ -263,7 +273,7 @@ EOF
|
|||
|
||||
ensure_that_target_doesnt_build_for_platforms \
|
||||
//target_skipping:pass_on_only_foo1_and_bar1 \
|
||||
"didn't satisfy constraint //target_skipping: compatible with all of bar1 and foo1 (" \
|
||||
"didn't satisfy constraints\\? \\[\\?//lib/compatibility:all_of_" \
|
||||
//target_skipping:foo2_bar1_platform \
|
||||
//target_skipping:foo2_bar2_platform \
|
||||
//target_skipping:foo3_platform \
|
||||
|
@ -291,24 +301,23 @@ EOF
|
|||
|
||||
ensure_that_target_doesnt_build_for_platforms \
|
||||
//target_skipping:pass_on_foo1_or_foo2_but_not_bar1 \
|
||||
"didn't satisfy constraint //target_skipping: incompatible with bar1 (" \
|
||||
"didn't satisfy constraint //lib/compatibility:none_of$" \
|
||||
//target_skipping:foo1_bar1_platform \
|
||||
//target_skipping:foo2_bar1_platform \
|
||||
//target_skipping:foo2_bar1_platform
|
||||
|
||||
ensure_that_target_doesnt_build_for_platforms \
|
||||
//target_skipping:pass_on_foo1_or_foo2_but_not_bar1 \
|
||||
"didn't satisfy constraint //target_skipping: compatible with any of foo1 or foo2 (" \
|
||||
"didn't satisfy constraint //lib/compatibility:any_of$" \
|
||||
//target_skipping:foo3_platform
|
||||
|
||||
ensure_that_target_doesnt_build_for_platforms \
|
||||
//target_skipping:pass_on_foo1_or_foo2_but_not_bar1 \
|
||||
"didn't satisfy constraints \\[" \
|
||||
"didn't satisfy constraints \\[//lib/compatibility:" \
|
||||
//target_skipping:bar1_platform
|
||||
|
||||
# Since the order of constraints isn't guaranteed until
|
||||
# 72787a1267a6087923aca83bf161f93c0a1323e0, we do two individual checks here.
|
||||
expect_log "//target_skipping: compatible with any of foo1 or foo2 ("
|
||||
expect_log "//target_skipping: incompatible with bar1 ("
|
||||
expect_log "//lib/compatibility:any_of\\>"
|
||||
expect_log "//lib/compatibility:none_of\\>"
|
||||
}
|
||||
|
||||
cd "$TEST_TMPDIR"
|
||||
|
|
Loading…
Reference in New Issue