|
| 1 | +# Copyright 2019 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 | +"""Definitions related to the Python toolchain.""" |
| 16 | + |
| 17 | +load(":utils.bzl", "expand_pyversion_template") |
| 18 | + |
| 19 | +def define_autodetecting_toolchain( |
| 20 | + name, |
| 21 | + pywrapper_template, |
| 22 | + windows_config_setting): |
| 23 | + """Defines the autodetecting Python toolchain. |
| 24 | +
|
| 25 | + This includes both strict and non-strict variants. |
| 26 | +
|
| 27 | + For use only by @bazel_tools//tools/python:BUILD; see the documentation |
| 28 | + comment there. |
| 29 | +
|
| 30 | + Args: |
| 31 | + name: The name of the toolchain to introduce. Must have value |
| 32 | + "autodetecting_toolchain". This param is present only to make the |
| 33 | + BUILD file more readable. |
| 34 | + pywrapper_template: The label of the pywrapper_template.txt file. |
| 35 | + windows_config_setting: The label of a config_setting that matches when |
| 36 | + the platform is windows, in which case the toolchain is configured |
| 37 | + in a way that triggers a workaround for #7844. |
| 38 | + """ |
| 39 | + if native.package_name() != "tools/python": |
| 40 | + fail("define_autodetecting_toolchain() is private to " + |
| 41 | + "@bazel_tools//tools/python") |
| 42 | + if name != "autodetecting_toolchain": |
| 43 | + fail("Python autodetecting toolchain must be named " + |
| 44 | + "'autodetecting_toolchain'") |
| 45 | + |
| 46 | + expand_pyversion_template( |
| 47 | + name = "_generate_wrappers", |
| 48 | + template = pywrapper_template, |
| 49 | + out2 = ":py2wrapper.sh", |
| 50 | + out3 = ":py3wrapper.sh", |
| 51 | + out2_nonstrict = ":py2wrapper_nonstrict.sh", |
| 52 | + out3_nonstrict = ":py3wrapper_nonstrict.sh", |
| 53 | + visibility = ["//visibility:private"], |
| 54 | + ) |
| 55 | + |
| 56 | + # Note that the pywrapper script is a .sh file, not a sh_binary target. If |
| 57 | + # we needed to make it a proper shell target, e.g. because it needed to |
| 58 | + # access runfiles and needed to depend on the runfiles library, then we'd |
| 59 | + # have to use a workaround to allow it to be depended on by py_runtime. See |
| 60 | + # https://github.com/bazelbuild/bazel/issues/4286#issuecomment-475661317. |
| 61 | + |
| 62 | + # buildifier: disable=native-py |
| 63 | + py_runtime( |
| 64 | + name = "_autodetecting_py3_runtime", |
| 65 | + interpreter = ":py3wrapper.sh", |
| 66 | + python_version = "PY3", |
| 67 | + stub_shebang = "#!/usr/bin/env python3", |
| 68 | + visibility = ["//visibility:private"], |
| 69 | + ) |
| 70 | + |
| 71 | + # buildifier: disable=native-py |
| 72 | + py_runtime( |
| 73 | + name = "_autodetecting_py3_runtime_nonstrict", |
| 74 | + interpreter = ":py3wrapper_nonstrict.sh", |
| 75 | + python_version = "PY3", |
| 76 | + stub_shebang = "#!/usr/bin/env python3", |
| 77 | + visibility = ["//visibility:private"], |
| 78 | + ) |
| 79 | + |
| 80 | + # This is a dummy runtime whose interpreter_path triggers the native rule |
| 81 | + # logic to use the legacy behavior on Windows. |
| 82 | + # TODO(#7844): Remove this target. |
| 83 | + # buildifier: disable=native-py |
| 84 | + py_runtime( |
| 85 | + name = "_magic_sentinel_runtime", |
| 86 | + interpreter_path = "/_magic_pyruntime_sentinel_do_not_use", |
| 87 | + python_version = "PY3", |
| 88 | + visibility = ["//visibility:private"], |
| 89 | + ) |
| 90 | + |
| 91 | + py_runtime_pair( |
| 92 | + name = "_autodetecting_py_runtime_pair", |
| 93 | + py3_runtime = select({ |
| 94 | + # If we're on windows, inject the sentinel to tell native rule logic |
| 95 | + # that we attempted to use the autodetecting toolchain and need to |
| 96 | + # switch back to legacy behavior. |
| 97 | + # TODO(#7844): Remove this hack. |
| 98 | + windows_config_setting: ":_magic_sentinel_runtime", |
| 99 | + "//conditions:default": ":_autodetecting_py3_runtime", |
| 100 | + }), |
| 101 | + visibility = ["//visibility:public"], |
| 102 | + ) |
| 103 | + |
| 104 | + py_runtime_pair( |
| 105 | + name = "_autodetecting_py_runtime_pair_nonstrict", |
| 106 | + py3_runtime = select({ |
| 107 | + # Same hack as above. |
| 108 | + # TODO(#7844): Remove this hack. |
| 109 | + windows_config_setting: ":_magic_sentinel_runtime", |
| 110 | + "//conditions:default": ":_autodetecting_py3_runtime_nonstrict", |
| 111 | + }), |
| 112 | + visibility = ["//visibility:public"], |
| 113 | + ) |
| 114 | + |
| 115 | + native.toolchain( |
| 116 | + name = name, |
| 117 | + toolchain = ":_autodetecting_py_runtime_pair", |
| 118 | + toolchain_type = ":toolchain_type", |
| 119 | + visibility = ["//visibility:public"], |
| 120 | + ) |
| 121 | + |
| 122 | + native.toolchain( |
| 123 | + name = name + "_nonstrict", |
| 124 | + toolchain = ":_autodetecting_py_runtime_pair_nonstrict", |
| 125 | + toolchain_type = ":toolchain_type", |
| 126 | + visibility = ["//visibility:public"], |
| 127 | + ) |
0 commit comments