Ignas Anikevicius | c9c2768 | 2024-03-18 16:16:26 +0900 | [diff] [blame] | 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 module is used to construct the config settings in the BUILD file in this same package. |
| 16 | """ |
| 17 | |
| 18 | load("@bazel_skylib//lib:selects.bzl", "selects") |
Richard Levasseur | 54c9fab | 2024-08-31 07:19:47 -0700 | [diff] [blame] | 19 | load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") |
Ignas Anikevicius | 654b4d5 | 2024-09-17 13:12:48 +0900 | [diff] [blame] | 20 | load(":semver.bzl", "semver") |
Ignas Anikevicius | c9c2768 | 2024-03-18 16:16:26 +0900 | [diff] [blame] | 21 | |
Ignas Anikevicius | 654b4d5 | 2024-09-17 13:12:48 +0900 | [diff] [blame] | 22 | _PYTHON_VERSION_FLAG = Label("//python/config_settings:python_version") |
Ignas Anikevicius | 30fc3f9 | 2024-10-07 12:22:19 +0900 | [diff] [blame] | 23 | _PYTHON_VERSION_MAJOR_MINOR_FLAG = Label("//python/config_settings:python_version_major_minor") |
Ignas Anikevicius | c9c2768 | 2024-03-18 16:16:26 +0900 | [diff] [blame] | 24 | |
Ignas Anikevicius | 33fa845 | 2024-10-07 11:07:27 +0900 | [diff] [blame] | 25 | def construct_config_settings(*, name, default_version, versions, minor_mapping): # buildifier: disable=function-docstring |
Ignas Anikevicius | c9c2768 | 2024-03-18 16:16:26 +0900 | [diff] [blame] | 26 | """Create a 'python_version' config flag and construct all config settings used in rules_python. |
| 27 | |
| 28 | This mainly includes the targets that are used in the toolchain and pip hub |
| 29 | repositories that only match on the 'python_version' flag values. |
| 30 | |
| 31 | Args: |
Ignas Anikevicius | 654b4d5 | 2024-09-17 13:12:48 +0900 | [diff] [blame] | 32 | name: {type}`str` A dummy name value that is no-op for now. |
Ignas Anikevicius | 33fa845 | 2024-10-07 11:07:27 +0900 | [diff] [blame] | 33 | default_version: {type}`str` the default value for the `python_version` flag. |
Ignas Anikevicius | 654b4d5 | 2024-09-17 13:12:48 +0900 | [diff] [blame] | 34 | versions: {type}`list[str]` A list of versions to build constraint settings for. |
| 35 | minor_mapping: {type}`dict[str, str]` A mapping from `X.Y` to `X.Y.Z` python versions. |
Ignas Anikevicius | c9c2768 | 2024-03-18 16:16:26 +0900 | [diff] [blame] | 36 | """ |
Ignas Anikevicius | 654b4d5 | 2024-09-17 13:12:48 +0900 | [diff] [blame] | 37 | _ = name # @unused |
Richard Levasseur | 54c9fab | 2024-08-31 07:19:47 -0700 | [diff] [blame] | 38 | _python_version_flag( |
Ignas Anikevicius | 654b4d5 | 2024-09-17 13:12:48 +0900 | [diff] [blame] | 39 | name = _PYTHON_VERSION_FLAG.name, |
Ignas Anikevicius | 33fa845 | 2024-10-07 11:07:27 +0900 | [diff] [blame] | 40 | build_setting_default = default_version, |
Ignas Anikevicius | 654b4d5 | 2024-09-17 13:12:48 +0900 | [diff] [blame] | 41 | visibility = ["//visibility:public"], |
| 42 | ) |
| 43 | |
| 44 | _python_version_major_minor_flag( |
| 45 | name = _PYTHON_VERSION_MAJOR_MINOR_FLAG.name, |
| 46 | build_setting_default = "", |
Ignas Anikevicius | c9c2768 | 2024-03-18 16:16:26 +0900 | [diff] [blame] | 47 | visibility = ["//visibility:public"], |
| 48 | ) |
| 49 | |
Ignas Anikevicius | fce7354 | 2024-06-17 22:05:28 +0900 | [diff] [blame] | 50 | native.config_setting( |
| 51 | name = "is_python_version_unset", |
Ignas Anikevicius | 654b4d5 | 2024-09-17 13:12:48 +0900 | [diff] [blame] | 52 | flag_values = {_PYTHON_VERSION_FLAG: ""}, |
Ignas Anikevicius | fce7354 | 2024-06-17 22:05:28 +0900 | [diff] [blame] | 53 | visibility = ["//visibility:public"], |
| 54 | ) |
| 55 | |
Ignas Anikevicius | 654b4d5 | 2024-09-17 13:12:48 +0900 | [diff] [blame] | 56 | _reverse_minor_mapping = {full: minor for minor, full in minor_mapping.items()} |
| 57 | for version in versions: |
| 58 | minor_version = _reverse_minor_mapping.get(version) |
| 59 | if not minor_version: |
| 60 | native.config_setting( |
| 61 | name = "is_python_{}".format(version), |
| 62 | flag_values = {":python_version": version}, |
| 63 | visibility = ["//visibility:public"], |
| 64 | ) |
| 65 | continue |
| 66 | |
| 67 | # Also need to match the minor version when using |
| 68 | name = "is_python_{}".format(version) |
| 69 | native.config_setting( |
| 70 | name = "_" + name, |
| 71 | flag_values = {":python_version": version}, |
| 72 | visibility = ["//visibility:public"], |
| 73 | ) |
| 74 | |
| 75 | # An alias pointing to an underscore-prefixed config_setting_group |
| 76 | # is used because config_setting_group creates |
| 77 | # `is_{version}_N` targets, which are easily confused with the |
| 78 | # `is_{minor}.{micro}` (dot) targets. |
| 79 | selects.config_setting_group( |
| 80 | name = "_{}_group".format(name), |
| 81 | match_any = [ |
| 82 | ":_is_python_{}".format(version), |
| 83 | ":is_python_{}".format(minor_version), |
| 84 | ], |
| 85 | visibility = ["//visibility:private"], |
| 86 | ) |
| 87 | native.alias( |
| 88 | name = name, |
| 89 | actual = "_{}_group".format(name), |
| 90 | visibility = ["//visibility:public"], |
| 91 | ) |
| 92 | |
| 93 | # This matches the raw flag value, e.g. --//python/config_settings:python_version=3.8 |
| 94 | # It's private because matching the concept of e.g. "3.8" value is done |
| 95 | # using the `is_python_X.Y` config setting group, which is aware of the |
| 96 | # minor versions that could match instead. |
| 97 | for minor in minor_mapping.keys(): |
| 98 | native.config_setting( |
| 99 | name = "is_python_{}".format(minor), |
| 100 | flag_values = {_PYTHON_VERSION_MAJOR_MINOR_FLAG: minor}, |
Ignas Anikevicius | c9c2768 | 2024-03-18 16:16:26 +0900 | [diff] [blame] | 101 | visibility = ["//visibility:public"], |
| 102 | ) |
Richard Levasseur | 54c9fab | 2024-08-31 07:19:47 -0700 | [diff] [blame] | 103 | |
| 104 | def _python_version_flag_impl(ctx): |
| 105 | value = ctx.build_setting_value |
Richard Levasseur | 54c9fab | 2024-08-31 07:19:47 -0700 | [diff] [blame] | 106 | return [ |
| 107 | # BuildSettingInfo is the original provider returned, so continue to |
| 108 | # return it for compatibility |
| 109 | BuildSettingInfo(value = value), |
| 110 | # FeatureFlagInfo is returned so that config_setting respects the value |
| 111 | # as returned by this rule instead of as originally seen on the command |
| 112 | # line. |
| 113 | # It is also for Google compatibility, which expects the FeatureFlagInfo |
| 114 | # provider. |
| 115 | config_common.FeatureFlagInfo(value = value), |
| 116 | ] |
| 117 | |
| 118 | _python_version_flag = rule( |
| 119 | implementation = _python_version_flag_impl, |
| 120 | build_setting = config.string(flag = True), |
Ignas Anikevicius | 654b4d5 | 2024-09-17 13:12:48 +0900 | [diff] [blame] | 121 | attrs = {}, |
| 122 | ) |
| 123 | |
| 124 | def _python_version_major_minor_flag_impl(ctx): |
| 125 | input = ctx.attr._python_version_flag[config_common.FeatureFlagInfo].value |
| 126 | if input: |
| 127 | version = semver(input) |
| 128 | value = "{}.{}".format(version.major, version.minor) |
| 129 | else: |
| 130 | value = "" |
| 131 | |
| 132 | return [config_common.FeatureFlagInfo(value = value)] |
| 133 | |
| 134 | _python_version_major_minor_flag = rule( |
| 135 | implementation = _python_version_major_minor_flag_impl, |
| 136 | build_setting = config.string(flag = False), |
Richard Levasseur | 54c9fab | 2024-08-31 07:19:47 -0700 | [diff] [blame] | 137 | attrs = { |
Ignas Anikevicius | 654b4d5 | 2024-09-17 13:12:48 +0900 | [diff] [blame] | 138 | "_python_version_flag": attr.label( |
| 139 | default = _PYTHON_VERSION_FLAG, |
Richard Levasseur | 54c9fab | 2024-08-31 07:19:47 -0700 | [diff] [blame] | 140 | ), |
| 141 | }, |
| 142 | ) |