1*60517a1eSAndroid Build Coastguard Worker:::{default-domain} bzl 2*60517a1eSAndroid Build Coastguard Worker::: 3*60517a1eSAndroid Build Coastguard Worker 4*60517a1eSAndroid Build Coastguard Worker# Configuring Python toolchains and runtimes 5*60517a1eSAndroid Build Coastguard Worker 6*60517a1eSAndroid Build Coastguard WorkerThis documents how to configure the Python toolchain and runtimes for different 7*60517a1eSAndroid Build Coastguard Workeruse cases. 8*60517a1eSAndroid Build Coastguard Worker 9*60517a1eSAndroid Build Coastguard Worker## Bzlmod MODULE configuration 10*60517a1eSAndroid Build Coastguard Worker 11*60517a1eSAndroid Build Coastguard WorkerHow to configure `rules_python` in your MODULE.bazel file depends on how and why 12*60517a1eSAndroid Build Coastguard Workeryou're using Python. There are 4 basic use cases: 13*60517a1eSAndroid Build Coastguard Worker 14*60517a1eSAndroid Build Coastguard Worker1. A root module that always uses Python. For example, you're building a 15*60517a1eSAndroid Build Coastguard Worker Python application. 16*60517a1eSAndroid Build Coastguard Worker2. A library module with dev-only uses of Python. For example, a Java project 17*60517a1eSAndroid Build Coastguard Worker that only uses Python as part of testing itself. 18*60517a1eSAndroid Build Coastguard Worker3. A library module without version constraints. For example, a rule set with 19*60517a1eSAndroid Build Coastguard Worker Python build tools, but defers to the user as to what Python version is used 20*60517a1eSAndroid Build Coastguard Worker for the tools. 21*60517a1eSAndroid Build Coastguard Worker4. A library module with version constraints. For example, a rule set with 22*60517a1eSAndroid Build Coastguard Worker Python build tools, and the module requires a specific version of Python 23*60517a1eSAndroid Build Coastguard Worker be used with its tools. 24*60517a1eSAndroid Build Coastguard Worker 25*60517a1eSAndroid Build Coastguard Worker### Root modules 26*60517a1eSAndroid Build Coastguard Worker 27*60517a1eSAndroid Build Coastguard WorkerRoot modules are always the top-most module. These are special in two ways: 28*60517a1eSAndroid Build Coastguard Worker 29*60517a1eSAndroid Build Coastguard Worker1. Some `rules_python` bzlmod APIs are only respected by the root module. 30*60517a1eSAndroid Build Coastguard Worker2. The root module can force module overrides and specific module dependency 31*60517a1eSAndroid Build Coastguard Worker ordering. 32*60517a1eSAndroid Build Coastguard Worker 33*60517a1eSAndroid Build Coastguard WorkerWhen configuring `rules_python` for a root module, you typically want to 34*60517a1eSAndroid Build Coastguard Workerexplicitly specify the Python version you want to use. This ensures that 35*60517a1eSAndroid Build Coastguard Workerdependencies don't change the Python version out from under you. Remember that 36*60517a1eSAndroid Build Coastguard Worker`rules_python` will set a version by default, but it will change regularly as 37*60517a1eSAndroid Build Coastguard Workerit tracks a recent Python version. 38*60517a1eSAndroid Build Coastguard Worker 39*60517a1eSAndroid Build Coastguard WorkerNOTE: If your root module only uses Python for development of the module itself, 40*60517a1eSAndroid Build Coastguard Workeryou should read the dev-only library module section. 41*60517a1eSAndroid Build Coastguard Worker 42*60517a1eSAndroid Build Coastguard Worker``` 43*60517a1eSAndroid Build Coastguard Workerbazel_dep(name="rules_python", version=...) 44*60517a1eSAndroid Build Coastguard Workerpython = use_extension("@rules_python//python/extensions:python.bzl", "python") 45*60517a1eSAndroid Build Coastguard Worker 46*60517a1eSAndroid Build Coastguard Workerpython.toolchain(python_version = "3.12", is_default = True) 47*60517a1eSAndroid Build Coastguard Worker``` 48*60517a1eSAndroid Build Coastguard Worker 49*60517a1eSAndroid Build Coastguard Worker### Library modules 50*60517a1eSAndroid Build Coastguard Worker 51*60517a1eSAndroid Build Coastguard WorkerA library module is a module that can show up in arbitrary locations in the 52*60517a1eSAndroid Build Coastguard Workerbzlmod module graph -- it's unknown where in the breadth-first search order the 53*60517a1eSAndroid Build Coastguard Workermodule will be relative to other modules. For example, `rules_python` is a 54*60517a1eSAndroid Build Coastguard Workerlibrary module. 55*60517a1eSAndroid Build Coastguard Worker 56*60517a1eSAndroid Build Coastguard Worker#### Library modules with dev-only Python usage 57*60517a1eSAndroid Build Coastguard Worker 58*60517a1eSAndroid Build Coastguard WorkerA library module with dev-only Python usage is usually one where Python is only 59*60517a1eSAndroid Build Coastguard Workerused as part of its tests. For example, a module for Java rules might run some 60*60517a1eSAndroid Build Coastguard WorkerPython program to generate test data, but real usage of the rules don't need 61*60517a1eSAndroid Build Coastguard WorkerPython to work. To configure this, follow the root-module setup, but remember to 62*60517a1eSAndroid Build Coastguard Workerspecify `dev_dependency = True` to the bzlmod APIs: 63*60517a1eSAndroid Build Coastguard Worker 64*60517a1eSAndroid Build Coastguard Worker``` 65*60517a1eSAndroid Build Coastguard Worker# MODULE.bazel 66*60517a1eSAndroid Build Coastguard Workerbazel_dep(name = "rules_python", version=..., dev_dependency = True) 67*60517a1eSAndroid Build Coastguard Worker 68*60517a1eSAndroid Build Coastguard Workerpython = use_extension( 69*60517a1eSAndroid Build Coastguard Worker "@rules_python//python/extensions:python.bzl", 70*60517a1eSAndroid Build Coastguard Worker "python", 71*60517a1eSAndroid Build Coastguard Worker dev_dependency = True 72*60517a1eSAndroid Build Coastguard Worker) 73*60517a1eSAndroid Build Coastguard Worker 74*60517a1eSAndroid Build Coastguard Workerpython.toolchain(python_version = "3.12", is_default=True) 75*60517a1eSAndroid Build Coastguard Worker``` 76*60517a1eSAndroid Build Coastguard Worker 77*60517a1eSAndroid Build Coastguard Worker#### Library modules without version constraints 78*60517a1eSAndroid Build Coastguard Worker 79*60517a1eSAndroid Build Coastguard WorkerA library module without version constraints is one where the version of Python 80*60517a1eSAndroid Build Coastguard Workerused for the Python programs it runs isn't chosen by the module itself. Instead, 81*60517a1eSAndroid Build Coastguard Workerit's up to the root module to pick an appropriate version of Python. 82*60517a1eSAndroid Build Coastguard Worker 83*60517a1eSAndroid Build Coastguard WorkerFor this case, configuration is simple: just depend on `rules_python` and use 84*60517a1eSAndroid Build Coastguard Workerthe normal `//python:py_binary.bzl` et al rules. There is no need to call 85*60517a1eSAndroid Build Coastguard Worker`python.toolchain` -- rules_python ensures _some_ Python version is available, 86*60517a1eSAndroid Build Coastguard Workerbut more often the root module will specify some version. 87*60517a1eSAndroid Build Coastguard Worker 88*60517a1eSAndroid Build Coastguard Worker``` 89*60517a1eSAndroid Build Coastguard Worker# MODULE.bazel 90*60517a1eSAndroid Build Coastguard Workerbazel_dep(name = "rules_python", version=...) 91*60517a1eSAndroid Build Coastguard Worker``` 92*60517a1eSAndroid Build Coastguard Worker 93*60517a1eSAndroid Build Coastguard Worker#### Library modules with version constraints 94*60517a1eSAndroid Build Coastguard Worker 95*60517a1eSAndroid Build Coastguard WorkerA library module with version constraints is one where the module requires a 96*60517a1eSAndroid Build Coastguard Workerspecific Python version be used with its tools. This has some pros/cons: 97*60517a1eSAndroid Build Coastguard Worker 98*60517a1eSAndroid Build Coastguard Worker* It allows the library's tools to use a different version of Python than 99*60517a1eSAndroid Build Coastguard Worker the rest of the build. For example, a user's program could use Python 3.12, 100*60517a1eSAndroid Build Coastguard Worker while the library module's tools use Python 3.10. 101*60517a1eSAndroid Build Coastguard Worker* It reduces the support burden for the library module because the library only needs 102*60517a1eSAndroid Build Coastguard Worker to test for the particular Python version they intend to run as. 103*60517a1eSAndroid Build Coastguard Worker* It raises the support burden for the library module because the version of 104*60517a1eSAndroid Build Coastguard Worker Python being used needs to be regularly incremented. 105*60517a1eSAndroid Build Coastguard Worker* It has higher build overhead because additional runtimes and libraries need 106*60517a1eSAndroid Build Coastguard Worker to be downloaded, and Bazel has to keep additional configuration state. 107*60517a1eSAndroid Build Coastguard Worker 108*60517a1eSAndroid Build Coastguard WorkerTo configure this, request the Python versions needed in MODULE.bazel and use 109*60517a1eSAndroid Build Coastguard Workerthe version-aware rules for `py_binary`. 110*60517a1eSAndroid Build Coastguard Worker 111*60517a1eSAndroid Build Coastguard Worker``` 112*60517a1eSAndroid Build Coastguard Worker# MODULE.bazel 113*60517a1eSAndroid Build Coastguard Workerbazel_dep(name = "rules_python", version=...) 114*60517a1eSAndroid Build Coastguard Worker 115*60517a1eSAndroid Build Coastguard Workerpython = use_extension("@rules_python//python/extensions:python.bzl", "python") 116*60517a1eSAndroid Build Coastguard Workerpython.toolchain(python_version = "3.12") 117*60517a1eSAndroid Build Coastguard Worker 118*60517a1eSAndroid Build Coastguard Worker# BUILD.bazel 119*60517a1eSAndroid Build Coastguard Workerload("@python_versions//3.12:defs.bzl", "py_binary") 120*60517a1eSAndroid Build Coastguard Worker 121*60517a1eSAndroid Build Coastguard Workerpy_binary(...) 122*60517a1eSAndroid Build Coastguard Worker``` 123*60517a1eSAndroid Build Coastguard Worker 124*60517a1eSAndroid Build Coastguard Worker### Pinning to a Python version 125*60517a1eSAndroid Build Coastguard Worker 126*60517a1eSAndroid Build Coastguard WorkerPinning to a version allows targets to force that a specific Python version is 127*60517a1eSAndroid Build Coastguard Workerused, even if the root module configures a different version as a default. This 128*60517a1eSAndroid Build Coastguard Workeris most useful for two cases: 129*60517a1eSAndroid Build Coastguard Worker 130*60517a1eSAndroid Build Coastguard Worker1. For submodules to ensure they run with the appropriate Python version 131*60517a1eSAndroid Build Coastguard Worker2. To allow incremental, per-target, upgrading to newer Python versions, 132*60517a1eSAndroid Build Coastguard Worker typically in a mono-repo situation. 133*60517a1eSAndroid Build Coastguard Worker 134*60517a1eSAndroid Build Coastguard WorkerTo configure a submodule with the version-aware rules, request the particular 135*60517a1eSAndroid Build Coastguard Workerversion you need, then use the `@python_versions` repo to use the rules that 136*60517a1eSAndroid Build Coastguard Workerforce specific versions: 137*60517a1eSAndroid Build Coastguard Worker 138*60517a1eSAndroid Build Coastguard Worker```starlark 139*60517a1eSAndroid Build Coastguard Workerpython = use_extension("@rules_python//python/extensions:python.bzl", "python") 140*60517a1eSAndroid Build Coastguard Worker 141*60517a1eSAndroid Build Coastguard Workerpython.toolchain( 142*60517a1eSAndroid Build Coastguard Worker python_version = "3.11", 143*60517a1eSAndroid Build Coastguard Worker) 144*60517a1eSAndroid Build Coastguard Workeruse_repo(python, "python_versions") 145*60517a1eSAndroid Build Coastguard Worker``` 146*60517a1eSAndroid Build Coastguard Worker 147*60517a1eSAndroid Build Coastguard WorkerThen use e.g. `load("@python_versions//3.11:defs.bzl", "py_binary")` to use 148*60517a1eSAndroid Build Coastguard Workerthe rules that force that particular version. Multiple versions can be specified 149*60517a1eSAndroid Build Coastguard Workerand use within a single build. 150*60517a1eSAndroid Build Coastguard Worker 151*60517a1eSAndroid Build Coastguard WorkerFor more documentation, see the bzlmod examples under the {gh-path}`examples` 152*60517a1eSAndroid Build Coastguard Workerfolder. Look for the examples that contain a `MODULE.bazel` file. 153*60517a1eSAndroid Build Coastguard Worker 154*60517a1eSAndroid Build Coastguard Worker### Other toolchain details 155*60517a1eSAndroid Build Coastguard Worker 156*60517a1eSAndroid Build Coastguard WorkerThe `python.toolchain()` call makes its contents available under a repo named 157*60517a1eSAndroid Build Coastguard Worker`python_X_Y`, where X and Y are the major and minor versions. For example, 158*60517a1eSAndroid Build Coastguard Worker`python.toolchain(python_version="3.11")` creates the repo `@python_3_11`. 159*60517a1eSAndroid Build Coastguard WorkerRemember to call `use_repo()` to make repos visible to your module: 160*60517a1eSAndroid Build Coastguard Worker`use_repo(python, "python_3_11")` 161*60517a1eSAndroid Build Coastguard Worker 162*60517a1eSAndroid Build Coastguard Worker#### Toolchain usage in other rules 163*60517a1eSAndroid Build Coastguard Worker 164*60517a1eSAndroid Build Coastguard WorkerPython toolchains can be utilized in other bazel rules, such as `genrule()`, by 165*60517a1eSAndroid Build Coastguard Workeradding the `toolchains=["@rules_python//python:current_py_toolchain"]` 166*60517a1eSAndroid Build Coastguard Workerattribute. You can obtain the path to the Python interpreter using the 167*60517a1eSAndroid Build Coastguard Worker`$(PYTHON2)` and `$(PYTHON3)` ["Make" 168*60517a1eSAndroid Build Coastguard WorkerVariables](https://bazel.build/reference/be/make-variables). See the 169*60517a1eSAndroid Build Coastguard Worker{gh-path}`test_current_py_toolchain <tests/load_from_macro/BUILD.bazel>` target 170*60517a1eSAndroid Build Coastguard Workerfor an example. 171*60517a1eSAndroid Build Coastguard Worker 172*60517a1eSAndroid Build Coastguard Worker### Overriding toolchain defaults and adding more versions 173*60517a1eSAndroid Build Coastguard Worker 174*60517a1eSAndroid Build Coastguard WorkerOne can perform various overrides for the registered toolchains from the root 175*60517a1eSAndroid Build Coastguard Workermodule. For example, the following use cases would be supported using the 176*60517a1eSAndroid Build Coastguard Workerexisting attributes: 177*60517a1eSAndroid Build Coastguard Worker 178*60517a1eSAndroid Build Coastguard Worker* Limiting the available toolchains for the entire `bzlmod` transitive graph 179*60517a1eSAndroid Build Coastguard Worker via {attr}`python.override.available_python_versions`. 180*60517a1eSAndroid Build Coastguard Worker* Setting particular `X.Y.Z` Python versions when modules request `X.Y` version 181*60517a1eSAndroid Build Coastguard Worker via {attr}`python.override.minor_mapping`. 182*60517a1eSAndroid Build Coastguard Worker* Per-version control of the coverage tool used using 183*60517a1eSAndroid Build Coastguard Worker {attr}`python.single_version_platform_override.coverage_tool`. 184*60517a1eSAndroid Build Coastguard Worker* Adding additional Python versions via {bzl:obj}`python.single_version_override` or 185*60517a1eSAndroid Build Coastguard Worker {bzl:obj}`python.single_version_platform_override`. 186*60517a1eSAndroid Build Coastguard Worker 187*60517a1eSAndroid Build Coastguard Worker## Workspace configuration 188*60517a1eSAndroid Build Coastguard Worker 189*60517a1eSAndroid Build Coastguard WorkerTo import rules_python in your project, you first need to add it to your 190*60517a1eSAndroid Build Coastguard Worker`WORKSPACE` file, using the snippet provided in the 191*60517a1eSAndroid Build Coastguard Worker[release you choose](https://github.com/bazelbuild/rules_python/releases) 192*60517a1eSAndroid Build Coastguard Worker 193*60517a1eSAndroid Build Coastguard WorkerTo depend on a particular unreleased version, you can do the following: 194*60517a1eSAndroid Build Coastguard Worker 195*60517a1eSAndroid Build Coastguard Worker```starlark 196*60517a1eSAndroid Build Coastguard Workerload("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 197*60517a1eSAndroid Build Coastguard Worker 198*60517a1eSAndroid Build Coastguard Worker 199*60517a1eSAndroid Build Coastguard Worker# Update the SHA and VERSION to the lastest version available here: 200*60517a1eSAndroid Build Coastguard Worker# https://github.com/bazelbuild/rules_python/releases. 201*60517a1eSAndroid Build Coastguard Worker 202*60517a1eSAndroid Build Coastguard WorkerSHA="84aec9e21cc56fbc7f1335035a71c850d1b9b5cc6ff497306f84cced9a769841" 203*60517a1eSAndroid Build Coastguard Worker 204*60517a1eSAndroid Build Coastguard WorkerVERSION="0.23.1" 205*60517a1eSAndroid Build Coastguard Worker 206*60517a1eSAndroid Build Coastguard Workerhttp_archive( 207*60517a1eSAndroid Build Coastguard Worker name = "rules_python", 208*60517a1eSAndroid Build Coastguard Worker sha256 = SHA, 209*60517a1eSAndroid Build Coastguard Worker strip_prefix = "rules_python-{}".format(VERSION), 210*60517a1eSAndroid Build Coastguard Worker url = "https://github.com/bazelbuild/rules_python/releases/download/{}/rules_python-{}.tar.gz".format(VERSION,VERSION), 211*60517a1eSAndroid Build Coastguard Worker) 212*60517a1eSAndroid Build Coastguard Worker 213*60517a1eSAndroid Build Coastguard Workerload("@rules_python//python:repositories.bzl", "py_repositories") 214*60517a1eSAndroid Build Coastguard Worker 215*60517a1eSAndroid Build Coastguard Workerpy_repositories() 216*60517a1eSAndroid Build Coastguard Worker``` 217*60517a1eSAndroid Build Coastguard Worker 218*60517a1eSAndroid Build Coastguard Worker### Workspace toolchain registration 219*60517a1eSAndroid Build Coastguard Worker 220*60517a1eSAndroid Build Coastguard WorkerTo register a hermetic Python toolchain rather than rely on a system-installed interpreter for runtime execution, you can add to the `WORKSPACE` file: 221*60517a1eSAndroid Build Coastguard Worker 222*60517a1eSAndroid Build Coastguard Worker```starlark 223*60517a1eSAndroid Build Coastguard Workerload("@rules_python//python:repositories.bzl", "python_register_toolchains") 224*60517a1eSAndroid Build Coastguard Worker 225*60517a1eSAndroid Build Coastguard Workerpython_register_toolchains( 226*60517a1eSAndroid Build Coastguard Worker name = "python_3_11", 227*60517a1eSAndroid Build Coastguard Worker # Available versions are listed in @rules_python//python:versions.bzl. 228*60517a1eSAndroid Build Coastguard Worker # We recommend using the same version your team is already standardized on. 229*60517a1eSAndroid Build Coastguard Worker python_version = "3.11", 230*60517a1eSAndroid Build Coastguard Worker) 231*60517a1eSAndroid Build Coastguard Worker 232*60517a1eSAndroid Build Coastguard Workerload("@python_3_11//:defs.bzl", "interpreter") 233*60517a1eSAndroid Build Coastguard Worker 234*60517a1eSAndroid Build Coastguard Workerload("@rules_python//python:pip.bzl", "pip_parse") 235*60517a1eSAndroid Build Coastguard Worker 236*60517a1eSAndroid Build Coastguard Workerpip_parse( 237*60517a1eSAndroid Build Coastguard Worker ... 238*60517a1eSAndroid Build Coastguard Worker python_interpreter_target = interpreter, 239*60517a1eSAndroid Build Coastguard Worker ... 240*60517a1eSAndroid Build Coastguard Worker) 241*60517a1eSAndroid Build Coastguard Worker``` 242*60517a1eSAndroid Build Coastguard Worker 243*60517a1eSAndroid Build Coastguard WorkerAfter registration, your Python targets will use the toolchain's interpreter during execution, but a system-installed interpreter 244*60517a1eSAndroid Build Coastguard Workeris still used to 'bootstrap' Python targets (see https://github.com/bazelbuild/rules_python/issues/691). 245*60517a1eSAndroid Build Coastguard WorkerYou may also find some quirks while using this toolchain. Please refer to [python-build-standalone documentation's _Quirks_ section](https://gregoryszorc.com/docs/python-build-standalone/main/quirks.html). 246*60517a1eSAndroid Build Coastguard Worker 247*60517a1eSAndroid Build Coastguard Worker## Autodetecting toolchain 248*60517a1eSAndroid Build Coastguard Worker 249*60517a1eSAndroid Build Coastguard WorkerThe autodetecting toolchain is a deprecated toolchain that is built into Bazel. 250*60517a1eSAndroid Build Coastguard WorkerIt's name is a bit misleading: it doesn't autodetect anything. All it does is 251*60517a1eSAndroid Build Coastguard Workeruse `python3` from the environment a binary runs within. This provides extremely 252*60517a1eSAndroid Build Coastguard Workerlimited functionality to the rules (at build time, nothing is knowable about 253*60517a1eSAndroid Build Coastguard Workerthe Python runtime). 254*60517a1eSAndroid Build Coastguard Worker 255*60517a1eSAndroid Build Coastguard WorkerBazel itself automatically registers `@bazel_tools//tools/python:autodetecting_toolchain` 256*60517a1eSAndroid Build Coastguard Workeras the lowest priority toolchain. For WORKSPACE builds, if no other toolchain 257*60517a1eSAndroid Build Coastguard Workeris registered, that toolchain will be used. For bzlmod builds, rules_python 258*60517a1eSAndroid Build Coastguard Workerautomatically registers a higher-priority toolchain; it won't be used unless 259*60517a1eSAndroid Build Coastguard Workerthere is a toolchain misconfiguration somewhere. 260*60517a1eSAndroid Build Coastguard Worker 261*60517a1eSAndroid Build Coastguard WorkerTo aid migration off the Bazel-builtin toolchain, rules_python provides 262*60517a1eSAndroid Build Coastguard Worker{bzl:obj}`@rules_python//python/runtime_env_toolchains:all`. This is an equivalent 263*60517a1eSAndroid Build Coastguard Workertoolchain, but is implemented using rules_python's objects. 264*60517a1eSAndroid Build Coastguard Worker 265*60517a1eSAndroid Build Coastguard Worker 266*60517a1eSAndroid Build Coastguard Worker## Custom toolchains 267*60517a1eSAndroid Build Coastguard Worker 268*60517a1eSAndroid Build Coastguard WorkerWhile rules_python provides toolchains by default, it is not required to use 269*60517a1eSAndroid Build Coastguard Workerthem, and you can define your own toolchains to use instead. This section 270*60517a1eSAndroid Build Coastguard Workergives an introduction for how to define them yourself. 271*60517a1eSAndroid Build Coastguard Worker 272*60517a1eSAndroid Build Coastguard Worker:::{note} 273*60517a1eSAndroid Build Coastguard Worker* Defining your own toolchains is an advanced feature. 274*60517a1eSAndroid Build Coastguard Worker* APIs used for defining them are less stable and may change more often. 275*60517a1eSAndroid Build Coastguard Worker::: 276*60517a1eSAndroid Build Coastguard Worker 277*60517a1eSAndroid Build Coastguard WorkerUnder the hood, there are multiple toolchains that comprise the different 278*60517a1eSAndroid Build Coastguard Workerinformation necessary to build Python targets. Each one has an 279*60517a1eSAndroid Build Coastguard Workerassociated _toolchain type_ that identifies it. We call the collection of these 280*60517a1eSAndroid Build Coastguard Workertoolchains a "toolchain suite". 281*60517a1eSAndroid Build Coastguard Worker 282*60517a1eSAndroid Build Coastguard WorkerOne of the underlying design goals of the toolchains is to support complex and 283*60517a1eSAndroid Build Coastguard Workerbespoke environments. Such environments may use an arbitrary combination of 284*60517a1eSAndroid Build Coastguard Worker{obj}`RBE`, cross-platform building, multiple Python versions, 285*60517a1eSAndroid Build Coastguard Workerbuilding Python from source, embeding Python (as opposed to building separate 286*60517a1eSAndroid Build Coastguard Workerinterpreters), using prebuilt binaries, or using binaries built from source. To 287*60517a1eSAndroid Build Coastguard Workerthat end, many of the attributes they accept, and fields they provide, are 288*60517a1eSAndroid Build Coastguard Workeroptional. 289*60517a1eSAndroid Build Coastguard Worker 290*60517a1eSAndroid Build Coastguard Worker### Target toolchain type 291*60517a1eSAndroid Build Coastguard Worker 292*60517a1eSAndroid Build Coastguard WorkerThe target toolchain type is {obj}`//python:toolchain_type`, and it 293*60517a1eSAndroid Build Coastguard Workeris for _target configuration_ runtime information, e.g., the Python version 294*60517a1eSAndroid Build Coastguard Workerand interpreter binary that a program will use. 295*60517a1eSAndroid Build Coastguard Worker 296*60517a1eSAndroid Build Coastguard WorkerThe is typically implemented using {obj}`py_runtime()`, which 297*60517a1eSAndroid Build Coastguard Workerprovides the {obj}`PyRuntimeInfo` provider. For historical reasons from the 298*60517a1eSAndroid Build Coastguard WorkerPython 2 transition, `py_runtime` is wrapped in {obj}`py_runtime_pair`, 299*60517a1eSAndroid Build Coastguard Workerwhich provides {obj}`ToolchainInfo` with the field `py3_runtime`, which is an 300*60517a1eSAndroid Build Coastguard Workerinstance of `PyRuntimeInfo`. 301*60517a1eSAndroid Build Coastguard Worker 302*60517a1eSAndroid Build Coastguard WorkerThis toolchain type is intended to hold only _target configuration_ values. As 303*60517a1eSAndroid Build Coastguard Workersuch, when defining its associated {external:bzl:obj}`toolchain` target, only 304*60517a1eSAndroid Build Coastguard Workerset {external:bzl:obj}`toolchain.target_compatible_with` and/or 305*60517a1eSAndroid Build Coastguard Worker{external:bzl:obj}`toolchain.target_settings` constraints; there is no need to 306*60517a1eSAndroid Build Coastguard Workerset {external:bzl:obj}`toolchain.exec_compatible_with`. 307*60517a1eSAndroid Build Coastguard Worker 308*60517a1eSAndroid Build Coastguard Worker### Python C toolchain type 309*60517a1eSAndroid Build Coastguard Worker 310*60517a1eSAndroid Build Coastguard WorkerThe Python C toolchain type ("py cc") is {obj}`//python/cc:toolchain_type`, and 311*60517a1eSAndroid Build Coastguard Workerit has C/C++ information for the _target configuration_, e.g. the C headers that 312*60517a1eSAndroid Build Coastguard Workerprovide `Python.h`. 313*60517a1eSAndroid Build Coastguard Worker 314*60517a1eSAndroid Build Coastguard WorkerThis is typically implemented using {obj}`py_cc_toolchain()`, which provides 315*60517a1eSAndroid Build Coastguard Worker{obj}`ToolchainInfo` with the field `py_cc_toolchain` set, which is a 316*60517a1eSAndroid Build Coastguard Worker{obj}`PyCcToolchainInfo` provider instance. 317*60517a1eSAndroid Build Coastguard Worker 318*60517a1eSAndroid Build Coastguard WorkerThis toolchain type is intended to hold only _target configuration_ values 319*60517a1eSAndroid Build Coastguard Workerrelating to the C/C++ information for the Python runtime. As such, when defining 320*60517a1eSAndroid Build Coastguard Workerits associated {external:obj}`toolchain` target, only set 321*60517a1eSAndroid Build Coastguard Worker{external:bzl:obj}`toolchain.target_compatible_with` and/or 322*60517a1eSAndroid Build Coastguard Worker{external:bzl:obj}`toolchain.target_settings` constraints; there is no need to 323*60517a1eSAndroid Build Coastguard Workerset {external:bzl:obj}`toolchain.exec_compatible_with`. 324*60517a1eSAndroid Build Coastguard Worker 325*60517a1eSAndroid Build Coastguard Worker### Exec tools toolchain type 326*60517a1eSAndroid Build Coastguard Worker 327*60517a1eSAndroid Build Coastguard WorkerThe exec tools toolchain type is {obj}`//python:exec_tools_toolchain_type`, 328*60517a1eSAndroid Build Coastguard Workerand it is for supporting tools for _building_ programs, e.g. the binary to 329*60517a1eSAndroid Build Coastguard Workerprecompile code at build time. 330*60517a1eSAndroid Build Coastguard Worker 331*60517a1eSAndroid Build Coastguard WorkerThis toolchain type is intended to hold only _exec configuration_ values -- 332*60517a1eSAndroid Build Coastguard Workerusually tools (prebuilt or from-source) used to build Python targets. 333*60517a1eSAndroid Build Coastguard Worker 334*60517a1eSAndroid Build Coastguard WorkerThis is typically implemented using {obj}`py_exec_tools_toolchain`, which 335*60517a1eSAndroid Build Coastguard Workerprovides {obj}`ToolchainInfo` with the field `exec_tools` set, which is an 336*60517a1eSAndroid Build Coastguard Workerinstance of {obj}`PyExecToolsInfo`. 337*60517a1eSAndroid Build Coastguard Worker 338*60517a1eSAndroid Build Coastguard WorkerThe toolchain constraints of this toolchain type can be a bit more nuanced than 339*60517a1eSAndroid Build Coastguard Workerthe other toolchain types. Typically, you set 340*60517a1eSAndroid Build Coastguard Worker{external:bzl:obj}`toolchain.target_settings` to the Python version the tools 341*60517a1eSAndroid Build Coastguard Workerare for, and {external:bzl:obj}`toolchain.exec_compatible_with` to the platform 342*60517a1eSAndroid Build Coastguard Workerthey can run on. This allows the toolchain to first be considered based on the 343*60517a1eSAndroid Build Coastguard Workertarget configuration (e.g. Python version), then for one to be chosen based on 344*60517a1eSAndroid Build Coastguard Workerfinding one compatible with the available host platforms to run the tool on. 345*60517a1eSAndroid Build Coastguard Worker 346*60517a1eSAndroid Build Coastguard WorkerHowever, what `target_compatible_with`/`target_settings` and 347*60517a1eSAndroid Build Coastguard Worker`exec_compatible_with` values to use depend on details of the tools being used. 348*60517a1eSAndroid Build Coastguard WorkerFor example: 349*60517a1eSAndroid Build Coastguard Worker* If you had a precompiler that supported any version of Python, then 350*60517a1eSAndroid Build Coastguard Worker putting the Python version in `target_settings` is unnecessary. 351*60517a1eSAndroid Build Coastguard Worker* If you had a prebuilt polyglot precompiler binary that could run on any 352*60517a1eSAndroid Build Coastguard Worker platform, then setting `exec_compatible_with` is unnecessary. 353*60517a1eSAndroid Build Coastguard Worker 354*60517a1eSAndroid Build Coastguard WorkerThis can work because, when the rules invoke these build tools, they pass along 355*60517a1eSAndroid Build Coastguard Workerall necessary information so that the tool can be entirely independent of the 356*60517a1eSAndroid Build Coastguard Workertarget configuration being built for. 357*60517a1eSAndroid Build Coastguard Worker 358*60517a1eSAndroid Build Coastguard WorkerAlternatively, if you had a precompiler that only ran on linux, and only 359*60517a1eSAndroid Build Coastguard Workerproduced valid output for programs intended to run on linux, then _both_ 360*60517a1eSAndroid Build Coastguard Worker`exec_compatible_with` and `target_compatible_with` must be set to linux. 361*60517a1eSAndroid Build Coastguard Worker 362*60517a1eSAndroid Build Coastguard Worker### Custom toolchain example 363*60517a1eSAndroid Build Coastguard Worker 364*60517a1eSAndroid Build Coastguard WorkerHere, we show an example for a semi-complicated toolchain suite, one that is: 365*60517a1eSAndroid Build Coastguard Worker 366*60517a1eSAndroid Build Coastguard Worker* A CPython-based interpreter 367*60517a1eSAndroid Build Coastguard Worker* For Python version 3.12.0 368*60517a1eSAndroid Build Coastguard Worker* Using an in-build interpreter built from source 369*60517a1eSAndroid Build Coastguard Worker* That only runs on Linux 370*60517a1eSAndroid Build Coastguard Worker* Using a prebuilt precompiler that only runs on Linux, and only produces byte 371*60517a1eSAndroid Build Coastguard Worker code valid for 3.12 372*60517a1eSAndroid Build Coastguard Worker* With the exec tools interpreter disabled (unnecessary with a prebuild 373*60517a1eSAndroid Build Coastguard Worker precompiler) 374*60517a1eSAndroid Build Coastguard Worker* Providing C headers and libraries 375*60517a1eSAndroid Build Coastguard Worker 376*60517a1eSAndroid Build Coastguard WorkerDefining toolchains for this might look something like this: 377*60517a1eSAndroid Build Coastguard Worker 378*60517a1eSAndroid Build Coastguard Worker``` 379*60517a1eSAndroid Build Coastguard Worker# File: toolchain_impls/BUILD 380*60517a1eSAndroid Build Coastguard Workerload("@rules_python//python:py_cc_toolchain.bzl", "py_cc_toolchain") 381*60517a1eSAndroid Build Coastguard Workerload("@rules_python//python:py_exec_tools_toolchain.bzl", "py_exec_tools_toolchain") 382*60517a1eSAndroid Build Coastguard Workerload("@rules_python//python:py_runtime.bzl", "py_runtime") 383*60517a1eSAndroid Build Coastguard Workerload("@rules_python//python:py_runtime_pair.bzl", "py_runtime_pair") 384*60517a1eSAndroid Build Coastguard Worker 385*60517a1eSAndroid Build Coastguard WorkerMAJOR = 3 386*60517a1eSAndroid Build Coastguard WorkerMINOR = 12 387*60517a1eSAndroid Build Coastguard WorkerMICRO = 0 388*60517a1eSAndroid Build Coastguard Worker 389*60517a1eSAndroid Build Coastguard Workerpy_runtime( 390*60517a1eSAndroid Build Coastguard Worker name = "runtime", 391*60517a1eSAndroid Build Coastguard Worker interpreter = ":python", 392*60517a1eSAndroid Build Coastguard Worker interpreter_version_info = { 393*60517a1eSAndroid Build Coastguard Worker "major": str(MAJOR), 394*60517a1eSAndroid Build Coastguard Worker "minor": str(MINOR), 395*60517a1eSAndroid Build Coastguard Worker "micro": str(MICRO), 396*60517a1eSAndroid Build Coastguard Worker } 397*60517a1eSAndroid Build Coastguard Worker implementation = "cpython" 398*60517a1eSAndroid Build Coastguard Worker) 399*60517a1eSAndroid Build Coastguard Workerpy_runtime_pair( 400*60517a1eSAndroid Build Coastguard Worker name = "runtime_pair", 401*60517a1eSAndroid Build Coastguard Worker py3_runtime = ":runtime" 402*60517a1eSAndroid Build Coastguard Worker) 403*60517a1eSAndroid Build Coastguard Worker 404*60517a1eSAndroid Build Coastguard Workerpy_cc_toolchain( 405*60517a1eSAndroid Build Coastguard Worker name = "py_cc_toolchain_impl", 406*60517a1eSAndroid Build Coastguard Worker headers = ":headers", 407*60517a1eSAndroid Build Coastguard Worker libs = ":libs", 408*60517a1eSAndroid Build Coastguard Worker python_version = "{}.{}".format(MAJOR, MINOR) 409*60517a1eSAndroid Build Coastguard Worker) 410*60517a1eSAndroid Build Coastguard Worker 411*60517a1eSAndroid Build Coastguard Workerpy_exec_tools_toolchain( 412*60517a1eSAndroid Build Coastguard Worker name = "exec_tools_toolchain_impl", 413*60517a1eSAndroid Build Coastguard Worker exec_interpreter = "@rules_python/python:none", 414*60517a1eSAndroid Build Coastguard Worker precompiler = "precompiler-cpython-3.12" 415*60517a1eSAndroid Build Coastguard Worker) 416*60517a1eSAndroid Build Coastguard Worker 417*60517a1eSAndroid Build Coastguard Workercc_binary(name = "python3.12", ...) 418*60517a1eSAndroid Build Coastguard Workercc_library(name = "headers", ...) 419*60517a1eSAndroid Build Coastguard Workercc_library(name = "libs", ...) 420*60517a1eSAndroid Build Coastguard Worker 421*60517a1eSAndroid Build Coastguard Worker# File: toolchains/BUILD 422*60517a1eSAndroid Build Coastguard Worker# Putting toolchain() calls in a separate package from the toolchain 423*60517a1eSAndroid Build Coastguard Worker# implementations minimizes Bazel loading overhead 424*60517a1eSAndroid Build Coastguard Worker 425*60517a1eSAndroid Build Coastguard Workertoolchain( 426*60517a1eSAndroid Build Coastguard Worker name = "runtime_toolchain", 427*60517a1eSAndroid Build Coastguard Worker toolchain = "//toolchain_impl:runtime_pair", 428*60517a1eSAndroid Build Coastguard Worker toolchain_type = "@rules_python//python:toolchain_type", 429*60517a1eSAndroid Build Coastguard Worker target_compatible_with = ["@platforms/os:linux"] 430*60517a1eSAndroid Build Coastguard Worker) 431*60517a1eSAndroid Build Coastguard Workertoolchain( 432*60517a1eSAndroid Build Coastguard Worker name = "py_cc_toolchain", 433*60517a1eSAndroid Build Coastguard Worker toolchain = "//toolchain_impl:py_cc_toolchain_impl", 434*60517a1eSAndroid Build Coastguard Worker toolchain_type = "@rules_python//python/cc:toolchain_type", 435*60517a1eSAndroid Build Coastguard Worker target_compatible_with = ["@platforms/os:linux"] 436*60517a1eSAndroid Build Coastguard Worker) 437*60517a1eSAndroid Build Coastguard Worker 438*60517a1eSAndroid Build Coastguard Workertoolchain( 439*60517a1eSAndroid Build Coastguard Worker name = "exec_tools_toolchain", 440*60517a1eSAndroid Build Coastguard Worker toolchain = "//toolchain_impl:exec_tools_toolchain_impl", 441*60517a1eSAndroid Build Coastguard Worker toolchain_type = "@rules_python//python:exec_tools_toolchain_type", 442*60517a1eSAndroid Build Coastguard Worker target_settings = [ 443*60517a1eSAndroid Build Coastguard Worker "@rules_python//python/config_settings:is_python_3.12", 444*60517a1eSAndroid Build Coastguard Worker ], 445*60517a1eSAndroid Build Coastguard Worker exec_comaptible_with = ["@platforms/os:linux"] 446*60517a1eSAndroid Build Coastguard Worker) 447*60517a1eSAndroid Build Coastguard Worker``` 448*60517a1eSAndroid Build Coastguard Worker 449*60517a1eSAndroid Build Coastguard Worker:::{note} 450*60517a1eSAndroid Build Coastguard WorkerThe toolchain() calls should be in a separate BUILD file from everything else. 451*60517a1eSAndroid Build Coastguard WorkerThis avoids Bazel having to perform unnecessary work when it discovers the list 452*60517a1eSAndroid Build Coastguard Workerof available toolchains. 453*60517a1eSAndroid Build Coastguard Worker::: 454