Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lib/compatibility.bzl #381

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fa9f398
Create compatibility.bzl
trybka Mar 1, 2021
e86f542
Update compatlib and add some tests.
trybka Mar 23, 2021
b6a5584
Merge remote-tracking branch 'origin/main' into HEAD
philsc Aug 8, 2022
52b2e62
Tweak stuff a bit
philsc Aug 8, 2022
8190b2e
simplify some
philsc Aug 9, 2022
b3d4463
Consolidate tests
philsc Aug 9, 2022
977a070
Simplify some more
philsc Aug 9, 2022
63d9712
Clean up some more
philsc Aug 9, 2022
e202c2b
Get started on docs
philsc Aug 9, 2022
4b34b67
Expand docs a bit
philsc Aug 9, 2022
6abd9ad
Fix some syntax highlighting issues
philsc Aug 9, 2022
dc846a0
regenerate docs
philsc Aug 9, 2022
73b0ed8
Incorporate feedback
philsc Aug 10, 2022
5b4c97c
clean up some more
philsc Aug 10, 2022
b77d66e
Clean up some more
philsc Aug 10, 2022
7568466
Add composed incompatibility to test
philsc Aug 10, 2022
bf4a2cd
Run buildifier
philsc Aug 10, 2022
ee916b0
Fix test
philsc Aug 10, 2022
7939c78
Merge remote-tracking branch 'origin/main' into HEAD
philsc Aug 17, 2022
c333bc4
Remove `bazel shutdown` which is causing segfault on Windows
philsc Aug 17, 2022
d935d67
Switch to *settings
philsc Aug 25, 2022
ded484c
Merge remote-tracking branch 'origin/main' into HEAD
philsc Aug 30, 2022
8d07e16
Switch to predetermined `constraint_value` targets
philsc Aug 30, 2022
0ee8b41
update docs
philsc Aug 30, 2022
04caadf
Fix lint issues
philsc Aug 30, 2022
6765506
Merge remote-tracking branch 'origin/main' into HEAD
philsc Sep 14, 2022
76a22f4
Incorporate feedback
philsc Sep 14, 2022
0d87298
Rename to incompatible_in_*
philsc Sep 14, 2022
9eb896e
Switch everything to @platforms//:incompatible
philsc Sep 18, 2022
d27b58d
delete PATH manipulation
philsc Sep 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -43,6 +43,7 @@ s = shell.quote(p)
## List of modules (in lib/)

* [collections](docs/collections_doc.md)
* [compatibility](docs/compatibility_doc.md)
* [dicts](docs/dicts_doc.md)
* [partial](docs/partial_doc.md)
* [paths](docs/paths_doc.md)
Expand Down
5 changes: 5 additions & 0 deletions docs/BUILD
Expand Up @@ -26,6 +26,11 @@ stardoc_with_diff_test(
out_label = "//docs:common_settings_doc.md",
)

stardoc_with_diff_test(
bzl_library_target = "//lib:compatibility",
out_label = "//docs:compatibility_doc.md",
)

stardoc_with_diff_test(
name = "copy_directory",
bzl_library_target = "//rules:copy_directory",
Expand Down
145 changes: 145 additions & 0 deletions docs/compatibility_doc.md
@@ -0,0 +1,145 @@
<!-- Generated with Stardoc: http://skydoc.bazel.build -->

Skylib module of convenience functions for `target_compatible_with`.

Load the macros as follows in your `BUILD` files:
```python
load("@bazel_skylib//lib:compatibility.bzl", "compatibility")
```

See the [Platform docs](https://bazel.build/docs/platforms#skipping-incompatible-targets) for
more information.


<a id="#compatibility.all_of"></a>

## compatibility.all_of
comius marked this conversation as resolved.
Show resolved Hide resolved

<pre>
compatibility.all_of(<a href="#compatibility.all_of-settings">settings</a>)
</pre>

Create a `select()` for `target_compatible_with` which matches all of the given settings.

All of the settings must be true to get an empty list. Failure to match will result
in an incompatible `constraint_value` for the purpose of target skipping.

In other words, use this function to make a target incompatible unless all of the settings are
true.

Example:

```python
config_setting(
name = "dbg",
values = {"compilation_mode": "dbg"},
)

cc_binary(
name = "bin",
srcs = ["bin.cc"],
# This target can only be built for Linux in debug mode.
target_compatible_with = compatibility.all_of(
":dbg",
"@platforms//os:linux",
),
)
```

See also: `selects.config_setting_group(match_all)`


**PARAMETERS**


| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="compatibility.all_of-settings"></a>settings | The <code>config_setting</code> or <code>constraint_value</code> targets. | none |

**RETURNS**

A native series of `select()`s. The result is "incompatible" unless all settings are true.


<a id="#compatibility.any_of"></a>

## compatibility.any_of

<pre>
compatibility.any_of(<a href="#compatibility.any_of-settings">settings</a>)
</pre>

Create a `select()` for `target_compatible_with` which matches any of the given settings.

Any of the settings will resolve to an empty list, while the default condition will map to
an incompatible `constraint_value` for the purpose of target skipping.

In other words, use this function to make target incompatible unless one or more of the
settings are true.

```python
cc_binary(
name = "bin",
srcs = ["bin.cc"],
# This target can only be built for Linux or Mac.
target_compatible_with = compatibility.any_of(
"@platforms//os:linux",
"@platforms//os:macos",
),
)
```


**PARAMETERS**


| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="compatibility.any_of-settings"></a>settings | The <code>config_settings</code> or <code>constraint_value</code> targets. | none |

**RETURNS**

A native `select()` which maps any of the settings an empty list.


<a id="#compatibility.none_of"></a>

## compatibility.none_of

<pre>
compatibility.none_of(<a href="#compatibility.none_of-settings">settings</a>)
</pre>

Create a `select()` for `target_compatible_with` which matches none of the given settings.

Any of the settings will resolve to an incompatible `constraint_value` for the
purpose of target skipping.

In other words, use this function to make target incompatible if any of the settings are true.

```python
cc_binary(
name = "bin",
srcs = ["bin.cc"],
# This target cannot be built for Linux or Mac, but can be built for
# everything else.
target_compatible_with = compatibility.none_of(
"@platforms//os:linux",
"@platforms//os:macos",
),
)
```


**PARAMETERS**


| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="compatibility.none_of-settings"></a>settings | The <code>config_setting</code> or <code>constraint_value</code> targets. | none |

**RETURNS**

A native `select()` which maps any of the settings to the incompatible target.


8 changes: 8 additions & 0 deletions lib/BUILD
Expand Up @@ -15,6 +15,14 @@ bzl_library(
srcs = ["collections.bzl"],
)

bzl_library(
name = "compatibility",
srcs = ["compatibility.bzl"],
deps = [
":selects",
],
)

bzl_library(
name = "dicts",
srcs = ["dicts.bzl"],
Expand Down
126 changes: 126 additions & 0 deletions lib/compatibility.bzl
@@ -0,0 +1,126 @@
"""Skylib module of convenience functions for `target_compatible_with`.

Load the macros as follows in your `BUILD` files:
```python
load("@bazel_skylib//lib:compatibility.bzl", "compatibility")
```

See the [Platform docs](https://bazel.build/docs/platforms#skipping-incompatible-targets) for
more information.
"""

load(":selects.bzl", "selects")

def _none_of(*settings):
"""Create a `select()` for `target_compatible_with` which matches none of the given settings.

Any of the settings will resolve to an incompatible `constraint_value` for the
purpose of target skipping.

In other words, use this function to make target incompatible if any of the settings are true.

```python
cc_binary(
name = "bin",
srcs = ["bin.cc"],
# This target cannot be built for Linux or Mac, but can be built for
# everything else.
target_compatible_with = compatibility.none_of(
"@platforms//os:linux",
"@platforms//os:macos",
),
)
```

Args:
*settings: The `config_setting` or `constraint_value` targets.

Returns:
A native `select()` which maps any of the settings to the incompatible target.
"""
return selects.with_or({
tuple(settings): ["@platforms//:incompatible"],
"//conditions:default": [],
})

def _any_of(*settings):
"""Create a `select()` for `target_compatible_with` which matches any of the given settings.

Any of the settings will resolve to an empty list, while the default condition will map to
an incompatible `constraint_value` for the purpose of target skipping.

In other words, use this function to make target incompatible unless one or more of the
settings are true.

```python
cc_binary(
name = "bin",
srcs = ["bin.cc"],
# This target can only be built for Linux or Mac.
target_compatible_with = compatibility.any_of(
"@platforms//os:linux",
"@platforms//os:macos",
),
)
```

Args:
*settings: The `config_settings` or `constraint_value` targets.

Returns:
A native `select()` which maps any of the settings an empty list.
"""
return selects.with_or({
tuple(settings): [],
"//conditions:default": ["@platforms//:incompatible"],
})

def _all_of(*settings):
"""Create a `select()` for `target_compatible_with` which matches all of the given settings.

All of the settings must be true to get an empty list. Failure to match will result
in an incompatible `constraint_value` for the purpose of target skipping.

In other words, use this function to make a target incompatible unless all of the settings are
true.

Example:

```python
config_setting(
name = "dbg",
values = {"compilation_mode": "dbg"},
)

cc_binary(
name = "bin",
srcs = ["bin.cc"],
# This target can only be built for Linux in debug mode.
target_compatible_with = compatibility.all_of(
":dbg",
"@platforms//os:linux",
),
)
```

See also: `selects.config_setting_group(match_all)`

Args:
*settings: The `config_setting` or `constraint_value` targets.

Returns:
A native series of `select()`s. The result is "incompatible" unless all settings are true.
"""
result = []
for setting in settings:
result += select({
setting: [],
"//conditions:default": ["@platforms//:incompatible"],
})
return result

compatibility = struct(
all_of = _all_of,
any_of = _any_of,
none_of = _none_of,
)
13 changes: 13 additions & 0 deletions tests/BUILD
Expand Up @@ -92,6 +92,19 @@ sh_test(
tags = ["local"],
)

sh_test(
name = "compatibility_test",
srcs = ["compatibility_test.sh"],
data = [
":unittest.bash",
"//lib:compatibility",
],
tags = ["local"],
deps = [
"@bazel_tools//tools/bash/runfiles",
],
)

shell_args_test_gen(
name = "shell_spawn_e2e_test_src",
)
Expand Down