1*60517a1eSAndroid Build Coastguard Worker# Copyright 2023 The Bazel Authors. All rights reserved 2*60517a1eSAndroid Build Coastguard Worker# 3*60517a1eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*60517a1eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*60517a1eSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*60517a1eSAndroid Build Coastguard Worker# 7*60517a1eSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*60517a1eSAndroid Build Coastguard Worker# 9*60517a1eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*60517a1eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*60517a1eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*60517a1eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*60517a1eSAndroid Build Coastguard Worker# limitations under the License. 14*60517a1eSAndroid Build Coastguard Worker 15*60517a1eSAndroid Build Coastguard Worker"Repo rule used by bzlmod extension to create a repo that has a map of Python interpreters and their labels" 16*60517a1eSAndroid Build Coastguard Worker 17*60517a1eSAndroid Build Coastguard Workerload( 18*60517a1eSAndroid Build Coastguard Worker "//python/private:toolchains_repo.bzl", 19*60517a1eSAndroid Build Coastguard Worker "python_toolchain_build_file_content", 20*60517a1eSAndroid Build Coastguard Worker) 21*60517a1eSAndroid Build Coastguard Worker 22*60517a1eSAndroid Build Coastguard Workerdef _have_same_length(*lists): 23*60517a1eSAndroid Build Coastguard Worker if not lists: 24*60517a1eSAndroid Build Coastguard Worker fail("expected at least one list") 25*60517a1eSAndroid Build Coastguard Worker return len({len(length): None for length in lists}) == 1 26*60517a1eSAndroid Build Coastguard Worker 27*60517a1eSAndroid Build Coastguard Worker_HUB_BUILD_FILE_TEMPLATE = """\ 28*60517a1eSAndroid Build Coastguard Workerload("@bazel_skylib//:bzl_library.bzl", "bzl_library") 29*60517a1eSAndroid Build Coastguard Workerload("@@{rules_python}//python/private:py_toolchain_suite.bzl", "py_toolchain_suite") 30*60517a1eSAndroid Build Coastguard Worker 31*60517a1eSAndroid Build Coastguard Workerbzl_library( 32*60517a1eSAndroid Build Coastguard Worker name = "interpreters_bzl", 33*60517a1eSAndroid Build Coastguard Worker srcs = ["interpreters.bzl"], 34*60517a1eSAndroid Build Coastguard Worker visibility = ["@rules_python//:__subpackages__"], 35*60517a1eSAndroid Build Coastguard Worker) 36*60517a1eSAndroid Build Coastguard Worker 37*60517a1eSAndroid Build Coastguard Worker{toolchains} 38*60517a1eSAndroid Build Coastguard Worker""" 39*60517a1eSAndroid Build Coastguard Worker 40*60517a1eSAndroid Build Coastguard Workerdef _hub_build_file_content( 41*60517a1eSAndroid Build Coastguard Worker prefixes, 42*60517a1eSAndroid Build Coastguard Worker python_versions, 43*60517a1eSAndroid Build Coastguard Worker set_python_version_constraints, 44*60517a1eSAndroid Build Coastguard Worker user_repository_names, 45*60517a1eSAndroid Build Coastguard Worker workspace_location): 46*60517a1eSAndroid Build Coastguard Worker """This macro iterates over each of the lists and returns the toolchain content. 47*60517a1eSAndroid Build Coastguard Worker 48*60517a1eSAndroid Build Coastguard Worker python_toolchain_build_file_content is called to generate each of the toolchain 49*60517a1eSAndroid Build Coastguard Worker definitions. 50*60517a1eSAndroid Build Coastguard Worker """ 51*60517a1eSAndroid Build Coastguard Worker 52*60517a1eSAndroid Build Coastguard Worker if not _have_same_length(python_versions, set_python_version_constraints, user_repository_names): 53*60517a1eSAndroid Build Coastguard Worker fail("all lists must have the same length") 54*60517a1eSAndroid Build Coastguard Worker 55*60517a1eSAndroid Build Coastguard Worker # Iterate over the length of python_versions and call 56*60517a1eSAndroid Build Coastguard Worker # build the toolchain content by calling python_toolchain_build_file_content 57*60517a1eSAndroid Build Coastguard Worker toolchains = "\n".join( 58*60517a1eSAndroid Build Coastguard Worker [ 59*60517a1eSAndroid Build Coastguard Worker python_toolchain_build_file_content( 60*60517a1eSAndroid Build Coastguard Worker prefix = prefixes[i], 61*60517a1eSAndroid Build Coastguard Worker python_version = python_versions[i], 62*60517a1eSAndroid Build Coastguard Worker set_python_version_constraint = set_python_version_constraints[i], 63*60517a1eSAndroid Build Coastguard Worker user_repository_name = user_repository_names[i], 64*60517a1eSAndroid Build Coastguard Worker ) 65*60517a1eSAndroid Build Coastguard Worker for i in range(len(python_versions)) 66*60517a1eSAndroid Build Coastguard Worker ], 67*60517a1eSAndroid Build Coastguard Worker ) 68*60517a1eSAndroid Build Coastguard Worker 69*60517a1eSAndroid Build Coastguard Worker return _HUB_BUILD_FILE_TEMPLATE.format( 70*60517a1eSAndroid Build Coastguard Worker toolchains = toolchains, 71*60517a1eSAndroid Build Coastguard Worker rules_python = workspace_location.workspace_name, 72*60517a1eSAndroid Build Coastguard Worker ) 73*60517a1eSAndroid Build Coastguard Worker 74*60517a1eSAndroid Build Coastguard Worker_interpreters_bzl_template = """ 75*60517a1eSAndroid Build Coastguard WorkerINTERPRETER_LABELS = {{ 76*60517a1eSAndroid Build Coastguard Worker{interpreter_labels} 77*60517a1eSAndroid Build Coastguard Worker}} 78*60517a1eSAndroid Build Coastguard WorkerDEFAULT_PYTHON_VERSION = "{default_python_version}" 79*60517a1eSAndroid Build Coastguard Worker""" 80*60517a1eSAndroid Build Coastguard Worker 81*60517a1eSAndroid Build Coastguard Worker_line_for_hub_template = """\ 82*60517a1eSAndroid Build Coastguard Worker "{name}_host": Label("@{name}_host//:python"), 83*60517a1eSAndroid Build Coastguard Worker""" 84*60517a1eSAndroid Build Coastguard Worker 85*60517a1eSAndroid Build Coastguard Workerdef _hub_repo_impl(rctx): 86*60517a1eSAndroid Build Coastguard Worker # Create the various toolchain definitions and 87*60517a1eSAndroid Build Coastguard Worker # write them to the BUILD file. 88*60517a1eSAndroid Build Coastguard Worker rctx.file( 89*60517a1eSAndroid Build Coastguard Worker "BUILD.bazel", 90*60517a1eSAndroid Build Coastguard Worker _hub_build_file_content( 91*60517a1eSAndroid Build Coastguard Worker rctx.attr.toolchain_prefixes, 92*60517a1eSAndroid Build Coastguard Worker rctx.attr.toolchain_python_versions, 93*60517a1eSAndroid Build Coastguard Worker rctx.attr.toolchain_set_python_version_constraints, 94*60517a1eSAndroid Build Coastguard Worker rctx.attr.toolchain_user_repository_names, 95*60517a1eSAndroid Build Coastguard Worker rctx.attr._rules_python_workspace, 96*60517a1eSAndroid Build Coastguard Worker ), 97*60517a1eSAndroid Build Coastguard Worker executable = False, 98*60517a1eSAndroid Build Coastguard Worker ) 99*60517a1eSAndroid Build Coastguard Worker 100*60517a1eSAndroid Build Coastguard Worker # Create a dict that is later used to create 101*60517a1eSAndroid Build Coastguard Worker # a symlink to a interpreter. 102*60517a1eSAndroid Build Coastguard Worker interpreter_labels = "".join([ 103*60517a1eSAndroid Build Coastguard Worker _line_for_hub_template.format(name = name) 104*60517a1eSAndroid Build Coastguard Worker for name in rctx.attr.toolchain_user_repository_names 105*60517a1eSAndroid Build Coastguard Worker ]) 106*60517a1eSAndroid Build Coastguard Worker 107*60517a1eSAndroid Build Coastguard Worker rctx.file( 108*60517a1eSAndroid Build Coastguard Worker "interpreters.bzl", 109*60517a1eSAndroid Build Coastguard Worker _interpreters_bzl_template.format( 110*60517a1eSAndroid Build Coastguard Worker interpreter_labels = interpreter_labels, 111*60517a1eSAndroid Build Coastguard Worker default_python_version = rctx.attr.default_python_version, 112*60517a1eSAndroid Build Coastguard Worker ), 113*60517a1eSAndroid Build Coastguard Worker executable = False, 114*60517a1eSAndroid Build Coastguard Worker ) 115*60517a1eSAndroid Build Coastguard Worker 116*60517a1eSAndroid Build Coastguard Workerhub_repo = repository_rule( 117*60517a1eSAndroid Build Coastguard Worker doc = """\ 118*60517a1eSAndroid Build Coastguard WorkerThis private rule create a repo with a BUILD file that contains a map of interpreter names 119*60517a1eSAndroid Build Coastguard Workerand the labels to said interpreters. This map is used to by the interpreter hub extension. 120*60517a1eSAndroid Build Coastguard WorkerThis rule also writes out the various toolchains for the different Python versions. 121*60517a1eSAndroid Build Coastguard Worker""", 122*60517a1eSAndroid Build Coastguard Worker implementation = _hub_repo_impl, 123*60517a1eSAndroid Build Coastguard Worker attrs = { 124*60517a1eSAndroid Build Coastguard Worker "default_python_version": attr.string( 125*60517a1eSAndroid Build Coastguard Worker doc = "Default Python version for the build in `X.Y` or `X.Y.Z` format.", 126*60517a1eSAndroid Build Coastguard Worker mandatory = True, 127*60517a1eSAndroid Build Coastguard Worker ), 128*60517a1eSAndroid Build Coastguard Worker "toolchain_prefixes": attr.string_list( 129*60517a1eSAndroid Build Coastguard Worker doc = "List prefixed for the toolchains", 130*60517a1eSAndroid Build Coastguard Worker mandatory = True, 131*60517a1eSAndroid Build Coastguard Worker ), 132*60517a1eSAndroid Build Coastguard Worker "toolchain_python_versions": attr.string_list( 133*60517a1eSAndroid Build Coastguard Worker doc = "List of Python versions for the toolchains. In `X.Y.Z` format.", 134*60517a1eSAndroid Build Coastguard Worker mandatory = True, 135*60517a1eSAndroid Build Coastguard Worker ), 136*60517a1eSAndroid Build Coastguard Worker "toolchain_set_python_version_constraints": attr.string_list( 137*60517a1eSAndroid Build Coastguard Worker doc = "List of version contraints for the toolchains", 138*60517a1eSAndroid Build Coastguard Worker mandatory = True, 139*60517a1eSAndroid Build Coastguard Worker ), 140*60517a1eSAndroid Build Coastguard Worker "toolchain_user_repository_names": attr.string_list( 141*60517a1eSAndroid Build Coastguard Worker doc = "List of the user repo names for the toolchains", 142*60517a1eSAndroid Build Coastguard Worker mandatory = True, 143*60517a1eSAndroid Build Coastguard Worker ), 144*60517a1eSAndroid Build Coastguard Worker "_rules_python_workspace": attr.label(default = Label("//:does_not_matter_what_this_name_is")), 145*60517a1eSAndroid Build Coastguard Worker }, 146*60517a1eSAndroid Build Coastguard Worker) 147