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"""Create a repository to hold a local Python toolchain definitions.""" 16 17load("//python/private:text_util.bzl", "render") 18load(":repo_utils.bzl", "REPO_DEBUG_ENV_VAR", "repo_utils") 19 20_TOOLCHAIN_TEMPLATE = """ 21# Generated by local_runtime_toolchains_repo.bzl 22 23load("@rules_python//python/private:py_toolchain_suite.bzl", "define_local_toolchain_suites") 24 25define_local_toolchain_suites( 26 name = "toolchains", 27 version_aware_repo_names = {version_aware_names}, 28 version_unaware_repo_names = {version_unaware_names}, 29) 30""" 31 32def _local_runtime_toolchains_repo(rctx): 33 logger = repo_utils.logger(rctx) 34 rctx.file("WORKSPACE", "") 35 rctx.file("MODULE.bazel", "") 36 rctx.file("REPO.bazel", "") 37 38 logger.info(lambda: _format_toolchains_for_logging(rctx)) 39 40 rctx.file("BUILD.bazel", _TOOLCHAIN_TEMPLATE.format( 41 version_aware_names = render.list(rctx.attr.runtimes), 42 version_unaware_names = render.list(rctx.attr.default_runtimes or rctx.attr.runtimes), 43 )) 44 45local_runtime_toolchains_repo = repository_rule( 46 implementation = _local_runtime_toolchains_repo, 47 doc = """ 48Create a repo of toolchains definitions for local runtimes. 49 50This is intended to be used on the toolchain implemenations generated by 51`local_runtime_repo`. 52 53NOTE: This does not call `native.register_toolchains` -- the caller is 54responsible for registering the toolchains this defines. 55""", 56 attrs = { 57 "default_runtimes": attr.string_list( 58 doc = """ 59The repo names of `local_runtime_repo` repos to define as toolchains. 60 61These will be defined as *version-unaware* toolchains. This means they will 62match any Python version. As such, they are registered after the version-aware 63toolchains defined by the `runtimes` attribute. 64 65Note that order matters: it determines the toolchain priority within the 66package. 67""", 68 ), 69 "runtimes": attr.string_list( 70 doc = """ 71The repo names of `local_runtime_repo` repos to define as toolchains. 72 73These will be defined as *version-aware* toolchains. This means they require the 74`--//python/config_settings:python_version` to be set in order to match. These 75are registered before `default_runtimes`. 76 77Note that order matters: it determines the toolchain priority within the 78package. 79""", 80 ), 81 "_rule_name": attr.string(default = "local_toolchains_repo"), 82 }, 83 environ = [REPO_DEBUG_ENV_VAR], 84) 85 86def _format_toolchains_for_logging(rctx): 87 lines = ["Local toolchain priority order:"] 88 i = 0 89 for i, name in enumerate(rctx.attr.runtimes, start = i): 90 lines.append(" {}: {} (version aware)".format(i, name)) 91 for i, name in enumerate(rctx.attr.default_runtimes, start = i): 92 lines.append(" {}: {} (version unaware)".format(i, name)) 93 return "\n".join(lines) 94