blob: bce18c3132f6b0ec6a254818bc05d64651a81459 [file] [log] [blame]
# Copyright 2022 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Implementation of py_library rule."""
load("@bazel_skylib//lib:dicts.bzl", "dicts")
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("//python/private:builders.bzl", "builders")
load("//python/private:flags.bzl", "AddSrcsToRunfilesFlag", "PrecompileFlag")
load(
"//python/private:toolchain_types.bzl",
"EXEC_TOOLS_TOOLCHAIN_TYPE",
TOOLCHAIN_TYPE = "TARGET_TOOLCHAIN_TYPE",
)
load(
":attributes.bzl",
"COMMON_ATTRS",
"PY_SRCS_ATTRS",
"PrecompileAttr",
"REQUIRED_EXEC_GROUPS",
"SRCS_VERSION_ALL_VALUES",
"create_srcs_attr",
"create_srcs_version_attr",
)
load(
":common.bzl",
"check_native_allowed",
"collect_imports",
"collect_runfiles",
"create_instrumented_files_info",
"create_output_group_info",
"create_py_info",
"filter_to_py_srcs",
"union_attrs",
)
load(":providers.bzl", "PyCcLinkParamsProvider")
load(":py_internal.bzl", "py_internal")
_py_builtins = py_internal
LIBRARY_ATTRS = union_attrs(
COMMON_ATTRS,
PY_SRCS_ATTRS,
create_srcs_version_attr(values = SRCS_VERSION_ALL_VALUES),
create_srcs_attr(mandatory = False),
{
"_add_srcs_to_runfiles_flag": attr.label(
default = "//python/config_settings:add_srcs_to_runfiles",
),
},
)
def py_library_impl(ctx, *, semantics):
"""Abstract implementation of py_library rule.
Args:
ctx: The rule ctx
semantics: A `LibrarySemantics` struct; see `create_library_semantics_struct`
Returns:
A list of modern providers to propagate.
"""
check_native_allowed(ctx)
direct_sources = filter_to_py_srcs(ctx.files.srcs)
precompile_result = semantics.maybe_precompile(ctx, direct_sources)
required_py_files = precompile_result.keep_srcs
required_pyc_files = []
implicit_pyc_files = []
implicit_pyc_source_files = direct_sources
precompile_attr = ctx.attr.precompile
precompile_flag = ctx.attr._precompile_flag[BuildSettingInfo].value
if (precompile_attr == PrecompileAttr.ENABLED or
precompile_flag == PrecompileFlag.FORCE_ENABLED):
required_pyc_files.extend(precompile_result.pyc_files)
else:
implicit_pyc_files.extend(precompile_result.pyc_files)
default_outputs = builders.DepsetBuilder()
default_outputs.add(precompile_result.keep_srcs)
default_outputs.add(required_pyc_files)
default_outputs = default_outputs.build()
runfiles = builders.RunfilesBuilder()
if AddSrcsToRunfilesFlag.is_enabled(ctx):
runfiles.add(required_py_files)
runfiles.add(collect_runfiles(ctx))
runfiles = runfiles.build(ctx)
cc_info = semantics.get_cc_info_for_library(ctx)
py_info, deps_transitive_sources, builtins_py_info = create_py_info(
ctx,
required_py_files = required_py_files,
required_pyc_files = required_pyc_files,
implicit_pyc_files = implicit_pyc_files,
implicit_pyc_source_files = implicit_pyc_source_files,
imports = collect_imports(ctx, semantics),
)
# TODO(b/253059598): Remove support for extra actions; https://github.com/bazelbuild/bazel/issues/16455
listeners_enabled = _py_builtins.are_action_listeners_enabled(ctx)
if listeners_enabled:
_py_builtins.add_py_extra_pseudo_action(
ctx = ctx,
dependency_transitive_python_sources = deps_transitive_sources,
)
providers = [
DefaultInfo(files = default_outputs, runfiles = runfiles),
py_info,
create_instrumented_files_info(ctx),
PyCcLinkParamsProvider(cc_info = cc_info),
create_output_group_info(py_info.transitive_sources, extra_groups = {}),
]
if builtins_py_info:
providers.append(builtins_py_info)
return providers
_DEFAULT_PY_LIBRARY_DOC = """
A library of Python code that can be depended upon.
Default outputs:
* The input Python sources
* The precompiled artifacts from the sources.
NOTE: Precompilation affects which of the default outputs are included in the
resulting runfiles. See the precompile-related attributes and flags for
more information.
:::{versionchanged} 0.37.0
Source files are no longer added to the runfiles directly.
:::
"""
def create_py_library_rule(*, attrs = {}, **kwargs):
"""Creates a py_library rule.
Args:
attrs: dict of rule attributes.
**kwargs: Additional kwargs to pass onto the rule() call.
Returns:
A rule object
"""
# Within Google, the doc attribute is overridden
kwargs.setdefault("doc", _DEFAULT_PY_LIBRARY_DOC)
# TODO: b/253818097 - fragments=py is only necessary so that
# RequiredConfigFragmentsTest passes
fragments = kwargs.pop("fragments", None) or []
kwargs["exec_groups"] = REQUIRED_EXEC_GROUPS | (kwargs.get("exec_groups") or {})
return rule(
attrs = dicts.add(LIBRARY_ATTRS, attrs),
toolchains = [
config_common.toolchain_type(TOOLCHAIN_TYPE, mandatory = False),
config_common.toolchain_type(EXEC_TOOLS_TOOLCHAIN_TYPE, mandatory = False),
],
fragments = fragments + ["py"],
**kwargs
)