From cd07209388bbcb1f8c2f59713271caa6ee6bb6e2 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 27 Jul 2023 10:02:07 -0700 Subject: [PATCH 1/2] docs: Better explain when and how to use toolchains for bzlmod This explains the different ways to register toolchains and how to use them. Also fixes python_aliases -> python_versions repo name --- README.md | 87 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 4453436eb3..660e6e20af 100644 --- a/README.md +++ b/README.md @@ -41,37 +41,98 @@ the older way of configuring bazel with a `WORKSPACE` file. **IMPORTANT: bzlmod support is still in Beta; APIs are subject to change.** +The first step to using rules_python with bzlmod is to add the dependency to +your MODULE.bazel file: + +```starlark +# Update the version "0.0.0" to the release found here: +# https://github.com/bazelbuild/rules_python/releases. +bazel_dep(name = "rules_python", version = "0.0.0") +``` + +Once added, you can load the rules and use them: + +```starlark +load("@rules_python//python:py_binary.bzl", "py_binary") + +py_binary(...) +``` + +Depending on what you're doing, you likely want to do some additional +configuration to control what Python version is used; read the following +sections for how to do that. + #### Toolchain registration with bzlmod A default toolchain is automatically configured depending on `rules_python`. Note, however, the version used tracks the most recent Python release and will change often. -If you want to register specific Python versions, then use -`python.toolchain()` for each version you need: +If you want to use a specific Python version for your programs, then how +to do so depends on if you're configuring the root module or not. The root +module is special because it can set the *default* Python version, which +is used by the version-unaware rules (e.g. `//python:py_binary.bzl` et al). For +submodules, it's recommended to use the version-aware rules to pin your programs +to a specific Python version so they don't accidentally run with a different +version configured by the root module. + +##### Configuring and using the default Python version + +To specify what the default Python version is, set `is_default = True` when +calling `python.toolchain()`. This can only be done by the root module; it is +silently ignored if a submodule does it. Similarly, using the version-unaware +rules (which always use the default Python version) should only be done by the +root module. If submodules use them, then they may run with a different Python +version than they expect. ```starlark -# Update the version "0.0.0" to the release found here: -# https://github.com/bazelbuild/rules_python/releases. -bazel_dep(name = "rules_python", version = "0.0.0") python = use_extension("@rules_python//python/extensions:python.bzl", "python") python.toolchain( python_version = "3.11", + is_default = True, ) -use_repo(python, "python_3_11", "python_aliases") ``` -The `use_repo` statement above is essential as it imports one or more -repositories into the current module's scope. The two repositories `python_3_11` -and `python_aliases` are created internally by the `python` extension. -The name `python_versions` is a constant and is always imported. The identifier -`python_3_11` was created by using `"python_{}".format("3.11".replace(".","_"))`. -This rule takes the Python version and creates the repository name using -the version. +Then use the base rules from e.g. `//python:py_binary.bzl`. + +##### Pinning to a Python version + +Pinning to a version allows targets to force that a specific Python version is +used, even if the root module configures a different version as a default. This +is most useful for two cases: + +1. For submodules to ensure they run with the appropriate Python version +2. To allow incremental, per-target, upgrading to newer Python versions, + typically in a mono-repo situation. + +To configure a submodule with the version-aware rules, request the particular +version you need, then use the `@python_versions` repo to use the rules that +force specific versions: + +```starlark +python = use_extension("@rules_python//python/extensions:python.bzl", "python") + +python.toolchain( + python_version = "3.11", +) +use_repo(python, "python_versions") +``` + +Then use e.g. `load("@python_versions//3.11:defs.bzl", "py_binary")` to use +the rules that force that particular version. Multiple versions can be specified +and use within a single build. For more documentation, see the bzlmod examples under the [examples](examples) folder. Look for the examples that contain a `MODULE.bazel` file. +##### Other toolchain details + +The `python.toolchain()` call makes its contents available under a repo named +`python_X_Y`, where X and Y are the major and minor versions. For example, +`python.toolchain(python_version="3.11")` creates the repo `@python_3_11`. +Remember to call `use_repo()` to make repos visible to your module: +`use_repo(python, "python_3_11")` + ### Using a WORKSPACE file To import rules_python in your project, you first need to add it to your From 77084fca8f02299ca4105bb47688f2c8694e51b3 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Mon, 31 Jul 2023 13:27:03 -0700 Subject: [PATCH 2/2] fixup! docs: Better explain when and how to use toolchains for bzlmod --- python/extensions/pip.bzl | 7 ++++--- python/extensions/python.bzl | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/python/extensions/pip.bzl b/python/extensions/pip.bzl index b70327e8f4..bea75fb654 100644 --- a/python/extensions/pip.bzl +++ b/python/extensions/pip.bzl @@ -350,9 +350,10 @@ Targets from different hubs should not be used together. "python_version": attr.string( mandatory = True, doc = """ -The Python version to use for resolving the pip dependencies. If not specified, -then the default Python version (as set by the root module or rules_python) -will be used. +The Python version to use for resolving the pip dependencies, in Major.Minor +format (e.g. "3.11"). Patch level granularity (e.g. "3.11.1") is not supported. +If not specified, then the default Python version (as set by the root module or +rules_python) will be used. The version specified here must have a corresponding `python.toolchain()` configured. diff --git a/python/extensions/python.bzl b/python/extensions/python.bzl index 2d4032a546..2d007267b1 100644 --- a/python/extensions/python.bzl +++ b/python/extensions/python.bzl @@ -250,7 +250,9 @@ A toolchain's repository name uses the format `python_{major}_{minor}`, e.g. ), "python_version": attr.string( mandatory = True, - doc = "The Python version, in `major.minor` format, e.g '3.12', to create a toolchain for.", + doc = "The Python version, in `major.minor` format, e.g " + + "'3.12', to create a toolchain for. Patch level " + + "granularity (e.g. '3.12.1') is not supported.", ), }, ),