Skip to content

Enabling bzlmod causes workspace toolchains to no longer be registered #1675

@rickeylev

Description

@rickeylev

🐞 bug report

Affected Rule

python_register_toolchains in WORKSPACE files

Is this a regression?

Unclear

Description

Enabling bzlmod, but still using a workspace file (i.e. an empty module file), causes the python toolchains to no longer be registered.

🔬 Minimal Reproduction

Modify tests/cc/py_cc_toolchain_registered in the following ways:

  • Comment out everything in MODULE.bazel
  • Change the toolchain being looked up to @rules_python//python:toolchain_type

Run bazel test ... --enable_bzlmod

Actual behavior:

Toolchain debug output says:

Selected @@bazel_tools//tools/python:_autodetecting_py_runtime_pair

This means its using python from the environment's path (i.e. some system python) instead of the hermetic runtimes that were configured in WORKSPACE.

Expected behavior

Toolchain debug output should print

Selected @@python_3_11_x86_64-unknown-linux-gnu//:python_runtimes

(the name of the repo set in WORKSPACE).

Analysis

The cause of this is python/repositories.bzl detects if bzlmod is enabled, and, if so, disables toolchain registration. This was done because native.register_toolchains isn't normally available when bzlmod is enabled. However, when the code path is through a WORKSPACE file, it appears that symbol is available.

The immediate fix is to move the "if bzlmod enabled, don't do X" logic out of python/repositories.bzl itself and into the bzlmod extension. The extension logic calls that same python_register_toolchains function. The "X" logic here is two parts:

  1. Whether to call native.register_toolchains
  2. Whether to call toolchains_repo() (which creates the repo with all the toolchain() calls)

Now that we have integration tests again, it's feasible to construct a test for this.

The thing to double check is toolchain precedence. I can't remember offhand what the precedence of workspace-registered toolchains are when bzlmod is enabled. The main thing we're looking for is that the workspace-registered toolchains are after the module.bazel ones -- this is necessary so that the version-aware rules pick up their correct toolchain. The workspace python_register_toolchains() call will create version-unaware toolchains, which will match everything

Workarounds

The best workaround is to update MODULE.bazel to register the toolchain.

# MODULE.bazel
bazel_dep(name = "rules_python")

python = use_extension("@rules_python//python/extensions/python.bzl", "python")
python.toolchain(python_version="3.10") # Or whatever version

# No need to register anything; it'll happen automatically by the above

The logic that prevents the toolchain from being registered also prevents creating the repo that defines the toolchains, so modifying the WORKSPACE file to fix this isn't very easy. To go that route, you need to manually redefine the toolchains somehow (either manually in your own BUILD file, or possibly by loading the private toolchains_repo() rule that is being skipped and manually re-invoking it). I wouldn't suggest either of those; the couple lines of MODULE config are much easier.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions