• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"""This file contains repository rules and macros to support toolchain registration.
16"""
17
18# NOTE @aignas 2024-10-07:  we are not importing this from `@pythons_hub` because of this
19# leading to a backwards incompatible change - the `//python:repositories.bzl` is loading
20# from this file and it will cause a circular import loop and an error. If the users in
21# WORKSPACE world want to override the `minor_mapping`, they will have to pass an argument.
22load("//python:versions.bzl", "MINOR_MAPPING")
23load(":python_register_toolchains.bzl", "python_register_toolchains")
24load(":toolchains_repo.bzl", "multi_toolchain_aliases")
25
26def python_register_multi_toolchains(
27        name,
28        python_versions,
29        default_version = None,
30        minor_mapping = None,
31        **kwargs):
32    """Convenience macro for registering multiple Python toolchains.
33
34    Args:
35        name: {type}`str` base name for each name in {obj}`python_register_toolchains` call.
36        python_versions: {type}`list[str]` the Python versions.
37        default_version: {type}`str` the default Python version. If not set,
38            the first version in python_versions is used.
39        minor_mapping: {type}`dict[str, str]` mapping between `X.Y` to `X.Y.Z`
40            format. Defaults to the value in `//python:versions.bzl`.
41        **kwargs: passed to each {obj}`python_register_toolchains` call.
42    """
43    if len(python_versions) == 0:
44        fail("python_versions must not be empty")
45
46    minor_mapping = minor_mapping or MINOR_MAPPING
47
48    if not default_version:
49        default_version = python_versions.pop(0)
50    for python_version in python_versions:
51        if python_version == default_version:
52            # We register the default version lastly so that it's not picked first when --platforms
53            # is set with a constraint during toolchain resolution. This is due to the fact that
54            # Bazel will match the unconstrained toolchain if we register it before the constrained
55            # ones.
56            continue
57        python_register_toolchains(
58            name = name + "_" + python_version.replace(".", "_"),
59            python_version = python_version,
60            set_python_version_constraint = True,
61            minor_mapping = minor_mapping,
62            **kwargs
63        )
64    python_register_toolchains(
65        name = name + "_" + default_version.replace(".", "_"),
66        python_version = default_version,
67        set_python_version_constraint = False,
68        minor_mapping = minor_mapping,
69        **kwargs
70    )
71
72    multi_toolchain_aliases(
73        name = name,
74        python_versions = {
75            python_version: name + "_" + python_version.replace(".", "_")
76            for python_version in (python_versions + [default_version])
77        },
78        minor_mapping = minor_mapping,
79    )
80