Skip to content

-Wconf:src filter resolves symlinks, breaking external/ filters in Bazel 9 #13145

@mbland

Description

@mbland

Reproduction steps

The following requires Bazelisk for selecting the Bazel version.

$ mkdir wconfsrc-repro
$ cd wconfsrc-repro
$ cat >MODULE.bazel
module(name = "wconfsrc_repro")

bazel_dep(name = "rules_scala", version = "7.1.5")

scala_config = use_extension(
    "@rules_scala//scala/extensions:config.bzl",
    "scala_config",
)
scala_config.settings(scala_version = "2.13.17")

scala_deps = use_extension(
    "@rules_scala//scala/extensions:deps.bzl",
    "scala_deps",
)
scala_deps.scala()

register_toolchains("//...:all")
^D

$ cat >BUILD
load("@rules_scala//scala:scala_toolchain.bzl", "scala_toolchain")

scala_toolchain(
    name = "toolchain_impl",
    scalacopts = [
        "-Xfatal-warnings",
        "-deprecation",
        "-Wconf:src=bazel-out/.*:s",
        "-Wconf:src=external/.*:s",
    ],
)

toolchain(
    name = "toolchain",
    toolchain = ":toolchain_impl",
    toolchain_type = "@rules_scala//scala:toolchain_type",
    visibility = ["//visibility:public"],
)
^D

# Output edited for readability
$ USE_BAZEL_VERSION=9.0.0rc1 bazel build \
  @rules_scala//third_party/dependency_analyzer/src/main:dependency_analyzer

INFO: Analyzed target
  @@rules_scala+//third_party/dependency_analyzer/src/main:dependency_analyzer
  (1 packages loaded, 15 targets and 16 aspects configured).
  [ ...snip... ]
ERROR: /private/var/tmp/_bazel_mbland/.../external/rules_scala+/third_party/dependency_analyzer/src/main/BUILD:4:39:
  scala @@rules_scala+//third_party/dependency_analyzer/src/main:dependency_analyzer failed:
  [ ...snip... ]
external/rules_scala+/third_party/dependency_analyzer/src/main/io/bazel/rulesscala/dependencyanalyzer/Reporter213.scala:21:
  warning: object JavaConverters in package collection is deprecated (since 2.13.0): Use `scala.jdk.CollectionConverters` instead
      case r: DepsTrackingReporter => r.registerAstUsedJars(usedJarPathToPositions.keys.toSet.asJava)
                                                                                        ^
external/rules_scala+/third_party/dependency_analyzer/src/main/io/bazel/rulesscala/dependencyanalyzer/Reporter213.scala:28:
  warning: method doReport in class FilteringReporter is deprecated (since 2.13.12): use the `doReport` overload instead
    global.reporter.doReport(pos, message, global.reporter.ERROR)
                    ^
external/rules_scala+/third_party/dependency_analyzer/src/main/io/bazel/rulesscala/dependencyanalyzer/Reporter213.scala:33:
  warning: method doReport in class FilteringReporter is deprecated (since 2.13.12): use the `doReport` overload instead
    global.reporter.doReport(pos, message, global.reporter.WARNING)
                    ^
error: No warnings can be incurred under -Werror.
3 warnings
1 error
Build failure with errors.
Target @@rules_scala+//third_party/dependency_analyzer/src/main:dependency_analyzer failed to build
[ ...snip... ]

Problem

The -Wconf:src filter in 2.12 and 2.13 resolves each source path to its canonical form before matching it. If the original path is a symlink, the actual path may not match the filter. This renders -Wconf:src=external/.*:s filters to silence warnings in external source repositories under Bazel 9 ineffective.

Scala3 does not have this issue, since Scala 3.5.0 and later uses toAbsolutePath in its implementation instead. Updating the MODULE.bazel file to use Scala 3.5.2 and adding/removing the -Wconf:src=external/.*:s flag demonstrates this.

Users may currently work around this problem by applying -Wconf:src=cache/repos/v1/contents/.*:s when building with Bazel 9. However, the behavior is still surprising, and the workaround isn't particularly discoverable or stable.

I'm happy to send a pull request to update SourcePattern.check() to use absolutePath instead.

(Granted, I/we should update the rules_scala implementations to address the deprecation warnings. But for now, they effectively illustrate the problem.)


More detail on the Bazel side: The Bazel output directory layout stores unpacked external source archives, such as rules_scala, in an external/ directory. This directory contains symlinks to the actual archives elsewhere on the file system.

# Change to the execroot directory revealed by building with
# `bazel build -s`
$ pushd /private/var/tmp/_bazel_mbland/.../execroot/_main

# Same `external/` symlink for both versions, pointing into the `external/`
# sibling of `execroot/`
$ ls -l external/rules_scala+
lrwxr-xr-x  1 mbland  wheel  85 Dec 11 14:08 external/rules_scala+@ -> /private/var/tmp/_bazel_mbland/.../external/rules_scala+

# The actual `external/rules_scala+` directory exists under 8.4.2
$ ls -l ../../external/rules_scala+
[ ...shows contents of actual external/rules_scala+ directory... ]

# The `external/rules_scala+` symlink under 9.0.0rc1,
# where the `...` segments are hash values
$ ls -l ../../external/rules_scala+
lrwxr-xr-x  1 mbland  wheel  148 Dec 11 16:45 ../../external/rules_scala+@ -> /var/tmp/_bazel_mbland/cache/repos/v1/contents/.../...

cc: @fmeum @Wyverald @rafikk

Also cc: @lrytz, author of scala/scala@39d3b3a and scala/scala#8373, in case there was a rationale for using canonicalPath over absolutePath.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions