blob: 33261befafe6acafe77a4e62ea99d6114b789a38 [file] [log] [blame]
Richard Levasseurb8f16452023-07-08 09:58:12 -07001# Copyright 2023 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
Richard Levasseur2893d852023-02-15 20:08:22 -080015"""Functionality shared by multiple pieces of code."""
16
Richard Levasseur2df32592023-05-02 09:38:02 -070017load("@bazel_skylib//lib:types.bzl", "types")
Richard Levasseur416bd4c2024-09-26 15:21:50 -070018load("@rules_python_internal//:rules_python_config.bzl", "config")
Richard Levasseur2df32592023-05-02 09:38:02 -070019
Richard Levasseur2893d852023-02-15 20:08:22 -080020def copy_propagating_kwargs(from_kwargs, into_kwargs = None):
21 """Copies args that must be compatible between two targets with a dependency relationship.
22
23 This is intended for when one target depends on another, so they must have
24 compatible settings such as `testonly` and `compatible_with`. This usually
25 happens when a macro generates multiple targets, some of which depend
26 on one another, so their settings must be compatible.
27
28 Args:
29 from_kwargs: keyword args dict whose common kwarg will be copied.
30 into_kwargs: optional keyword args dict that the values from `from_kwargs`
31 will be copied into. The values in this dict will take precedence
32 over the ones in `from_kwargs` (i.e., if this has `testonly` already
33 set, then it won't be overwritten).
34 NOTE: THIS WILL BE MODIFIED IN-PLACE.
35
36 Returns:
37 Keyword args to use for the depender target derived from the dependency
38 target. If `into_kwargs` was passed in, then that same object is
39 returned; this is to facilitate easy `**` expansion.
40 """
41 if into_kwargs == None:
42 into_kwargs = {}
43
44 # Include tags because people generally expect tags to propagate.
45 for attr in ("testonly", "tags", "compatible_with", "restricted_to"):
46 if attr in from_kwargs and attr not in into_kwargs:
47 into_kwargs[attr] = from_kwargs[attr]
48 return into_kwargs
Richard Levasseur3b9c85e2023-03-23 12:59:58 -070049
50# The implementation of the macros and tagging mechanism follows the example
51# set by rules_cc and rules_java.
52
53_MIGRATION_TAG = "__PYTHON_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__"
54
55def add_migration_tag(attrs):
Richard Levasseur2df32592023-05-02 09:38:02 -070056 """Add a special tag to `attrs` to aid migration off native rles.
57
58 Args:
59 attrs: dict of keyword args. The `tags` key will be modified in-place.
60
61 Returns:
62 The same `attrs` object, but modified.
63 """
Richard Levasseur416bd4c2024-09-26 15:21:50 -070064 if not config.enable_pystar:
65 add_tag(attrs, _MIGRATION_TAG)
Richard Levasseurb8f16452023-07-08 09:58:12 -070066 return attrs
67
68def add_tag(attrs, tag):
69 """Adds `tag` to `attrs["tags"]`.
70
71 Args:
72 attrs: dict of keyword args. It is modified in place.
73 tag: str, the tag to add.
74 """
Richard Levasseur3b9c85e2023-03-23 12:59:58 -070075 if "tags" in attrs and attrs["tags"] != None:
Richard Levasseur2df32592023-05-02 09:38:02 -070076 tags = attrs["tags"]
77
78 # Preserve the input type: this allows a test verifying the underlying
79 # rule can accept the tuple for the tags argument.
80 if types.is_tuple(tags):
Richard Levasseurb8f16452023-07-08 09:58:12 -070081 attrs["tags"] = tags + (tag,)
Richard Levasseur2df32592023-05-02 09:38:02 -070082 else:
Richard Levasseurb8f16452023-07-08 09:58:12 -070083 # List concatenation is necessary because the original value
84 # may be a frozen list.
85 attrs["tags"] = tags + [tag]
Richard Levasseur3b9c85e2023-03-23 12:59:58 -070086 else:
Richard Levasseurb8f16452023-07-08 09:58:12 -070087 attrs["tags"] = [tag]
Richard Levasseur69abe802023-11-24 11:21:20 -080088
Richard Levasseur2d34f6c2024-09-26 04:00:51 -070089# Helper to make the provider definitions not crash under Bazel 5.4:
90# Bazel 5.4 doesn't support the `init` arg of `provider()`, so we have to
91# not pass that when using Bazel 5.4. But, not passing the `init` arg
92# changes the return value from a two-tuple to a single value, which then
93# breaks Bazel 6+ code.
94# This isn't actually used under Bazel 5.4, so just stub out the values
95# to get past the loading phase.
96def define_bazel_6_provider(doc, fields, **kwargs):
97 """Define a provider, or a stub for pre-Bazel 7."""
98 if not IS_BAZEL_6_OR_HIGHER:
99 return provider("Stub, not used", fields = []), None
100 return provider(doc = doc, fields = fields, **kwargs)
101
Mark Elliotf40038e2024-10-30 12:11:53 -0400102IS_BAZEL_7_4_OR_HIGHER = hasattr(native, "legacy_globals")
103
Richard Levasseur69abe802023-11-24 11:21:20 -0800104IS_BAZEL_7_OR_HIGHER = hasattr(native, "starlark_doc_extract")
105
106# Bazel 5.4 has a bug where every access of testing.ExecutionInfo is a
107# different object that isn't equal to any other. This is fixed in bazel 6+.
108IS_BAZEL_6_OR_HIGHER = testing.ExecutionInfo == testing.ExecutionInfo
Ziad Shaban8ecad9d2024-01-14 09:54:22 +0100109
110_marker_rule_to_detect_bazel_6_4_or_higher = rule(implementation = lambda ctx: None)
111
112# Bazel 6.4 and higher have a bug fix where rule names show up in the str()
113# of a rule. See
114# https://github.com/bazelbuild/bazel/commit/002490b9a2376f0b2ea4a37102c5e94fc50a65ba
115# https://github.com/bazelbuild/bazel/commit/443cbcb641e17f7337ccfdecdfa5e69bc16cae55
116# This technique is done instead of using native.bazel_version because,
117# under stardoc, the native.bazel_version attribute is entirely missing, which
118# prevents doc generation from being able to correctly generate docs.
119IS_BAZEL_6_4_OR_HIGHER = "_marker_rule_to_detect_bazel_6_4_or_higher" in str(
120 _marker_rule_to_detect_bazel_6_4_or_higher,
121)