Skip to content

Bazel 8 $(location) and --legacy_external_runfiles example

Notifications You must be signed in to change notification settings

mbland/bazel-8-location

Repository files navigation

Bazel 8 $(location) and --legacy_external_runfiles example

This reproduces the changing behavior of the $(location) predefined source/output path variable in Bazel 8.0.0 and Bazel 8.0.1. Corresponds to bazelbuild/bazel#25198.

Summary

Under Bazel 8, bazel build expansions of $(location) for targets in external repositories match $(execpath) instead of $(rootpath), which breaks some existing BUILD targets.

Under bazel run, expansions of $(location) match $(rootpath) instead.

There are two workarounds:

  • Update all affected $(location) expansions to use $(rootpath) instead. This is backwards compatible to Bazel 6.5.0.

  • Apply the --legacy_external_runfiles flag to restore the previous behavior, whereby expansions of $(rootpath), $(execpath), and $(location) are identical.

Running the reproduction

Run the run-reproduction.sh script, which uses bazelisk and .bazelversion to configure the Bazel version for each run. I distilled the repository rule in repository.bzl from the rule that instantiates the @org_apache_commons_commons_lang_3_5_without_file repo seen in bazelbuild/rules_scala#1678. (Specifically, from jvm_import_external in scala/scala_maven_import_external.bzl.)

The output will contain the following (edited out from all of the Bazel messages):

$ ./run-reproduction.sh

-----------
Bazel 7.5.0
-----------

From `bazel build //:build-expansions`:
  execpath: external/_main~_repo_rules~org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  rootpath: external/_main~_repo_rules~org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  location: external/_main~_repo_rules~org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar

From `bazel run //:run-expansions`:
  execpath: external/_main~_repo_rules~org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  rootpath: external/_main~_repo_rules~org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  location: external/_main~_repo_rules~org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar

-----------
Bazel 8.0.1
-----------

From `bazel build //:build-expansions`:
  execpath: external/+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  rootpath: ../+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  location: external/+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar

From `bazel run //:run-expansions`:
  execpath: external/+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  rootpath: ../+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  location: ../+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar

-------------------------------------------
Bazel 8.0.1 with --legacy_external_runfiles
-------------------------------------------

From `bazel build //:build-expansions`:
  execpath: external/+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  rootpath: external/+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  location: external/+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar

From `bazel run //:run-expansions`:
  execpath: external/+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  rootpath: external/+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar
  location: external/+_repo_rules+org_apache_commons_commons_lang3_3_5/commons-lang3-3.5.jar

Analysis

All of the expansions in question are for targets in external repositories.

The reproduction shows that prior to Bazel 8, expansions of $(location), $(rootpath), and $(execpath) are identical. All of them begin with external/, whether running bazel build or bazel run.

Under Bazel 8, by default, expansions of $(rootpath) now begin with ../, and expansions of $(execpath) begin with external/. However, expansions of $(location) depend on the Bazel command:

Command $(location) expands to which starts with
bazel build $(execpath) external/
bazel run $(rootpath) ../

Setting the --legacy_external_runfiles flag to true will restore the behavior whereby all expansions are identical and begin with external/.

Conclusion

Arguably, users should always use $(rootpath) to expand targets in external repositories (unless they're using $(rlocationpath) with a runfiles library). The predefined source/output path variable documentation even mentions:

The rootpath of a file in an external repository repo will start with ../repo/, followed by the repository-relative path.

At the same time, bazel build should probably expand $(location) to match $(rootpath), just as bazel run already does.

Background

I'd first noticed the broken $(location) phenomenon when working on bazelbuild/rules_scala#1652, and committed the $(rootpath) fix in bazelbuild/rules_scala#1678. The message for bazelbuild/rules_scala@08ab275 contains notes on my investigation at the time.

Then @shs96c mentioned that he'd encountered the same problem in a #general thread in the Bazel Slack workspace on 2025-02-03. @fmeum mentioned the connection to --legacy_external_runfiles in the same thread.

About

Bazel 8 $(location) and --legacy_external_runfiles example

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published