blob: f1e142cc36d953dd0c366f0be18936a44c5f485b [file] [log] [blame]
# Copyright 2023 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.
"""This module is used to construct the config settings in the BUILD file in this same package.
"""
load("@bazel_skylib//lib:selects.bzl", "selects")
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
def construct_config_settings(name, python_versions):
"""Constructs a set of configs for all Python versions.
Args:
name: str, unused; only specified to satisfy buildifier lint checks
and allow programatic modification of the target.
python_versions: list of all (x.y.z) Python versions supported by rules_python.
"""
# Maps e.g. "3.8" -> ["3.8.1", "3.8.2", etc]
minor_to_micro_versions = {}
allowed_flag_values = []
for micro_version in python_versions:
minor, _, _ = micro_version.rpartition(".")
minor_to_micro_versions.setdefault(minor, []).append(micro_version)
allowed_flag_values.append(micro_version)
string_flag(
name = "python_version",
# TODO: The default here should somehow match the MODULE config. Until
# then, use the empty string to indicate an unknown version. This
# also prevents version-unaware targets from inadvertently matching
# a select condition when they shouldn't.
build_setting_default = "",
values = [""] + sorted(allowed_flag_values),
visibility = ["//visibility:public"],
)
for minor_version, micro_versions in minor_to_micro_versions.items():
# This matches the raw flag value, e.g. --//python/config_settings:python_version=3.8
# It's private because matching the concept of e.g. "3.8" value is done
# using the `is_python_X.Y` config setting group, which is aware of the
# minor versions that could match instead.
equals_minor_version_name = "_python_version_flag_equals_" + minor_version
native.config_setting(
name = equals_minor_version_name,
flag_values = {":python_version": minor_version},
)
matches_minor_version_names = [equals_minor_version_name]
for micro_version in micro_versions:
is_micro_version_name = "is_python_" + micro_version
native.config_setting(
name = is_micro_version_name,
flag_values = {":python_version": micro_version},
visibility = ["//visibility:public"],
)
matches_minor_version_names.append(is_micro_version_name)
# This is prefixed with an underscore to prevent confusion due to how
# config_setting_group is implemented and how our micro-version targets
# are named. config_setting_group will generate targets like
# "is_python_3.10_1" (where the `_N` suffix is len(match_any).
# Meanwhile, the micro-version tarets are named "is_python_3.10.1" --
# just a single dot vs underscore character difference.
selects.config_setting_group(
name = "_is_python_" + minor_version,
match_any = matches_minor_version_names,
)
native.alias(
name = "is_python_" + minor_version,
actual = "_is_python_" + minor_version,
visibility = ["//visibility:public"],
)