| # 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 |
| ) |