xref: /aosp_15_r20/external/bazelbuild-rules_python/python/private/common/py_library.bzl (revision 60517a1edbc8ecf509223e9af94a7adec7d736b8)
1# Copyright 2022 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"""Implementation of py_library rule."""
15
16load("@bazel_skylib//lib:dicts.bzl", "dicts")
17load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
18load("//python/private:flags.bzl", "PrecompileAddToRunfilesFlag")
19load(
20    "//python/private:toolchain_types.bzl",
21    "EXEC_TOOLS_TOOLCHAIN_TYPE",
22    TOOLCHAIN_TYPE = "TARGET_TOOLCHAIN_TYPE",
23)
24load(
25    ":attributes.bzl",
26    "COMMON_ATTRS",
27    "PY_SRCS_ATTRS",
28    "SRCS_VERSION_ALL_VALUES",
29    "create_srcs_attr",
30    "create_srcs_version_attr",
31)
32load(
33    ":common.bzl",
34    "check_native_allowed",
35    "collect_imports",
36    "collect_runfiles",
37    "create_instrumented_files_info",
38    "create_output_group_info",
39    "create_py_info",
40    "filter_to_py_srcs",
41    "union_attrs",
42)
43load(":providers.bzl", "PyCcLinkParamsProvider")
44load(":py_internal.bzl", "py_internal")
45
46_py_builtins = py_internal
47
48LIBRARY_ATTRS = union_attrs(
49    COMMON_ATTRS,
50    PY_SRCS_ATTRS,
51    create_srcs_version_attr(values = SRCS_VERSION_ALL_VALUES),
52    create_srcs_attr(mandatory = False),
53)
54
55def py_library_impl(ctx, *, semantics):
56    """Abstract implementation of py_library rule.
57
58    Args:
59        ctx: The rule ctx
60        semantics: A `LibrarySemantics` struct; see `create_library_semantics_struct`
61
62    Returns:
63        A list of modern providers to propagate.
64    """
65    check_native_allowed(ctx)
66    direct_sources = filter_to_py_srcs(ctx.files.srcs)
67
68    precompile_result = semantics.maybe_precompile(ctx, direct_sources)
69    direct_pyc_files = depset(precompile_result.pyc_files)
70    default_outputs = depset(precompile_result.keep_srcs, transitive = [direct_pyc_files])
71
72    extra_runfiles_depsets = [depset(precompile_result.keep_srcs)]
73    if ctx.attr._precompile_add_to_runfiles_flag[BuildSettingInfo].value == PrecompileAddToRunfilesFlag.ALWAYS:
74        extra_runfiles_depsets.append(direct_pyc_files)
75
76    runfiles = collect_runfiles(
77        ctx = ctx,
78        files = depset(transitive = extra_runfiles_depsets),
79    )
80
81    cc_info = semantics.get_cc_info_for_library(ctx)
82    py_info, deps_transitive_sources, builtins_py_info = create_py_info(
83        ctx,
84        direct_sources = depset(direct_sources),
85        imports = collect_imports(ctx, semantics),
86        direct_pyc_files = direct_pyc_files,
87    )
88
89    # TODO(b/253059598): Remove support for extra actions; https://github.com/bazelbuild/bazel/issues/16455
90    listeners_enabled = _py_builtins.are_action_listeners_enabled(ctx)
91    if listeners_enabled:
92        _py_builtins.add_py_extra_pseudo_action(
93            ctx = ctx,
94            dependency_transitive_python_sources = deps_transitive_sources,
95        )
96
97    return [
98        DefaultInfo(files = default_outputs, runfiles = runfiles),
99        py_info,
100        builtins_py_info,
101        create_instrumented_files_info(ctx),
102        PyCcLinkParamsProvider(cc_info = cc_info),
103        create_output_group_info(py_info.transitive_sources, extra_groups = {}),
104    ]
105
106_DEFAULT_PY_LIBRARY_DOC = """
107A library of Python code that can be depended upon.
108
109Default outputs:
110* The input Python sources
111* The precompiled artifacts from the sources.
112
113NOTE: Precompilation affects which of the default outputs are included in the
114resulting runfiles. See the precompile-related attributes and flags for
115more information.
116"""
117
118def create_py_library_rule(*, attrs = {}, **kwargs):
119    """Creates a py_library rule.
120
121    Args:
122        attrs: dict of rule attributes.
123        **kwargs: Additional kwargs to pass onto the rule() call.
124    Returns:
125        A rule object
126    """
127
128    # Within Google, the doc attribute is overridden
129    kwargs.setdefault("doc", _DEFAULT_PY_LIBRARY_DOC)
130
131    # TODO: b/253818097 - fragments=py is only necessary so that
132    # RequiredConfigFragmentsTest passes
133    fragments = kwargs.pop("fragments", None) or []
134    return rule(
135        attrs = dicts.add(LIBRARY_ATTRS, attrs),
136        toolchains = [
137            config_common.toolchain_type(TOOLCHAIN_TYPE, mandatory = False),
138            config_common.toolchain_type(EXEC_TOOLS_TOOLCHAIN_TYPE, mandatory = False),
139        ],
140        fragments = fragments + ["py"],
141        **kwargs
142    )
143