# 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"], )