xref: /aosp_15_r20/external/bazelbuild-rules_python/python/private/common/common.bzl (revision 60517a1edbc8ecf509223e9af94a7adec7d736b8)
1*60517a1eSAndroid Build Coastguard Worker# Copyright 2022 The Bazel Authors. All rights reserved.
2*60517a1eSAndroid Build Coastguard Worker#
3*60517a1eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*60517a1eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*60517a1eSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*60517a1eSAndroid Build Coastguard Worker#
7*60517a1eSAndroid Build Coastguard Worker#    http://www.apache.org/licenses/LICENSE-2.0
8*60517a1eSAndroid Build Coastguard Worker#
9*60517a1eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*60517a1eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*60517a1eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*60517a1eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*60517a1eSAndroid Build Coastguard Worker# limitations under the License.
14*60517a1eSAndroid Build Coastguard Worker"""Various things common to Bazel and Google rule implementations."""
15*60517a1eSAndroid Build Coastguard Worker
16*60517a1eSAndroid Build Coastguard Workerload("//python/private:reexports.bzl", "BuiltinPyInfo")
17*60517a1eSAndroid Build Coastguard Workerload(":cc_helper.bzl", "cc_helper")
18*60517a1eSAndroid Build Coastguard Workerload(":providers.bzl", "PyInfo")
19*60517a1eSAndroid Build Coastguard Workerload(":py_internal.bzl", "py_internal")
20*60517a1eSAndroid Build Coastguard Workerload(
21*60517a1eSAndroid Build Coastguard Worker    ":semantics.bzl",
22*60517a1eSAndroid Build Coastguard Worker    "NATIVE_RULES_MIGRATION_FIX_CMD",
23*60517a1eSAndroid Build Coastguard Worker    "NATIVE_RULES_MIGRATION_HELP_URL",
24*60517a1eSAndroid Build Coastguard Worker)
25*60517a1eSAndroid Build Coastguard Worker
26*60517a1eSAndroid Build Coastguard Worker_testing = testing
27*60517a1eSAndroid Build Coastguard Worker_platform_common = platform_common
28*60517a1eSAndroid Build Coastguard Worker_coverage_common = coverage_common
29*60517a1eSAndroid Build Coastguard Worker_py_builtins = py_internal
30*60517a1eSAndroid Build Coastguard WorkerPackageSpecificationInfo = getattr(py_internal, "PackageSpecificationInfo", None)
31*60517a1eSAndroid Build Coastguard Worker
32*60517a1eSAndroid Build Coastguard Worker# Extensions without the dot
33*60517a1eSAndroid Build Coastguard Worker_PYTHON_SOURCE_EXTENSIONS = ["py"]
34*60517a1eSAndroid Build Coastguard Worker
35*60517a1eSAndroid Build Coastguard Worker# NOTE: Must stay in sync with the value used in rules_python
36*60517a1eSAndroid Build Coastguard Worker_MIGRATION_TAG = "__PYTHON_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__"
37*60517a1eSAndroid Build Coastguard Worker
38*60517a1eSAndroid Build Coastguard Workerdef create_binary_semantics_struct(
39*60517a1eSAndroid Build Coastguard Worker        *,
40*60517a1eSAndroid Build Coastguard Worker        create_executable,
41*60517a1eSAndroid Build Coastguard Worker        get_cc_details_for_binary,
42*60517a1eSAndroid Build Coastguard Worker        get_central_uncachable_version_file,
43*60517a1eSAndroid Build Coastguard Worker        get_coverage_deps,
44*60517a1eSAndroid Build Coastguard Worker        get_debugger_deps,
45*60517a1eSAndroid Build Coastguard Worker        get_extra_common_runfiles_for_binary,
46*60517a1eSAndroid Build Coastguard Worker        get_extra_providers,
47*60517a1eSAndroid Build Coastguard Worker        get_extra_write_build_data_env,
48*60517a1eSAndroid Build Coastguard Worker        get_interpreter_path,
49*60517a1eSAndroid Build Coastguard Worker        get_imports,
50*60517a1eSAndroid Build Coastguard Worker        get_native_deps_dso_name,
51*60517a1eSAndroid Build Coastguard Worker        get_native_deps_user_link_flags,
52*60517a1eSAndroid Build Coastguard Worker        get_stamp_flag,
53*60517a1eSAndroid Build Coastguard Worker        maybe_precompile,
54*60517a1eSAndroid Build Coastguard Worker        should_build_native_deps_dso,
55*60517a1eSAndroid Build Coastguard Worker        should_create_init_files,
56*60517a1eSAndroid Build Coastguard Worker        should_include_build_data):
57*60517a1eSAndroid Build Coastguard Worker    """Helper to ensure a semantics struct has all necessary fields.
58*60517a1eSAndroid Build Coastguard Worker
59*60517a1eSAndroid Build Coastguard Worker    Call this instead of a raw call to `struct(...)`; it'll help ensure all
60*60517a1eSAndroid Build Coastguard Worker    the necessary functions are being correctly provided.
61*60517a1eSAndroid Build Coastguard Worker
62*60517a1eSAndroid Build Coastguard Worker    Args:
63*60517a1eSAndroid Build Coastguard Worker        create_executable: Callable; creates a binary's executable output. See
64*60517a1eSAndroid Build Coastguard Worker            py_executable.bzl#py_executable_base_impl for details.
65*60517a1eSAndroid Build Coastguard Worker        get_cc_details_for_binary: Callable that returns a `CcDetails` struct; see
66*60517a1eSAndroid Build Coastguard Worker            `create_cc_detail_struct`.
67*60517a1eSAndroid Build Coastguard Worker        get_central_uncachable_version_file: Callable that returns an optional
68*60517a1eSAndroid Build Coastguard Worker            Artifact; this artifact is special: it is never cached and is a copy
69*60517a1eSAndroid Build Coastguard Worker            of `ctx.version_file`; see py_builtins.copy_without_caching
70*60517a1eSAndroid Build Coastguard Worker        get_coverage_deps: Callable that returns a list of Targets for making
71*60517a1eSAndroid Build Coastguard Worker            coverage work; only called if coverage is enabled.
72*60517a1eSAndroid Build Coastguard Worker        get_debugger_deps: Callable that returns a list of Targets that provide
73*60517a1eSAndroid Build Coastguard Worker            custom debugger support; only called for target-configuration.
74*60517a1eSAndroid Build Coastguard Worker        get_extra_common_runfiles_for_binary: Callable that returns a runfiles
75*60517a1eSAndroid Build Coastguard Worker            object of extra runfiles a binary should include.
76*60517a1eSAndroid Build Coastguard Worker        get_extra_providers: Callable that returns extra providers; see
77*60517a1eSAndroid Build Coastguard Worker            py_executable.bzl#_create_providers for details.
78*60517a1eSAndroid Build Coastguard Worker        get_extra_write_build_data_env: Callable that returns a dict[str, str]
79*60517a1eSAndroid Build Coastguard Worker            of additional environment variable to pass to build data generation.
80*60517a1eSAndroid Build Coastguard Worker        get_interpreter_path: Callable that returns an optional string, which is
81*60517a1eSAndroid Build Coastguard Worker            the path to the Python interpreter to use for running the binary.
82*60517a1eSAndroid Build Coastguard Worker        get_imports: Callable that returns a list of the target's import
83*60517a1eSAndroid Build Coastguard Worker            paths (from the `imports` attribute, so just the target's own import
84*60517a1eSAndroid Build Coastguard Worker            path strings, not from dependencies).
85*60517a1eSAndroid Build Coastguard Worker        get_native_deps_dso_name: Callable that returns a string, which is the
86*60517a1eSAndroid Build Coastguard Worker            basename (with extension) of the native deps DSO library.
87*60517a1eSAndroid Build Coastguard Worker        get_native_deps_user_link_flags: Callable that returns a list of strings,
88*60517a1eSAndroid Build Coastguard Worker            which are any extra linker flags to pass onto the native deps DSO
89*60517a1eSAndroid Build Coastguard Worker            linking action.
90*60517a1eSAndroid Build Coastguard Worker        get_stamp_flag: Callable that returns bool of if the --stamp flag was
91*60517a1eSAndroid Build Coastguard Worker            enabled or not.
92*60517a1eSAndroid Build Coastguard Worker        maybe_precompile: Callable that may optional precompile the input `.py`
93*60517a1eSAndroid Build Coastguard Worker            sources and returns the full set of desired outputs derived from
94*60517a1eSAndroid Build Coastguard Worker            the source files (e.g., both py and pyc, only one of them, etc).
95*60517a1eSAndroid Build Coastguard Worker        should_build_native_deps_dso: Callable that returns bool; True if
96*60517a1eSAndroid Build Coastguard Worker            building a native deps DSO is supported, False if not.
97*60517a1eSAndroid Build Coastguard Worker        should_create_init_files: Callable that returns bool; True if
98*60517a1eSAndroid Build Coastguard Worker            `__init__.py` files should be generated, False if not.
99*60517a1eSAndroid Build Coastguard Worker        should_include_build_data: Callable that returns bool; True if
100*60517a1eSAndroid Build Coastguard Worker            build data should be generated, False if not.
101*60517a1eSAndroid Build Coastguard Worker    Returns:
102*60517a1eSAndroid Build Coastguard Worker        A "BinarySemantics" struct.
103*60517a1eSAndroid Build Coastguard Worker    """
104*60517a1eSAndroid Build Coastguard Worker    return struct(
105*60517a1eSAndroid Build Coastguard Worker        # keep-sorted
106*60517a1eSAndroid Build Coastguard Worker        create_executable = create_executable,
107*60517a1eSAndroid Build Coastguard Worker        get_cc_details_for_binary = get_cc_details_for_binary,
108*60517a1eSAndroid Build Coastguard Worker        get_central_uncachable_version_file = get_central_uncachable_version_file,
109*60517a1eSAndroid Build Coastguard Worker        get_coverage_deps = get_coverage_deps,
110*60517a1eSAndroid Build Coastguard Worker        get_debugger_deps = get_debugger_deps,
111*60517a1eSAndroid Build Coastguard Worker        get_extra_common_runfiles_for_binary = get_extra_common_runfiles_for_binary,
112*60517a1eSAndroid Build Coastguard Worker        get_extra_providers = get_extra_providers,
113*60517a1eSAndroid Build Coastguard Worker        get_extra_write_build_data_env = get_extra_write_build_data_env,
114*60517a1eSAndroid Build Coastguard Worker        get_imports = get_imports,
115*60517a1eSAndroid Build Coastguard Worker        get_interpreter_path = get_interpreter_path,
116*60517a1eSAndroid Build Coastguard Worker        get_native_deps_dso_name = get_native_deps_dso_name,
117*60517a1eSAndroid Build Coastguard Worker        get_native_deps_user_link_flags = get_native_deps_user_link_flags,
118*60517a1eSAndroid Build Coastguard Worker        get_stamp_flag = get_stamp_flag,
119*60517a1eSAndroid Build Coastguard Worker        maybe_precompile = maybe_precompile,
120*60517a1eSAndroid Build Coastguard Worker        should_build_native_deps_dso = should_build_native_deps_dso,
121*60517a1eSAndroid Build Coastguard Worker        should_create_init_files = should_create_init_files,
122*60517a1eSAndroid Build Coastguard Worker        should_include_build_data = should_include_build_data,
123*60517a1eSAndroid Build Coastguard Worker    )
124*60517a1eSAndroid Build Coastguard Worker
125*60517a1eSAndroid Build Coastguard Workerdef create_library_semantics_struct(
126*60517a1eSAndroid Build Coastguard Worker        *,
127*60517a1eSAndroid Build Coastguard Worker        get_cc_info_for_library,
128*60517a1eSAndroid Build Coastguard Worker        get_imports,
129*60517a1eSAndroid Build Coastguard Worker        maybe_precompile):
130*60517a1eSAndroid Build Coastguard Worker    """Create a `LibrarySemantics` struct.
131*60517a1eSAndroid Build Coastguard Worker
132*60517a1eSAndroid Build Coastguard Worker    Call this instead of a raw call to `struct(...)`; it'll help ensure all
133*60517a1eSAndroid Build Coastguard Worker    the necessary functions are being correctly provided.
134*60517a1eSAndroid Build Coastguard Worker
135*60517a1eSAndroid Build Coastguard Worker    Args:
136*60517a1eSAndroid Build Coastguard Worker        get_cc_info_for_library: Callable that returns a CcInfo for the library;
137*60517a1eSAndroid Build Coastguard Worker            see py_library_impl for arg details.
138*60517a1eSAndroid Build Coastguard Worker        get_imports: Callable; see create_binary_semantics_struct.
139*60517a1eSAndroid Build Coastguard Worker        maybe_precompile: Callable; see create_binary_semantics_struct.
140*60517a1eSAndroid Build Coastguard Worker    Returns:
141*60517a1eSAndroid Build Coastguard Worker        a `LibrarySemantics` struct.
142*60517a1eSAndroid Build Coastguard Worker    """
143*60517a1eSAndroid Build Coastguard Worker    return struct(
144*60517a1eSAndroid Build Coastguard Worker        # keep sorted
145*60517a1eSAndroid Build Coastguard Worker        get_cc_info_for_library = get_cc_info_for_library,
146*60517a1eSAndroid Build Coastguard Worker        get_imports = get_imports,
147*60517a1eSAndroid Build Coastguard Worker        maybe_precompile = maybe_precompile,
148*60517a1eSAndroid Build Coastguard Worker    )
149*60517a1eSAndroid Build Coastguard Worker
150*60517a1eSAndroid Build Coastguard Workerdef create_cc_details_struct(
151*60517a1eSAndroid Build Coastguard Worker        *,
152*60517a1eSAndroid Build Coastguard Worker        cc_info_for_propagating,
153*60517a1eSAndroid Build Coastguard Worker        cc_info_for_self_link,
154*60517a1eSAndroid Build Coastguard Worker        cc_info_with_extra_link_time_libraries,
155*60517a1eSAndroid Build Coastguard Worker        extra_runfiles,
156*60517a1eSAndroid Build Coastguard Worker        cc_toolchain,
157*60517a1eSAndroid Build Coastguard Worker        feature_config,
158*60517a1eSAndroid Build Coastguard Worker        **kwargs):
159*60517a1eSAndroid Build Coastguard Worker    """Creates a CcDetails struct.
160*60517a1eSAndroid Build Coastguard Worker
161*60517a1eSAndroid Build Coastguard Worker    Args:
162*60517a1eSAndroid Build Coastguard Worker        cc_info_for_propagating: CcInfo that is propagated out of the target
163*60517a1eSAndroid Build Coastguard Worker            by returning it within a PyCcLinkParamsProvider object.
164*60517a1eSAndroid Build Coastguard Worker        cc_info_for_self_link: CcInfo that is used when linking for the
165*60517a1eSAndroid Build Coastguard Worker            binary (or its native deps DSO) itself. This may include extra
166*60517a1eSAndroid Build Coastguard Worker            information that isn't propagating (e.g. a custom malloc)
167*60517a1eSAndroid Build Coastguard Worker        cc_info_with_extra_link_time_libraries: CcInfo of extra link time
168*60517a1eSAndroid Build Coastguard Worker            libraries that MUST come after `cc_info_for_self_link` (or possibly
169*60517a1eSAndroid Build Coastguard Worker            always last; not entirely clear) when passed to
170*60517a1eSAndroid Build Coastguard Worker            `link.linking_contexts`.
171*60517a1eSAndroid Build Coastguard Worker        extra_runfiles: runfiles of extra files needed at runtime, usually as
172*60517a1eSAndroid Build Coastguard Worker            part of `cc_info_with_extra_link_time_libraries`; should be added to
173*60517a1eSAndroid Build Coastguard Worker            runfiles.
174*60517a1eSAndroid Build Coastguard Worker        cc_toolchain: CcToolchain that should be used when building.
175*60517a1eSAndroid Build Coastguard Worker        feature_config: struct from cc_configure_features(); see
176*60517a1eSAndroid Build Coastguard Worker            //python/private/common:py_executable.bzl%cc_configure_features.
177*60517a1eSAndroid Build Coastguard Worker        **kwargs: Additional keys/values to set in the returned struct. This is to
178*60517a1eSAndroid Build Coastguard Worker            facilitate extensions with less patching. Any added fields should
179*60517a1eSAndroid Build Coastguard Worker            pick names that are unlikely to collide if the CcDetails API has
180*60517a1eSAndroid Build Coastguard Worker            additional fields added.
181*60517a1eSAndroid Build Coastguard Worker
182*60517a1eSAndroid Build Coastguard Worker    Returns:
183*60517a1eSAndroid Build Coastguard Worker        A `CcDetails` struct.
184*60517a1eSAndroid Build Coastguard Worker    """
185*60517a1eSAndroid Build Coastguard Worker    return struct(
186*60517a1eSAndroid Build Coastguard Worker        cc_info_for_propagating = cc_info_for_propagating,
187*60517a1eSAndroid Build Coastguard Worker        cc_info_for_self_link = cc_info_for_self_link,
188*60517a1eSAndroid Build Coastguard Worker        cc_info_with_extra_link_time_libraries = cc_info_with_extra_link_time_libraries,
189*60517a1eSAndroid Build Coastguard Worker        extra_runfiles = extra_runfiles,
190*60517a1eSAndroid Build Coastguard Worker        cc_toolchain = cc_toolchain,
191*60517a1eSAndroid Build Coastguard Worker        feature_config = feature_config,
192*60517a1eSAndroid Build Coastguard Worker        **kwargs
193*60517a1eSAndroid Build Coastguard Worker    )
194*60517a1eSAndroid Build Coastguard Worker
195*60517a1eSAndroid Build Coastguard Workerdef create_executable_result_struct(*, extra_files_to_build, output_groups, extra_runfiles = None):
196*60517a1eSAndroid Build Coastguard Worker    """Creates a `CreateExecutableResult` struct.
197*60517a1eSAndroid Build Coastguard Worker
198*60517a1eSAndroid Build Coastguard Worker    This is the return value type of the semantics create_executable function.
199*60517a1eSAndroid Build Coastguard Worker
200*60517a1eSAndroid Build Coastguard Worker    Args:
201*60517a1eSAndroid Build Coastguard Worker        extra_files_to_build: depset of File; additional files that should be
202*60517a1eSAndroid Build Coastguard Worker            included as default outputs.
203*60517a1eSAndroid Build Coastguard Worker        output_groups: dict[str, depset[File]]; additional output groups that
204*60517a1eSAndroid Build Coastguard Worker            should be returned.
205*60517a1eSAndroid Build Coastguard Worker        extra_runfiles: A runfiles object of additional runfiles to include.
206*60517a1eSAndroid Build Coastguard Worker
207*60517a1eSAndroid Build Coastguard Worker    Returns:
208*60517a1eSAndroid Build Coastguard Worker        A `CreateExecutableResult` struct.
209*60517a1eSAndroid Build Coastguard Worker    """
210*60517a1eSAndroid Build Coastguard Worker    return struct(
211*60517a1eSAndroid Build Coastguard Worker        extra_files_to_build = extra_files_to_build,
212*60517a1eSAndroid Build Coastguard Worker        output_groups = output_groups,
213*60517a1eSAndroid Build Coastguard Worker        extra_runfiles = extra_runfiles,
214*60517a1eSAndroid Build Coastguard Worker    )
215*60517a1eSAndroid Build Coastguard Worker
216*60517a1eSAndroid Build Coastguard Workerdef union_attrs(*attr_dicts, allow_none = False):
217*60517a1eSAndroid Build Coastguard Worker    """Helper for combining and building attriute dicts for rules.
218*60517a1eSAndroid Build Coastguard Worker
219*60517a1eSAndroid Build Coastguard Worker    Similar to dict.update, except:
220*60517a1eSAndroid Build Coastguard Worker      * Duplicate keys raise an error if they aren't equal. This is to prevent
221*60517a1eSAndroid Build Coastguard Worker        unintentionally replacing an attribute with a potentially incompatible
222*60517a1eSAndroid Build Coastguard Worker        definition.
223*60517a1eSAndroid Build Coastguard Worker      * None values are special: They mean the attribute is required, but the
224*60517a1eSAndroid Build Coastguard Worker        value should be provided by another attribute dict (depending on the
225*60517a1eSAndroid Build Coastguard Worker        `allow_none` arg).
226*60517a1eSAndroid Build Coastguard Worker    Args:
227*60517a1eSAndroid Build Coastguard Worker        *attr_dicts: The dicts to combine.
228*60517a1eSAndroid Build Coastguard Worker        allow_none: bool, if True, then None values are allowed. If False,
229*60517a1eSAndroid Build Coastguard Worker            then one of `attrs_dicts` must set a non-None value for keys
230*60517a1eSAndroid Build Coastguard Worker            with a None value.
231*60517a1eSAndroid Build Coastguard Worker
232*60517a1eSAndroid Build Coastguard Worker    Returns:
233*60517a1eSAndroid Build Coastguard Worker        dict of attributes.
234*60517a1eSAndroid Build Coastguard Worker    """
235*60517a1eSAndroid Build Coastguard Worker    result = {}
236*60517a1eSAndroid Build Coastguard Worker    missing = {}
237*60517a1eSAndroid Build Coastguard Worker    for attr_dict in attr_dicts:
238*60517a1eSAndroid Build Coastguard Worker        for attr_name, value in attr_dict.items():
239*60517a1eSAndroid Build Coastguard Worker            if value == None and not allow_none:
240*60517a1eSAndroid Build Coastguard Worker                if attr_name not in result:
241*60517a1eSAndroid Build Coastguard Worker                    missing[attr_name] = None
242*60517a1eSAndroid Build Coastguard Worker            else:
243*60517a1eSAndroid Build Coastguard Worker                if attr_name in missing:
244*60517a1eSAndroid Build Coastguard Worker                    missing.pop(attr_name)
245*60517a1eSAndroid Build Coastguard Worker
246*60517a1eSAndroid Build Coastguard Worker                if attr_name not in result or result[attr_name] == None:
247*60517a1eSAndroid Build Coastguard Worker                    result[attr_name] = value
248*60517a1eSAndroid Build Coastguard Worker                elif value != None and result[attr_name] != value:
249*60517a1eSAndroid Build Coastguard Worker                    fail("Duplicate attribute name: '{}': existing={}, new={}".format(
250*60517a1eSAndroid Build Coastguard Worker                        attr_name,
251*60517a1eSAndroid Build Coastguard Worker                        result[attr_name],
252*60517a1eSAndroid Build Coastguard Worker                        value,
253*60517a1eSAndroid Build Coastguard Worker                    ))
254*60517a1eSAndroid Build Coastguard Worker
255*60517a1eSAndroid Build Coastguard Worker                # Else, they're equal, so do nothing. This allows merging dicts
256*60517a1eSAndroid Build Coastguard Worker                # that both define the same key from a common place.
257*60517a1eSAndroid Build Coastguard Worker
258*60517a1eSAndroid Build Coastguard Worker    if missing and not allow_none:
259*60517a1eSAndroid Build Coastguard Worker        fail("Required attributes missing: " + csv(missing.keys()))
260*60517a1eSAndroid Build Coastguard Worker    return result
261*60517a1eSAndroid Build Coastguard Worker
262*60517a1eSAndroid Build Coastguard Workerdef csv(values):
263*60517a1eSAndroid Build Coastguard Worker    """Convert a list of strings to comma separated value string."""
264*60517a1eSAndroid Build Coastguard Worker    return ", ".join(sorted(values))
265*60517a1eSAndroid Build Coastguard Worker
266*60517a1eSAndroid Build Coastguard Workerdef filter_to_py_srcs(srcs):
267*60517a1eSAndroid Build Coastguard Worker    """Filters .py files from the given list of files"""
268*60517a1eSAndroid Build Coastguard Worker
269*60517a1eSAndroid Build Coastguard Worker    # TODO(b/203567235): Get the set of recognized extensions from
270*60517a1eSAndroid Build Coastguard Worker    # elsewhere, as there may be others. e.g. Bazel recognizes .py3
271*60517a1eSAndroid Build Coastguard Worker    # as a valid extension.
272*60517a1eSAndroid Build Coastguard Worker    return [f for f in srcs if f.extension == "py"]
273*60517a1eSAndroid Build Coastguard Worker
274*60517a1eSAndroid Build Coastguard Workerdef collect_imports(ctx, semantics):
275*60517a1eSAndroid Build Coastguard Worker    return depset(direct = semantics.get_imports(ctx), transitive = [
276*60517a1eSAndroid Build Coastguard Worker        dep[PyInfo].imports
277*60517a1eSAndroid Build Coastguard Worker        for dep in ctx.attr.deps
278*60517a1eSAndroid Build Coastguard Worker        if PyInfo in dep
279*60517a1eSAndroid Build Coastguard Worker    ] + [
280*60517a1eSAndroid Build Coastguard Worker        dep[BuiltinPyInfo].imports
281*60517a1eSAndroid Build Coastguard Worker        for dep in ctx.attr.deps
282*60517a1eSAndroid Build Coastguard Worker        if BuiltinPyInfo in dep
283*60517a1eSAndroid Build Coastguard Worker    ])
284*60517a1eSAndroid Build Coastguard Worker
285*60517a1eSAndroid Build Coastguard Workerdef collect_runfiles(ctx, files):
286*60517a1eSAndroid Build Coastguard Worker    """Collects the necessary files from the rule's context.
287*60517a1eSAndroid Build Coastguard Worker
288*60517a1eSAndroid Build Coastguard Worker    This presumes the ctx is for a py_binary, py_test, or py_library rule.
289*60517a1eSAndroid Build Coastguard Worker
290*60517a1eSAndroid Build Coastguard Worker    Args:
291*60517a1eSAndroid Build Coastguard Worker        ctx: rule ctx
292*60517a1eSAndroid Build Coastguard Worker        files: depset of extra files to include in the runfiles.
293*60517a1eSAndroid Build Coastguard Worker    Returns:
294*60517a1eSAndroid Build Coastguard Worker        runfiles necessary for the ctx's target.
295*60517a1eSAndroid Build Coastguard Worker    """
296*60517a1eSAndroid Build Coastguard Worker    return ctx.runfiles(
297*60517a1eSAndroid Build Coastguard Worker        transitive_files = files,
298*60517a1eSAndroid Build Coastguard Worker        # This little arg carries a lot of weight, but because Starlark doesn't
299*60517a1eSAndroid Build Coastguard Worker        # have a way to identify if a target is just a File, the equivalent
300*60517a1eSAndroid Build Coastguard Worker        # logic can't be re-implemented in pure-Starlark.
301*60517a1eSAndroid Build Coastguard Worker        #
302*60517a1eSAndroid Build Coastguard Worker        # Under the hood, it calls the Java `Runfiles#addRunfiles(ctx,
303*60517a1eSAndroid Build Coastguard Worker        # DEFAULT_RUNFILES)` method, which is the what the Java implementation
304*60517a1eSAndroid Build Coastguard Worker        # of the Python rules originally did, and the details of how that method
305*60517a1eSAndroid Build Coastguard Worker        # works have become relied on in various ways. Specifically, what it
306*60517a1eSAndroid Build Coastguard Worker        # does is visit the srcs, deps, and data attributes in the following
307*60517a1eSAndroid Build Coastguard Worker        # ways:
308*60517a1eSAndroid Build Coastguard Worker        #
309*60517a1eSAndroid Build Coastguard Worker        # For each target in the "data" attribute...
310*60517a1eSAndroid Build Coastguard Worker        #   If the target is a File, then add that file to the runfiles.
311*60517a1eSAndroid Build Coastguard Worker        #   Otherwise, add the target's **data runfiles** to the runfiles.
312*60517a1eSAndroid Build Coastguard Worker        #
313*60517a1eSAndroid Build Coastguard Worker        # Note that, contray to best practice, the default outputs of the
314*60517a1eSAndroid Build Coastguard Worker        # targets in `data` are *not* added, nor are the default runfiles.
315*60517a1eSAndroid Build Coastguard Worker        #
316*60517a1eSAndroid Build Coastguard Worker        # This ends up being important for several reasons, some of which are
317*60517a1eSAndroid Build Coastguard Worker        # specific to Google-internal features of the rules.
318*60517a1eSAndroid Build Coastguard Worker        #   * For Python executables, we have to use `data_runfiles` to avoid
319*60517a1eSAndroid Build Coastguard Worker        #     conflicts for the build data files. Such files have
320*60517a1eSAndroid Build Coastguard Worker        #     target-specific content, but uses a fixed location, so if a
321*60517a1eSAndroid Build Coastguard Worker        #     binary has another binary in `data`, and both try to specify a
322*60517a1eSAndroid Build Coastguard Worker        #     file for that file path, then a warning is printed and an
323*60517a1eSAndroid Build Coastguard Worker        #     arbitrary one will be used.
324*60517a1eSAndroid Build Coastguard Worker        #   * For rules with _entirely_ different sets of files in data runfiles
325*60517a1eSAndroid Build Coastguard Worker        #     vs default runfiles vs default outputs. For example,
326*60517a1eSAndroid Build Coastguard Worker        #     proto_library: documented behavior of this rule is that putting it
327*60517a1eSAndroid Build Coastguard Worker        #     in the `data` attribute will cause the transitive closure of
328*60517a1eSAndroid Build Coastguard Worker        #     `.proto` source files to be included. This set of sources is only
329*60517a1eSAndroid Build Coastguard Worker        #     in the `data_runfiles` (`default_runfiles` is empty).
330*60517a1eSAndroid Build Coastguard Worker        #   * For rules with a _subset_ of files in data runfiles. For example,
331*60517a1eSAndroid Build Coastguard Worker        #     a certain Google rule used for packaging arbitrary binaries will
332*60517a1eSAndroid Build Coastguard Worker        #     generate multiple versions of a binary (e.g. different archs,
333*60517a1eSAndroid Build Coastguard Worker        #     stripped vs un-stripped, etc) in its default outputs, but only
334*60517a1eSAndroid Build Coastguard Worker        #     one of them in the runfiles; this helps avoid large, unused
335*60517a1eSAndroid Build Coastguard Worker        #     binaries contributing to remote executor input limits.
336*60517a1eSAndroid Build Coastguard Worker        #
337*60517a1eSAndroid Build Coastguard Worker        # Unfortunately, the above behavior also results in surprising behavior
338*60517a1eSAndroid Build Coastguard Worker        # in some cases. For example, simple custom rules that only return their
339*60517a1eSAndroid Build Coastguard Worker        # files in their default outputs won't have their files included. Such
340*60517a1eSAndroid Build Coastguard Worker        # cases must either return their files in runfiles, or use `filegroup()`
341*60517a1eSAndroid Build Coastguard Worker        # which will do so for them.
342*60517a1eSAndroid Build Coastguard Worker        #
343*60517a1eSAndroid Build Coastguard Worker        # For each target in "srcs" and "deps"...
344*60517a1eSAndroid Build Coastguard Worker        #   Add the default runfiles of the target to the runfiles. While this
345*60517a1eSAndroid Build Coastguard Worker        #   is desirable behavior, it also ends up letting a `py_library`
346*60517a1eSAndroid Build Coastguard Worker        #   be put in `srcs` and still mostly work.
347*60517a1eSAndroid Build Coastguard Worker        # TODO(b/224640180): Reject py_library et al rules in srcs.
348*60517a1eSAndroid Build Coastguard Worker        collect_default = True,
349*60517a1eSAndroid Build Coastguard Worker    )
350*60517a1eSAndroid Build Coastguard Worker
351*60517a1eSAndroid Build Coastguard Workerdef create_py_info(ctx, *, direct_sources, direct_pyc_files, imports):
352*60517a1eSAndroid Build Coastguard Worker    """Create PyInfo provider.
353*60517a1eSAndroid Build Coastguard Worker
354*60517a1eSAndroid Build Coastguard Worker    Args:
355*60517a1eSAndroid Build Coastguard Worker        ctx: rule ctx.
356*60517a1eSAndroid Build Coastguard Worker        direct_sources: depset of Files; the direct, raw `.py` sources for the
357*60517a1eSAndroid Build Coastguard Worker            target. This should only be Python source files. It should not
358*60517a1eSAndroid Build Coastguard Worker            include pyc files.
359*60517a1eSAndroid Build Coastguard Worker        direct_pyc_files: depset of Files; the direct `.pyc` sources for the target.
360*60517a1eSAndroid Build Coastguard Worker        imports: depset of strings; the import path values to propagate.
361*60517a1eSAndroid Build Coastguard Worker
362*60517a1eSAndroid Build Coastguard Worker    Returns:
363*60517a1eSAndroid Build Coastguard Worker        A tuple of the PyInfo instance and a depset of the
364*60517a1eSAndroid Build Coastguard Worker        transitive sources collected from dependencies (the latter is only
365*60517a1eSAndroid Build Coastguard Worker        necessary for deprecated extra actions support).
366*60517a1eSAndroid Build Coastguard Worker    """
367*60517a1eSAndroid Build Coastguard Worker    uses_shared_libraries = False
368*60517a1eSAndroid Build Coastguard Worker    has_py2_only_sources = ctx.attr.srcs_version in ("PY2", "PY2ONLY")
369*60517a1eSAndroid Build Coastguard Worker    has_py3_only_sources = ctx.attr.srcs_version in ("PY3", "PY3ONLY")
370*60517a1eSAndroid Build Coastguard Worker    transitive_sources_depsets = []  # list of depsets
371*60517a1eSAndroid Build Coastguard Worker    transitive_sources_files = []  # list of Files
372*60517a1eSAndroid Build Coastguard Worker    transitive_pyc_depsets = [direct_pyc_files]  # list of depsets
373*60517a1eSAndroid Build Coastguard Worker    for target in ctx.attr.deps:
374*60517a1eSAndroid Build Coastguard Worker        # PyInfo may not be present e.g. cc_library rules.
375*60517a1eSAndroid Build Coastguard Worker        if PyInfo in target or BuiltinPyInfo in target:
376*60517a1eSAndroid Build Coastguard Worker            info = _get_py_info(target)
377*60517a1eSAndroid Build Coastguard Worker            transitive_sources_depsets.append(info.transitive_sources)
378*60517a1eSAndroid Build Coastguard Worker            uses_shared_libraries = uses_shared_libraries or info.uses_shared_libraries
379*60517a1eSAndroid Build Coastguard Worker            has_py2_only_sources = has_py2_only_sources or info.has_py2_only_sources
380*60517a1eSAndroid Build Coastguard Worker            has_py3_only_sources = has_py3_only_sources or info.has_py3_only_sources
381*60517a1eSAndroid Build Coastguard Worker
382*60517a1eSAndroid Build Coastguard Worker            # BuiltinPyInfo doesn't have this field.
383*60517a1eSAndroid Build Coastguard Worker            if hasattr(info, "transitive_pyc_files"):
384*60517a1eSAndroid Build Coastguard Worker                transitive_pyc_depsets.append(info.transitive_pyc_files)
385*60517a1eSAndroid Build Coastguard Worker        else:
386*60517a1eSAndroid Build Coastguard Worker            # TODO(b/228692666): Remove this once non-PyInfo targets are no
387*60517a1eSAndroid Build Coastguard Worker            # longer supported in `deps`.
388*60517a1eSAndroid Build Coastguard Worker            files = target.files.to_list()
389*60517a1eSAndroid Build Coastguard Worker            for f in files:
390*60517a1eSAndroid Build Coastguard Worker                if f.extension == "py":
391*60517a1eSAndroid Build Coastguard Worker                    transitive_sources_files.append(f)
392*60517a1eSAndroid Build Coastguard Worker                uses_shared_libraries = (
393*60517a1eSAndroid Build Coastguard Worker                    uses_shared_libraries or
394*60517a1eSAndroid Build Coastguard Worker                    cc_helper.is_valid_shared_library_artifact(f)
395*60517a1eSAndroid Build Coastguard Worker                )
396*60517a1eSAndroid Build Coastguard Worker    deps_transitive_sources = depset(
397*60517a1eSAndroid Build Coastguard Worker        direct = transitive_sources_files,
398*60517a1eSAndroid Build Coastguard Worker        transitive = transitive_sources_depsets,
399*60517a1eSAndroid Build Coastguard Worker    )
400*60517a1eSAndroid Build Coastguard Worker
401*60517a1eSAndroid Build Coastguard Worker    # We only look at data to calculate uses_shared_libraries, if it's already
402*60517a1eSAndroid Build Coastguard Worker    # true, then we don't need to waste time looping over it.
403*60517a1eSAndroid Build Coastguard Worker    if not uses_shared_libraries:
404*60517a1eSAndroid Build Coastguard Worker        # Similar to the above, except we only calculate uses_shared_libraries
405*60517a1eSAndroid Build Coastguard Worker        for target in ctx.attr.data:
406*60517a1eSAndroid Build Coastguard Worker            # TODO(b/234730058): Remove checking for PyInfo in data once depot
407*60517a1eSAndroid Build Coastguard Worker            # cleaned up.
408*60517a1eSAndroid Build Coastguard Worker            if PyInfo in target or BuiltinPyInfo in target:
409*60517a1eSAndroid Build Coastguard Worker                info = _get_py_info(target)
410*60517a1eSAndroid Build Coastguard Worker                uses_shared_libraries = info.uses_shared_libraries
411*60517a1eSAndroid Build Coastguard Worker            else:
412*60517a1eSAndroid Build Coastguard Worker                files = target.files.to_list()
413*60517a1eSAndroid Build Coastguard Worker                for f in files:
414*60517a1eSAndroid Build Coastguard Worker                    uses_shared_libraries = cc_helper.is_valid_shared_library_artifact(f)
415*60517a1eSAndroid Build Coastguard Worker                    if uses_shared_libraries:
416*60517a1eSAndroid Build Coastguard Worker                        break
417*60517a1eSAndroid Build Coastguard Worker            if uses_shared_libraries:
418*60517a1eSAndroid Build Coastguard Worker                break
419*60517a1eSAndroid Build Coastguard Worker
420*60517a1eSAndroid Build Coastguard Worker    py_info_kwargs = dict(
421*60517a1eSAndroid Build Coastguard Worker        transitive_sources = depset(
422*60517a1eSAndroid Build Coastguard Worker            transitive = [deps_transitive_sources, direct_sources],
423*60517a1eSAndroid Build Coastguard Worker        ),
424*60517a1eSAndroid Build Coastguard Worker        imports = imports,
425*60517a1eSAndroid Build Coastguard Worker        # NOTE: This isn't strictly correct, but with Python 2 gone,
426*60517a1eSAndroid Build Coastguard Worker        # the srcs_version logic is largely defunct, so shouldn't matter in
427*60517a1eSAndroid Build Coastguard Worker        # practice.
428*60517a1eSAndroid Build Coastguard Worker        has_py2_only_sources = has_py2_only_sources,
429*60517a1eSAndroid Build Coastguard Worker        has_py3_only_sources = has_py3_only_sources,
430*60517a1eSAndroid Build Coastguard Worker        uses_shared_libraries = uses_shared_libraries,
431*60517a1eSAndroid Build Coastguard Worker        direct_pyc_files = direct_pyc_files,
432*60517a1eSAndroid Build Coastguard Worker        transitive_pyc_files = depset(transitive = transitive_pyc_depsets),
433*60517a1eSAndroid Build Coastguard Worker    )
434*60517a1eSAndroid Build Coastguard Worker
435*60517a1eSAndroid Build Coastguard Worker    # TODO(b/203567235): Set `uses_shared_libraries` field, though the Bazel
436*60517a1eSAndroid Build Coastguard Worker    # docs indicate it's unused in Bazel and may be removed.
437*60517a1eSAndroid Build Coastguard Worker    py_info = PyInfo(**py_info_kwargs)
438*60517a1eSAndroid Build Coastguard Worker
439*60517a1eSAndroid Build Coastguard Worker    # Remove args that BuiltinPyInfo doesn't support
440*60517a1eSAndroid Build Coastguard Worker    py_info_kwargs.pop("direct_pyc_files")
441*60517a1eSAndroid Build Coastguard Worker    py_info_kwargs.pop("transitive_pyc_files")
442*60517a1eSAndroid Build Coastguard Worker    builtin_py_info = BuiltinPyInfo(**py_info_kwargs)
443*60517a1eSAndroid Build Coastguard Worker
444*60517a1eSAndroid Build Coastguard Worker    return py_info, deps_transitive_sources, builtin_py_info
445*60517a1eSAndroid Build Coastguard Worker
446*60517a1eSAndroid Build Coastguard Workerdef _get_py_info(target):
447*60517a1eSAndroid Build Coastguard Worker    return target[PyInfo] if PyInfo in target else target[BuiltinPyInfo]
448*60517a1eSAndroid Build Coastguard Worker
449*60517a1eSAndroid Build Coastguard Workerdef create_instrumented_files_info(ctx):
450*60517a1eSAndroid Build Coastguard Worker    return _coverage_common.instrumented_files_info(
451*60517a1eSAndroid Build Coastguard Worker        ctx,
452*60517a1eSAndroid Build Coastguard Worker        source_attributes = ["srcs"],
453*60517a1eSAndroid Build Coastguard Worker        dependency_attributes = ["deps", "data"],
454*60517a1eSAndroid Build Coastguard Worker        extensions = _PYTHON_SOURCE_EXTENSIONS,
455*60517a1eSAndroid Build Coastguard Worker    )
456*60517a1eSAndroid Build Coastguard Worker
457*60517a1eSAndroid Build Coastguard Workerdef create_output_group_info(transitive_sources, extra_groups):
458*60517a1eSAndroid Build Coastguard Worker    return OutputGroupInfo(
459*60517a1eSAndroid Build Coastguard Worker        compilation_prerequisites_INTERNAL_ = transitive_sources,
460*60517a1eSAndroid Build Coastguard Worker        compilation_outputs = transitive_sources,
461*60517a1eSAndroid Build Coastguard Worker        **extra_groups
462*60517a1eSAndroid Build Coastguard Worker    )
463*60517a1eSAndroid Build Coastguard Worker
464*60517a1eSAndroid Build Coastguard Workerdef maybe_add_test_execution_info(providers, ctx):
465*60517a1eSAndroid Build Coastguard Worker    """Adds ExecutionInfo, if necessary for proper test execution.
466*60517a1eSAndroid Build Coastguard Worker
467*60517a1eSAndroid Build Coastguard Worker    Args:
468*60517a1eSAndroid Build Coastguard Worker        providers: Mutable list of providers; may have ExecutionInfo
469*60517a1eSAndroid Build Coastguard Worker            provider appended.
470*60517a1eSAndroid Build Coastguard Worker        ctx: Rule ctx.
471*60517a1eSAndroid Build Coastguard Worker    """
472*60517a1eSAndroid Build Coastguard Worker
473*60517a1eSAndroid Build Coastguard Worker    # When built for Apple platforms, require the execution to be on a Mac.
474*60517a1eSAndroid Build Coastguard Worker    # TODO(b/176993122): Remove when bazel automatically knows to run on darwin.
475*60517a1eSAndroid Build Coastguard Worker    if target_platform_has_any_constraint(ctx, ctx.attr._apple_constraints):
476*60517a1eSAndroid Build Coastguard Worker        providers.append(_testing.ExecutionInfo({"requires-darwin": ""}))
477*60517a1eSAndroid Build Coastguard Worker
478*60517a1eSAndroid Build Coastguard Worker_BOOL_TYPE = type(True)
479*60517a1eSAndroid Build Coastguard Worker
480*60517a1eSAndroid Build Coastguard Workerdef is_bool(v):
481*60517a1eSAndroid Build Coastguard Worker    return type(v) == _BOOL_TYPE
482*60517a1eSAndroid Build Coastguard Worker
483*60517a1eSAndroid Build Coastguard Workerdef target_platform_has_any_constraint(ctx, constraints):
484*60517a1eSAndroid Build Coastguard Worker    """Check if target platform has any of a list of constraints.
485*60517a1eSAndroid Build Coastguard Worker
486*60517a1eSAndroid Build Coastguard Worker    Args:
487*60517a1eSAndroid Build Coastguard Worker      ctx: rule context.
488*60517a1eSAndroid Build Coastguard Worker      constraints: label_list of constraints.
489*60517a1eSAndroid Build Coastguard Worker
490*60517a1eSAndroid Build Coastguard Worker    Returns:
491*60517a1eSAndroid Build Coastguard Worker      True if target platform has at least one of the constraints.
492*60517a1eSAndroid Build Coastguard Worker    """
493*60517a1eSAndroid Build Coastguard Worker    for constraint in constraints:
494*60517a1eSAndroid Build Coastguard Worker        constraint_value = constraint[_platform_common.ConstraintValueInfo]
495*60517a1eSAndroid Build Coastguard Worker        if ctx.target_platform_has_constraint(constraint_value):
496*60517a1eSAndroid Build Coastguard Worker            return True
497*60517a1eSAndroid Build Coastguard Worker    return False
498*60517a1eSAndroid Build Coastguard Worker
499*60517a1eSAndroid Build Coastguard Workerdef check_native_allowed(ctx):
500*60517a1eSAndroid Build Coastguard Worker    """Check if the usage of the native rule is allowed.
501*60517a1eSAndroid Build Coastguard Worker
502*60517a1eSAndroid Build Coastguard Worker    Args:
503*60517a1eSAndroid Build Coastguard Worker        ctx: rule context to check
504*60517a1eSAndroid Build Coastguard Worker    """
505*60517a1eSAndroid Build Coastguard Worker    if not ctx.fragments.py.disallow_native_rules:
506*60517a1eSAndroid Build Coastguard Worker        return
507*60517a1eSAndroid Build Coastguard Worker
508*60517a1eSAndroid Build Coastguard Worker    if _MIGRATION_TAG in ctx.attr.tags:
509*60517a1eSAndroid Build Coastguard Worker        return
510*60517a1eSAndroid Build Coastguard Worker
511*60517a1eSAndroid Build Coastguard Worker    # NOTE: The main repo name is empty in *labels*, but not in
512*60517a1eSAndroid Build Coastguard Worker    # ctx.workspace_name
513*60517a1eSAndroid Build Coastguard Worker    is_main_repo = not bool(ctx.label.workspace_name)
514*60517a1eSAndroid Build Coastguard Worker    if is_main_repo:
515*60517a1eSAndroid Build Coastguard Worker        check_label = ctx.label
516*60517a1eSAndroid Build Coastguard Worker    else:
517*60517a1eSAndroid Build Coastguard Worker        # package_group doesn't allow @repo syntax, so we work around that
518*60517a1eSAndroid Build Coastguard Worker        # by prefixing external repos with a fake package path. This also
519*60517a1eSAndroid Build Coastguard Worker        # makes it easy to enable or disable all external repos.
520*60517a1eSAndroid Build Coastguard Worker        check_label = Label("@//__EXTERNAL_REPOS__/{workspace}/{package}".format(
521*60517a1eSAndroid Build Coastguard Worker            workspace = ctx.label.workspace_name,
522*60517a1eSAndroid Build Coastguard Worker            package = ctx.label.package,
523*60517a1eSAndroid Build Coastguard Worker        ))
524*60517a1eSAndroid Build Coastguard Worker    allowlist = ctx.attr._native_rules_allowlist
525*60517a1eSAndroid Build Coastguard Worker    if allowlist:
526*60517a1eSAndroid Build Coastguard Worker        allowed = ctx.attr._native_rules_allowlist[PackageSpecificationInfo].contains(check_label)
527*60517a1eSAndroid Build Coastguard Worker        allowlist_help = str(allowlist.label).replace("@//", "//")
528*60517a1eSAndroid Build Coastguard Worker    else:
529*60517a1eSAndroid Build Coastguard Worker        allowed = False
530*60517a1eSAndroid Build Coastguard Worker        allowlist_help = ("no allowlist specified; all disallowed; specify one " +
531*60517a1eSAndroid Build Coastguard Worker                          "with --python_native_rules_allowlist")
532*60517a1eSAndroid Build Coastguard Worker    if not allowed:
533*60517a1eSAndroid Build Coastguard Worker        if ctx.attr.generator_function:
534*60517a1eSAndroid Build Coastguard Worker            generator = "{generator_function}(name={generator_name}) in {generator_location}".format(
535*60517a1eSAndroid Build Coastguard Worker                generator_function = ctx.attr.generator_function,
536*60517a1eSAndroid Build Coastguard Worker                generator_name = ctx.attr.generator_name,
537*60517a1eSAndroid Build Coastguard Worker                generator_location = ctx.attr.generator_location,
538*60517a1eSAndroid Build Coastguard Worker            )
539*60517a1eSAndroid Build Coastguard Worker        else:
540*60517a1eSAndroid Build Coastguard Worker            generator = "No generator (called directly in BUILD file)"
541*60517a1eSAndroid Build Coastguard Worker
542*60517a1eSAndroid Build Coastguard Worker        msg = (
543*60517a1eSAndroid Build Coastguard Worker            "{target} not allowed to use native.{rule}\n" +
544*60517a1eSAndroid Build Coastguard Worker            "Generated by: {generator}\n" +
545*60517a1eSAndroid Build Coastguard Worker            "Allowlist: {allowlist}\n" +
546*60517a1eSAndroid Build Coastguard Worker            "Migrate to using @rules_python, see {help_url}\n" +
547*60517a1eSAndroid Build Coastguard Worker            "FIXCMD: {fix_cmd} --target={target} --rule={rule} " +
548*60517a1eSAndroid Build Coastguard Worker            "--generator_name={generator_name} --location={generator_location}"
549*60517a1eSAndroid Build Coastguard Worker        )
550*60517a1eSAndroid Build Coastguard Worker        fail(msg.format(
551*60517a1eSAndroid Build Coastguard Worker            target = str(ctx.label).replace("@//", "//"),
552*60517a1eSAndroid Build Coastguard Worker            rule = _py_builtins.get_rule_name(ctx),
553*60517a1eSAndroid Build Coastguard Worker            generator = generator,
554*60517a1eSAndroid Build Coastguard Worker            allowlist = allowlist_help,
555*60517a1eSAndroid Build Coastguard Worker            generator_name = ctx.attr.generator_name,
556*60517a1eSAndroid Build Coastguard Worker            generator_location = ctx.attr.generator_location,
557*60517a1eSAndroid Build Coastguard Worker            help_url = NATIVE_RULES_MIGRATION_HELP_URL,
558*60517a1eSAndroid Build Coastguard Worker            fix_cmd = NATIVE_RULES_MIGRATION_FIX_CMD,
559*60517a1eSAndroid Build Coastguard Worker        ))
560