1# Copyright 2024 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 15"""Setup code called by the code generated by `local_runtime_repo`.""" 16 17load("@bazel_skylib//lib:selects.bzl", "selects") 18load("@rules_cc//cc:defs.bzl", "cc_library") 19load("@rules_python//python:py_runtime.bzl", "py_runtime") 20load("@rules_python//python:py_runtime_pair.bzl", "py_runtime_pair") 21load("@rules_python//python/cc:py_cc_toolchain.bzl", "py_cc_toolchain") 22load("@rules_python//python/private:py_exec_tools_toolchain.bzl", "py_exec_tools_toolchain") 23 24_PYTHON_VERSION_FLAG = Label("@rules_python//python/config_settings:python_version") 25 26def define_local_runtime_toolchain_impl( 27 name, 28 lib_ext, 29 major, 30 minor, 31 micro, 32 interpreter_path, 33 implementation_name, 34 os): 35 """Defines a toolchain implementation for a local Python runtime. 36 37 Generates public targets: 38 * `python_runtimes`: The target toolchain type implementation 39 * `py_exec_tools_toolchain`: The exec tools toolchain type implementation 40 * `py_cc_toolchain`: The py cc toolchain type implementation 41 * `os`: A constraint (or alias to one) for the `target_compatible_with` this 42 toolchain is compatible with. 43 * `is_matching_python_version`: A `config_setting` for `target_settings` 44 this toolchain is compatible with. 45 46 Args: 47 name: `str` Only present to satisfy tooling 48 lib_ext: `str` The file extension for the `libpython` shared libraries 49 major: `str` The major Python version, e.g. `3` of `3.9.1`. 50 minor: `str` The minor Python version, e.g. `9` of `3.9.1`. 51 micro: `str` The micro Python version, e.g. "1" of `3.9.1`. 52 interpreter_path: `str` Absolute path to the interpreter. 53 implementation_name: `str` The implementation name, as returned by 54 `sys.implementation.name`. 55 os: `str` A label to the OS constraint (e.g. `@platforms//os:linux`) for 56 this runtime. 57 """ 58 major_minor = "{}.{}".format(major, minor) 59 major_minor_micro = "{}.{}".format(major_minor, micro) 60 61 cc_library( 62 name = "_python_headers", 63 # NOTE: Keep in sync with watch_tree() called in local_runtime_repo 64 srcs = native.glob(["include/**/*.h"]), 65 includes = ["include"], 66 ) 67 68 cc_library( 69 name = "_libpython", 70 # Don't use a recursive glob because the lib/ directory usually contains 71 # a subdirectory of the stdlib -- lots of unrelated files 72 srcs = native.glob([ 73 "lib/*{}".format(lib_ext), # Match libpython*.so 74 "lib/*{}*".format(lib_ext), # Also match libpython*.so.1.0 75 ]), 76 hdrs = [":_python_headers"], 77 ) 78 79 py_runtime( 80 name = "_py3_runtime", 81 interpreter_path = interpreter_path, 82 python_version = "PY3", 83 interpreter_version_info = { 84 "major": major, 85 "micro": micro, 86 "minor": minor, 87 }, 88 implementation_name = implementation_name, 89 ) 90 91 py_runtime_pair( 92 name = "python_runtimes", 93 py2_runtime = None, 94 py3_runtime = ":_py3_runtime", 95 visibility = ["//visibility:public"], 96 ) 97 98 py_exec_tools_toolchain( 99 name = "py_exec_tools_toolchain", 100 visibility = ["//visibility:public"], 101 precompiler = "@rules_python//tools/precompiler:precompiler", 102 ) 103 104 py_cc_toolchain( 105 name = "py_cc_toolchain", 106 headers = ":_python_headers", 107 libs = ":_libpython", 108 python_version = major_minor_micro, 109 visibility = ["//visibility:public"], 110 ) 111 112 native.alias( 113 name = "os", 114 # Call Label() to force the string to evaluate in the context of 115 # rules_python, not the calling BUILD-file code. This is because 116 # the value is an `@platforms//foo` string, which @rules_python has 117 # visibility to, but the calling repo may not. 118 actual = Label(os), 119 visibility = ["//visibility:public"], 120 ) 121 122 native.config_setting( 123 name = "_is_major_minor", 124 flag_values = { 125 _PYTHON_VERSION_FLAG: major_minor, 126 }, 127 ) 128 native.config_setting( 129 name = "_is_major_minor_micro", 130 flag_values = { 131 _PYTHON_VERSION_FLAG: major_minor_micro, 132 }, 133 ) 134 selects.config_setting_group( 135 name = "is_matching_python_version", 136 match_any = [ 137 ":_is_major_minor", 138 ":_is_major_minor_micro", 139 ], 140 visibility = ["//visibility:public"], 141 ) 142