| # Copyright 2024 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. | |
| """Setup code called by the code generated by `local_runtime_repo`.""" | |
| load("@bazel_skylib//lib:selects.bzl", "selects") | |
| load("@rules_cc//cc:defs.bzl", "cc_library") | |
| load("@rules_python//python:py_runtime.bzl", "py_runtime") | |
| load("@rules_python//python:py_runtime_pair.bzl", "py_runtime_pair") | |
| load("@rules_python//python/cc:py_cc_toolchain.bzl", "py_cc_toolchain") | |
| load("@rules_python//python/private:py_exec_tools_toolchain.bzl", "py_exec_tools_toolchain") | |
| _PYTHON_VERSION_FLAG = Label("@rules_python//python/config_settings:python_version") | |
| def define_local_runtime_toolchain_impl( | |
| name, | |
| lib_ext, | |
| major, | |
| minor, | |
| micro, | |
| interpreter_path, | |
| implementation_name, | |
| os): | |
| """Defines a toolchain implementation for a local Python runtime. | |
| Generates public targets: | |
| * `python_runtimes`: The target toolchain type implementation | |
| * `py_exec_tools_toolchain`: The exec tools toolchain type implementation | |
| * `py_cc_toolchain`: The py cc toolchain type implementation | |
| * `os`: A constraint (or alias to one) for the `target_compatible_with` this | |
| toolchain is compatible with. | |
| * `is_matching_python_version`: A `config_setting` for `target_settings` | |
| this toolchain is compatible with. | |
| Args: | |
| name: `str` Only present to satisfy tooling | |
| lib_ext: `str` The file extension for the `libpython` shared libraries | |
| major: `str` The major Python version, e.g. `3` of `3.9.1`. | |
| minor: `str` The minor Python version, e.g. `9` of `3.9.1`. | |
| micro: `str` The micro Python version, e.g. "1" of `3.9.1`. | |
| interpreter_path: `str` Absolute path to the interpreter. | |
| implementation_name: `str` The implementation name, as returned by | |
| `sys.implementation.name`. | |
| os: `str` A label to the OS constraint (e.g. `@platforms//os:linux`) for | |
| this runtime. | |
| """ | |
| major_minor = "{}.{}".format(major, minor) | |
| major_minor_micro = "{}.{}".format(major_minor, micro) | |
| cc_library( | |
| name = "_python_headers", | |
| # NOTE: Keep in sync with watch_tree() called in local_runtime_repo | |
| srcs = native.glob(["include/**/*.h"]), | |
| includes = ["include"], | |
| ) | |
| cc_library( | |
| name = "_libpython", | |
| # Don't use a recursive glob because the lib/ directory usually contains | |
| # a subdirectory of the stdlib -- lots of unrelated files | |
| srcs = native.glob([ | |
| "lib/*{}".format(lib_ext), # Match libpython*.so | |
| "lib/*{}*".format(lib_ext), # Also match libpython*.so.1.0 | |
| ]), | |
| hdrs = [":_python_headers"], | |
| ) | |
| py_runtime( | |
| name = "_py3_runtime", | |
| interpreter_path = interpreter_path, | |
| python_version = "PY3", | |
| interpreter_version_info = { | |
| "major": major, | |
| "micro": micro, | |
| "minor": minor, | |
| }, | |
| implementation_name = implementation_name, | |
| ) | |
| py_runtime_pair( | |
| name = "python_runtimes", | |
| py2_runtime = None, | |
| py3_runtime = ":_py3_runtime", | |
| visibility = ["//visibility:public"], | |
| ) | |
| py_exec_tools_toolchain( | |
| name = "py_exec_tools_toolchain", | |
| visibility = ["//visibility:public"], | |
| precompiler = "@rules_python//tools/precompiler:precompiler", | |
| ) | |
| py_cc_toolchain( | |
| name = "py_cc_toolchain", | |
| headers = ":_python_headers", | |
| libs = ":_libpython", | |
| python_version = major_minor_micro, | |
| visibility = ["//visibility:public"], | |
| ) | |
| native.alias( | |
| name = "os", | |
| # Call Label() to force the string to evaluate in the context of | |
| # rules_python, not the calling BUILD-file code. This is because | |
| # the value is an `@platforms//foo` string, which @rules_python has | |
| # visibility to, but the calling repo may not. | |
| actual = Label(os), | |
| visibility = ["//visibility:public"], | |
| ) | |
| native.config_setting( | |
| name = "_is_major_minor", | |
| flag_values = { | |
| _PYTHON_VERSION_FLAG: major_minor, | |
| }, | |
| ) | |
| native.config_setting( | |
| name = "_is_major_minor_micro", | |
| flag_values = { | |
| _PYTHON_VERSION_FLAG: major_minor_micro, | |
| }, | |
| ) | |
| selects.config_setting_group( | |
| name = "is_matching_python_version", | |
| match_any = [ | |
| ":_is_major_minor", | |
| ":_is_major_minor_micro", | |
| ], | |
| visibility = ["//visibility:public"], | |
| ) |