Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Bzlmod and add rules_scala to bazel-central-registry #1482

Open
sfc-gh-pbennes opened this issue Mar 16, 2023 · 62 comments · Fixed by #1619
Open

Support Bzlmod and add rules_scala to bazel-central-registry #1482

sfc-gh-pbennes opened this issue Mar 16, 2023 · 62 comments · Fixed by #1619

Comments

@sfc-gh-pbennes
Copy link

sfc-gh-pbennes commented Mar 16, 2023

Greetings!

It looks like rules_scala isn't part of the Bzlmod effort or added to bazel-central-registry yet. I've opened an issue both here and in https://github.com/bazelbuild/bazel-central-registry to request it: bazelbuild/bazel-central-registry#522

@chrislovecnm
Copy link

Just a note to anyone that starts the work native.register_toolchains is not supported when using bzlmod.

@sluongng
Copy link

@chrislovecnm
Copy link

chrislovecnm commented Jul 11, 2023

@sluongng
Copy link

Yeah you would only want to prepare the toolchain (as a new repository) inside the extension I think. Registering it must be called from the MODULE.bazel file.

So native.register_toolchains call from the extension's starlark does not work, but having the extension create @pythons_hub//:all and then MODULE.bazel calling register_toolchains("@pythons_hub//:all") worked. 👍

@mateuszkuta256
Copy link
Contributor

I prepared a minimal bzlmod support here and gonna split it into a few PRs
TODOs after merging it:

  • write documentation on how to use rules_scala with bzlmod (some properties like SCALA_VERSION will probably be configurable via repo-env)
  • prepare release notes
  • contribute repo to the Bazel Central Registry
  • add tests that the project builds using both WORKSPACE and MODULE.bazel
  • migrate test/external workspaces to blzmod too

@pcj
Copy link
Member

pcj commented Jun 30, 2024

@mateuszkuta256 thanks for getting this started! Any progress updates or blockers?

@mateuszkuta256
Copy link
Contributor

@mateuszkuta256 thanks for getting this started! Any progress updates or blockers?

hi, unfortunately I'm working on other things now and won't continue with this PR in the foreseeable future
I remember this migration was on hold because interfered with 'cross compilation support'
It looks like great progress was done it this area, so maybe someone can already take over the PR

@mbland
Copy link
Contributor

mbland commented Oct 2, 2024

I'd like to take on the task of Bzlmodifying this repo through a series of pull requests.

I've already created a (mostly) working branch in my own fork. Though I saw a couple draft pull requests here, I ended up taking a different approach and got it mostly working. In fact, I did exactly what @sluongng suggested in #1482 (comment). (I didn't notice this comment before just now—I might've read it, but not understood it at the time—but I did study rules_python and rules_go, and ended up doing exactly that.)

There are still issues I need help to address (recorded in some of the commit messages), I didn't strictly maintain WORKSPACE compatibility (fixable), and I only tested against Scala 2.13. But I can start teasing chunks out of it in a methodical fashion, to ensure that I maintain WORKSPACE and cross-version compatibility.

For an example of what it looks like from a client perspective, here's what the MODULE.bazel stanza from my local EngFlow/example repo looks like (as opposed to the current stanza, explanatory comment notwithstanding):

bazel_dep(name = "rules_scala", repo_name = "io_bazel_rules_scala")
local_path_override(
    module_name = "rules_scala",
    path = "../../bazelbuild/rules_scala"
)   

scala_dev_deps = use_extension(
    "@io_bazel_rules_scala//scala/extensions:deps.bzl",
    "scala_deps",
    dev_dependency = True,
)   
scala_dev_deps.toolchains(
    scalatest = True,
)

So if folks are game for me to do this, I'll start carving off pieces as separate pull requests, and we can resolve any outstanding problems in the process.

cc: @BillyAutrey @jayconrod @benjaminp @TheGrizzlyDev

mbland added a commit to mbland/rules_scala that referenced this issue Oct 3, 2024
This begins the Bzlmod compatibility migration by updating Bazel to
version 7.3.2 and adding initial `MODULE.bazel` and `WORKSPACE.bzlmod`
files.

Part of: bazelbuild#1482

Though Bzlmod remains disabled, updating to Bazel 7.3.2 requred updating
or adding the following packages to maintain `WORKSPACE` compatibility.

In `rules_scala_setup()`:

- bazel_skylib: 1.4.1 => 1.7.1
- rules_cc: 0.0.6 => 0.0.10
- rules_java: 5.4.1 => 7.9.0
- rules_proto: 5.3.0-21.7 => 6.0.2

Dev dependencies in `WORKSPACE`:

- com_google_protobuf: 28.2
- rules_pkg: 1.0.1
- rules_jvm_external: 6.4
- com_google_absl: abseil-cpp-20240722.0
- zlib: 1.3.1

Of all of the new, explicit dev dependencies, only `com_google_protobuf`
will be necessary to include in `MODULE.bazel`. The Bzlmod mechanism
will discover these other transitive dev dependencies automatically.

Also removed the `rules_java_extra` repo from `WORKSPACE`, which
appeared unused.

---

Though the current `rules_java` version is 7.12.1, and largely works
with this repo, it requires a few temporary workarounds. Rather than
commit the workarounds, upgrading only to 7.9.0 now seems less crufty.

What follows is a very detailed explanation of what happens with 7.12.1
with Bazel 7.3.2, just to have it on the record.

---

The workaround is to change a few toolchain and macro file targets from
`@bazel_tools//tools/jdk:` to `@rules_java//toolchains:`. This isn't a
terribly bad or invasive workaround, but `@bazel_tools//tools/jdk:` is
clearly the canonical path. Best to keep it that way, lest we build up
technical debt.

Without the workaround, these targets would fail:

- //test/src/main/resources/java_sources:CompiledWithJava11
- //test/src/main/resources/java_sources:CompiledWithJava8
- //test/toolchains:java21_toolchain
- //test:JunitRuntimePlatform
- //test:JunitRuntimePlatform_test_runner
- //test:scala_binary_jdk_11

with this error:

```txt
ERROR: .../external/rules_java_builtin/toolchains/BUILD:254:14:

While resolving toolchains for target
@@rules_java_builtin//toolchains:platformclasspath (096dcc8):

No matching toolchains found for types
@@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type.
```

This appears to be a consequence of both upgrading the Bazel version
from 6.3.0 to 7.3.2 and updating `rules_java` to 7.12.1. The
`rules_java_builtin` repo is part of the `WORKSPACE` prefix that adds
implicit dependencies:

- https://bazel.build/external/migration#builtin-default-deps

This repo was added to 7.0.0-pre.20231011.2 in the following change,
mapped to `@rules_java` within the scope of the `@bazel_tools` repo:

- bazelbuild/bazel: Add rules_java_builtin to the users of Java modules
  bazelbuild/bazel@ff1abb2

This change tried to ensure `rules_java` remained compatible with
earlier Bazel versions. However, it changed all instances of
`@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type` to
`//toolchains:bootstrap_runtime_toolchain_type`:

- bazelbuild/rules_java: Make rules_java backwards compatible with Bazel
  6.3.0
  bazelbuild/rules_java@30ecf3f

Bazel has bumped `rules_java` in its `workspace_deps.bzl` from 7.9.0 to
7.11.0, but it's only available as of 8.0.0-pre.20240911.1.

- bazelbuild/bazel: Update rules_java 7.11.1 / java_tools 13.8
  bazelbuild/bazel#23571
  bazelbuild/bazel@f92124a

---

What I believe is happening is, under Bazel 7.3.2 and `rules_java`
7.12.1:

- Bazel creates `rules_java` 7.9.0 as `@rules_java_builtin` in the
  `WORKSPACE` prefix.

- `@bazel_tools` has `@rules_java` mapped to `@rules_java_builtin` when
  initialized during the `WORKSPACE` prefix, during which
  `@bazel_tools//tools/jdk` registers `alias()` targets to
  `@rules_java` toolchain targets. These aliased toolchains specify
  `@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type` in their
  `toolchains` attribute.

- `WORKSPACE` loads `@rules_java` 7.12.1 and registers all its
  toolchains with type
  `@rules_java//toolchains:bootstrap_runtime_toolchain_type`.

- Some `@rules_java` rules explicitly specifying toolchains from
  `@bazel_tools//tools/jdk` can't find them, because the
  `@bazel_tools//tools/jdk` toolchain aliases expect toolchains of type
  `@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type`.

This has broken other projects in the same way:

- bazelbuild/bazel: [Bazel CI] Downstream project broken by rules_java
  upgrade #23619
  bazelbuild/bazel#23619

These problems don't appear under Bzlmod, and `@rules_java_builtin` was
never required. This is because `WORKSPACE` executes its statements
sequentially, while Bzlmod builds the module dependency graph _before_
instantiating repositories (within module extensions).

It seems a fix is on the way that removes `@rules_java_builtin` from the
`WORKSPACE` prefix, and adds `@rules_java` to the suffix. At this
moment, though, it's not even in a prerelase:

- bazelbuild/bazel: Remove rules_java_builtin in WORKSPACE prefix
  bazelbuild/bazel@7506690

---

Note that the error message matches that from the following resolved
issue, but that issue was for non-Bzlmod child repos when `WORKSPACE`
was disabled.

- bazelbuild/bazel: Undefined @@rules_java_builtin repository with
  --noenable_workspace option
  bazelbuild/bazel#22754
mbland added a commit to mbland/rules_scala that referenced this issue Oct 5, 2024
Related to bazelbuild#1482, bazelbuild#1618, and bazelbuild#1619. Results from the investigation
documented at:

- bazelbuild#1619 (comment)

Updates `_import_paths()` in `scala_proto_aspect.bzl` to handle
differences `ProtoInfo.proto_source_root` and `ProtoInfo.direct_sources`
values between Bazel 6 and Bazel 7.

Without this change, `_import_paths()` emits incorrect values under
Bazel 7, causing targets containing generated `.proto` inputs to fail,
e.g.  `//test/proto3:test_generated_proto`.

See also:

- Fix paths for sibling repository setup and generated .proto files
  bazelbuild/bazel@6c6c196

- The docstring for `ProtoInfo.proto_source_root` in the Bazel sources:
  https://github.com/bazelbuild/bazel/blob/7.3.2/src/main/starlark/builtins_bzl/common/proto/proto_info.bzl#L155-L172

- Remove incompatible_generated_protos_in_virtual_imports
  bazelbuild/bazel@3efaa32

- Comment from: Generated Protos are no longer considered as
  virtual_imports in Bazel 7
  bazelbuild/bazel#21075 (comment)

---

I cherrypicked this commit into bazelbuild#1618. While it fixed the
`//test/proto3` build failure, it does _not_ fix the hanging
scalapb_workers from the ProtoScalaPBRule aspect.

I'll have to investiate further whether than hang is related to Bazel,
rules_proto, com_google_protobuf, or some mixture thereof. Still,
progress!
mbland added a commit to mbland/rules_scala that referenced this issue Oct 5, 2024
Related to bazelbuild#1482, bazelbuild#1618, and bazelbuild#1619. Results from the investigation
documented at:

- bazelbuild#1619 (comment)

Updates `_import_paths()` in `scala_proto_aspect.bzl` to handle
differences `ProtoInfo.proto_source_root` and `ProtoInfo.direct_sources`
values between Bazel 6 and Bazel 7.

Without this change, `_import_paths()` emits incorrect values under
Bazel 7, causing targets containing generated `.proto` inputs to fail,
e.g.  `//test/proto3:test_generated_proto`.

See also:

- Fix paths for sibling repository setup and generated .proto files
  bazelbuild/bazel@6c6c196

- The docstring for `ProtoInfo.proto_source_root` in the Bazel sources:
  https://github.com/bazelbuild/bazel/blob/7.3.2/src/main/starlark/builtins_bzl/common/proto/proto_info.bzl#L155-L172

- Remove incompatible_generated_protos_in_virtual_imports
  bazelbuild/bazel@3efaa32

- Comment from: Generated Protos are no longer considered as
  virtual_imports in Bazel 7
  bazelbuild/bazel#21075 (comment)

---

I cherrypicked this commit into bazelbuild#1618. While it fixed the
`//test/proto3` build failure, it does _not_ fix the hanging
scalapb_workers from the ProtoScalaPBRule aspect.

I'll have to investiate further whether than hang is related to Bazel,
rules_proto, com_google_protobuf, or some mixture thereof. Still,
progress!
mbland added a commit to mbland/rules_scala that referenced this issue Oct 6, 2024
Related to bazelbuild#1482, bazelbuild#1618, and bazelbuild#1619. Results from the investigation
documented at:

- bazelbuild#1619 (comment)

Updates `_import_paths()` in `scala_proto_aspect.bzl` to handle
differences `ProtoInfo.proto_source_root` and `ProtoInfo.direct_sources`
values between Bazel 6 and Bazel 7.

Without this change, `_import_paths()` emits incorrect values under
Bazel 7, causing targets containing generated `.proto` inputs to fail,
e.g.  `//test/proto3:test_generated_proto`.

See also:

- Fix paths for sibling repository setup and generated .proto files
  bazelbuild/bazel@6c6c196

- The docstring for `ProtoInfo.proto_source_root` in the Bazel sources:
  https://github.com/bazelbuild/bazel/blob/7.3.2/src/main/starlark/builtins_bzl/common/proto/proto_info.bzl#L155-L172

- Remove incompatible_generated_protos_in_virtual_imports
  bazelbuild/bazel@3efaa32

- Comment from: Generated Protos are no longer considered as
  virtual_imports in Bazel 7
  bazelbuild/bazel#21075 (comment)

---

I cherrypicked this commit into bazelbuild#1618. While it fixed the
`//test/proto3` build failure, it does _not_ fix the hanging
scalapb_workers from the ProtoScalaPBRule aspect.

I'll have to investiate further whether than hang is related to Bazel,
rules_proto, com_google_protobuf, or some mixture thereof. Still,
progress!
mbland added a commit to mbland/rules_scala that referenced this issue Oct 7, 2024
Related to bazelbuild#1482, bazelbuild#1618, and bazelbuild#1619. Results from the investigation
documented at:

- bazelbuild#1619 (comment)

Updates `_import_paths()` in `scala_proto_aspect.bzl` to handle
differences `ProtoInfo.proto_source_root` and `ProtoInfo.direct_sources`
values between Bazel 6 and Bazel 7.

Without this change, `_import_paths()` emits incorrect values under
Bazel 7, causing targets containing generated `.proto` inputs to fail,
e.g.  `//test/proto3:test_generated_proto`.

See also:

- Fix paths for sibling repository setup and generated .proto files
  bazelbuild/bazel@6c6c196

- The docstring for `ProtoInfo.proto_source_root` in the Bazel sources:
  https://github.com/bazelbuild/bazel/blob/7.3.2/src/main/starlark/builtins_bzl/common/proto/proto_info.bzl#L155-L172

- Remove incompatible_generated_protos_in_virtual_imports
  bazelbuild/bazel@3efaa32

- Comment from: Generated Protos are no longer considered as
  virtual_imports in Bazel 7
  bazelbuild/bazel#21075 (comment)

---

I cherrypicked this commit into bazelbuild#1618. While it fixed the
`//test/proto3` build failure, it does _not_ fix the hanging
scalapb_workers from the ProtoScalaPBRule aspect.

I'll have to investiate further whether than hang is related to Bazel,
rules_proto, com_google_protobuf, or some mixture thereof. Still,
progress!
mbland added a commit to mbland/rules_scala that referenced this issue Oct 7, 2024
Part of bazelbuild#1482.

Splits the last component off of canonical repo names to produce the
expected repo name.

Without Bzlmod, it returns the original name. With Bzlmod enabled, it
avoids generating output like:

    scala_import(
        name = "_main~scala_deps~io_bazel_rules_scala_scala_compiler",
        jars = ["scala-compiler-2.12.18.jar"],
    )

resulting in errors like:

```
ERROR: .../_main~_repo_rules~io_bazel_rules_scala/scala/BUILD:
no such target '@@_main~scala_deps~io_bazel_rules_scala_scala_compiler//:io_bazel_rules_scala_scala_compiler':
target 'io_bazel_rules_scala_scala_compiler' not declared in package ''
defined by .../_main~scala_deps~io_bazel_rules_scala_scala_compiler/BUILD
and referenced by '@@_main~_repo_rules~io_bazel_rules_scala//scala:default_toolchain_scala_compile_classpath_provider'
```

Also fixes the following error when attaching resources from custom repos to
targets under Bzlmod:

```txt
$ bazel test //test/src/main/scala/scalarules/test/resources:all

1) Scala library depending on resources from external resource-only
  jar::allow to load resources(scalarules.test.resources.ScalaLibResourcesFromExternalDepTest)
  java.lang.NullPointerException
    at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.get(ScalaLibResourcesFromExternalDepTest.scala:17)
    at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.$anonfun$new$3(ScalaLibResourcesFromExternalDepTest.scala:11)
    at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.$anonfun$new$2(ScalaLibResourcesFromExternalDepTest.scala:11)
```

Can be replaced with a future bazel-skylib implementation, if accepted
into that repo.

---

We can't rely on the specific canonical repository name format:

> Repos generated by extensions have canonical names in the form of
> `module_repo_canonical_name+extension_name+repo_name`. For extensions
> hosted in the root module, the `module_repo_canonical_name` part is
> replaced with the string `_main`. Note that the canonical name format is
> not an API you should depend on — it's subject to change at any time.
>
> - https://bazel.build/external/extension#repository_names_and_visibility

The change to no longer encode module versions in canonical repo names in
Bazel 7.1.0 is a recent example of Bazel maintainers altering the format:

- bazelbuild/bazel#21316

And the maintainers recently replaced the `~` delimiter with `+` in the
upcoming Bazel 8 release due to build performance issues on Windows:

- bazelbuild/bazel#22865

This function assumes the only valid `repo_name` characters are letters,
numbers, '_', '-', and '.'. It finds the last character not in this set, and
returns the contents of `name` following this character. This is valid so
long as this condition holds:

- https://github.com/bazelbuild/bazel/blob/7.3.2/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryName.java#L159-L162
mbland added a commit to mbland/rules_scala that referenced this issue Oct 7, 2024
Part of bazelbuild#1482.

Splits the last component off of canonical repo names to produce the
expected repo name.

Without Bzlmod, it returns the original name. With Bzlmod enabled, it
avoids generating output like:

    scala_import(
        name = "_main~scala_deps~io_bazel_rules_scala_scala_compiler",
        jars = ["scala-compiler-2.12.18.jar"],
    )

resulting in errors like:

```
ERROR: .../_main~_repo_rules~io_bazel_rules_scala/scala/BUILD:
no such target '@@_main~scala_deps~io_bazel_rules_scala_scala_compiler//:io_bazel_rules_scala_scala_compiler':
target 'io_bazel_rules_scala_scala_compiler' not declared in package ''
defined by .../_main~scala_deps~io_bazel_rules_scala_scala_compiler/BUILD
and referenced by '@@_main~_repo_rules~io_bazel_rules_scala//scala:default_toolchain_scala_compile_classpath_provider'
```

Also fixes the following error when attaching resources from custom repos to
targets under Bzlmod:

```txt
$ bazel test //test/src/main/scala/scalarules/test/resources:all

1) Scala library depending on resources from external resource-only
  jar::allow to load resources(scalarules.test.resources.ScalaLibResourcesFromExternalDepTest)
  java.lang.NullPointerException
    at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.get(ScalaLibResourcesFromExternalDepTest.scala:17)
    at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.$anonfun$new$3(ScalaLibResourcesFromExternalDepTest.scala:11)
    at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.$anonfun$new$2(ScalaLibResourcesFromExternalDepTest.scala:11)
```

Can be replaced with a future bazel-skylib implementation, if accepted
into that repo.

---

We can't rely on the specific canonical repository name format:

> Repos generated by extensions have canonical names in the form of
> `module_repo_canonical_name+extension_name+repo_name`. For extensions
> hosted in the root module, the `module_repo_canonical_name` part is
> replaced with the string `_main`. Note that the canonical name format is
> not an API you should depend on — it's subject to change at any time.
>
> - https://bazel.build/external/extension#repository_names_and_visibility

The change to no longer encode module versions in canonical repo names in
Bazel 7.1.0 is a recent example of Bazel maintainers altering the format:

- bazelbuild/bazel#21316

And the maintainers recently replaced the `~` delimiter with `+` in the
upcoming Bazel 8 release due to build performance issues on Windows:

- bazelbuild/bazel#22865

This function assumes the only valid `repo_name` characters are letters,
numbers, '_', '-', and '.'. It finds the last character not in this set, and
returns the contents of `name` following this character. This is valid so
long as this condition holds:

- https://github.com/bazelbuild/bazel/blob/7.3.2/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryName.java#L159-L162
liucijus pushed a commit that referenced this issue Oct 8, 2024
Related to #1482, #1618, and #1619. Results from the investigation
documented at:

- #1619 (comment)

Updates `_import_paths()` in `scala_proto_aspect.bzl` to handle
differences `ProtoInfo.proto_source_root` and `ProtoInfo.direct_sources`
values between Bazel 6 and Bazel 7.

Without this change, `_import_paths()` emits incorrect values under
Bazel 7, causing targets containing generated `.proto` inputs to fail,
e.g.  `//test/proto3:test_generated_proto`.

See also:

- Fix paths for sibling repository setup and generated .proto files
  bazelbuild/bazel@6c6c196

- The docstring for `ProtoInfo.proto_source_root` in the Bazel sources:
  https://github.com/bazelbuild/bazel/blob/7.3.2/src/main/starlark/builtins_bzl/common/proto/proto_info.bzl#L155-L172

- Remove incompatible_generated_protos_in_virtual_imports
  bazelbuild/bazel@3efaa32

- Comment from: Generated Protos are no longer considered as
  virtual_imports in Bazel 7
  bazelbuild/bazel#21075 (comment)

---

I cherrypicked this commit into #1618. While it fixed the
`//test/proto3` build failure, it does _not_ fix the hanging
scalapb_workers from the ProtoScalaPBRule aspect.

I'll have to investiate further whether than hang is related to Bazel,
rules_proto, com_google_protobuf, or some mixture thereof. Still,
progress!
@simuons simuons reopened this Oct 8, 2024
mbland added a commit to mbland/rules_scala that referenced this issue Oct 8, 2024
Part of bazelbuild#1482.

Splits the last component off of canonical repo names to produce the
expected repo name.

Without Bzlmod, it returns the original name. With Bzlmod enabled, it
avoids generating output like:

    scala_import(
        name = "_main~scala_deps~io_bazel_rules_scala_scala_compiler",
        jars = ["scala-compiler-2.12.18.jar"],
    )

resulting in errors like:

```
ERROR: .../_main~_repo_rules~io_bazel_rules_scala/scala/BUILD:
no such target '@@_main~scala_deps~io_bazel_rules_scala_scala_compiler//:io_bazel_rules_scala_scala_compiler':
target 'io_bazel_rules_scala_scala_compiler' not declared in package ''
defined by .../_main~scala_deps~io_bazel_rules_scala_scala_compiler/BUILD
and referenced by '@@_main~_repo_rules~io_bazel_rules_scala//scala:default_toolchain_scala_compile_classpath_provider'
```

Also fixes the following error when attaching resources from custom repos to
targets under Bzlmod:

```txt
$ bazel test //test/src/main/scala/scalarules/test/resources:all

1) Scala library depending on resources from external resource-only
  jar::allow to load resources(scalarules.test.resources.ScalaLibResourcesFromExternalDepTest)
  java.lang.NullPointerException
    at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.get(ScalaLibResourcesFromExternalDepTest.scala:17)
    at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.$anonfun$new$3(ScalaLibResourcesFromExternalDepTest.scala:11)
    at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.$anonfun$new$2(ScalaLibResourcesFromExternalDepTest.scala:11)
```

Can be replaced with a future bazel-skylib implementation, if accepted
into that repo.

---

We can't rely on the specific canonical repository name format:

> Repos generated by extensions have canonical names in the form of
> `module_repo_canonical_name+extension_name+repo_name`. For extensions
> hosted in the root module, the `module_repo_canonical_name` part is
> replaced with the string `_main`. Note that the canonical name format is
> not an API you should depend on — it's subject to change at any time.
>
> - https://bazel.build/external/extension#repository_names_and_visibility

The change to no longer encode module versions in canonical repo names in
Bazel 7.1.0 is a recent example of Bazel maintainers altering the format:

- bazelbuild/bazel#21316

And the maintainers recently replaced the `~` delimiter with `+` in the
upcoming Bazel 8 release due to build performance issues on Windows:

- bazelbuild/bazel#22865

This function assumes the only valid `repo_name` characters are letters,
numbers, '_', '-', and '.'. It finds the last character not in this set, and
returns the contents of `name` following this character. This is valid so
long as this condition holds:

- https://github.com/bazelbuild/bazel/blob/7.3.2/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryName.java#L159-L162
@mbland
Copy link
Contributor

mbland commented Oct 11, 2024

A quick update for visibility: I'm very close to having the Bzlmodified rules_scala passing 100% of the tests, down to the last couple of failures:

  • I need to replace the bind() calls from twitter_scrooge with alias() or some such to get test_version.sh to pass.
  • I need to fix the Scala 3.1.2 and Scala 3.3.3 failures for the Scalafmt targets from test/shell/test_cross_build.sh (corresponding to the test3 and library3 test cases in test_scalafmt()).

I also need to get test_lint.sh working again, and update the dt_patches repos for Bzlmod. But the following all pass:

  • test_rules_scala.sh
  • test_reproducibility.sh
  • test_examples.sh
  • test_coverage.sh

Hopefully I can get these fixed up today, and I'll start peeling off the next pull request or two. And thanks to @simuons and @liucijus for reviewing and merging #1619 and #1620 already.

mbland added a commit to mbland/rules_scala that referenced this issue Feb 19, 2025
It seems the README won't expand refs like bazelbuild#1482. This updates such refs
to use the repo prefix, e.g., bazelbuild#1482.
mbland added a commit to mbland/rules_scala that referenced this issue Feb 19, 2025
Fulfills most of bazelbuild#1482. Compatible with Bazel 6.5.0 and 7.5.0, but not
Bazel 8.

New `MODULE.bazel` files mirroring existing `WORKSPACE` configurations
comprise the bulk of the commit. The empty `WORKSPACE.bzlmod` files
ensure that Bzlmod won't evaluate the existing `WORKSPACE` files.

These new files comprise the most significant part of the change:

- scala/extensions/config.bzl
- scala/extensions/deps.bzl
- scala/private/extensions/dev_deps.bzl
- scala/private/macros/bzlmod.bzl

The first three files above are already thoroughly tested by existing
tests now that `MODULE.bazel` files are in place. The following files
thoroughly test the helpers from `scala/private/macros/bzlmod.bzl` in
specifically:

- scala/private/macros/test/BUILD.bzlmod_test
- scala/private/macros/test/MODULE.bzlmod_test
- scala/private/macros/test/bzlmod_test_ext.bzl
- test/shell/test_bzlmod_macros.sh

The pattern employed throughout the new module extensions is explained
in the `scala/private/macros/bzlmod.bzl` docstring. Adding
`test/shell/test_bzlmod_macros.sh` also precipitated adding a new
`assert_matches` helper to `test/shell/test_helper.sh`.

"Publish to BCR" configuration in the `.bcr` directory comes from:

- https://github.com/bazel-contrib/publish-to-bcr/tree/main/templates

The bazel-contrib/publish-to-bcr README contains further guidance on
configuring the app. Once that's done, we can use the app to publish a
new version to https://registry.bazel.build/ and then close bazelbuild#1482.

Per bazelbuild#1647, `com_google_protobuf` remains at v21.7, and versions up to
v25.5 can work after bumping `com_google_absl` to 20240722.0 and setting
C++17 compiler flags in `.bazelrc`.

This change enables Bazel 6 and 7 users to migrate their `rules_scala`
dependency from `WORKSPACE` to `MODULE.bazel` whenever they're ready.

After the next major version release includes this change, we can update
`com_google_protobuf`, `rules_java`, and related dependencies as part of
enabling Bazel 8 compatibility (bazelbuild#1652). The `rules_jvm_external` update
in that change will effectively end Bzlmod support for Bazel 6.5.0,
requiring another major version release after that.
mbland added a commit to mbland/rules_scala that referenced this issue Feb 20, 2025
Fulfills most of bazelbuild#1482. Compatible with Bazel 6.5.0 and 7.5.0, but not
Bazel 8.

New `MODULE.bazel` files mirroring existing `WORKSPACE` configurations
comprise the bulk of the commit. The empty `WORKSPACE.bzlmod` files
ensure that Bzlmod won't evaluate the existing `WORKSPACE` files.

These new files comprise the most significant part of the change:

- scala/extensions/config.bzl
- scala/extensions/deps.bzl
- scala/private/extensions/dev_deps.bzl
- scala/private/macros/bzlmod.bzl

The first three files above are already thoroughly tested by existing
tests now that `MODULE.bazel` files are in place. The following files
thoroughly test the helpers from `scala/private/macros/bzlmod.bzl` in
specifically:

- scala/private/macros/test/BUILD.bzlmod_test
- scala/private/macros/test/MODULE.bzlmod_test
- scala/private/macros/test/bzlmod_test_ext.bzl
- test/shell/test_bzlmod_macros.sh

The pattern employed throughout the new module extensions is explained
in the `scala/private/macros/bzlmod.bzl` docstring. Adding
`test/shell/test_bzlmod_macros.sh` also precipitated adding a new
`assert_matches` helper to `test/shell/test_helper.sh`.

"Publish to BCR" configuration in the `.bcr` directory comes from:

- https://github.com/bazel-contrib/publish-to-bcr/tree/main/templates

The bazel-contrib/publish-to-bcr README contains further guidance on
configuring the app. Once that's done, we can use the app to publish a
new version to https://registry.bazel.build/ and then close bazelbuild#1482.

Per bazelbuild#1647, `com_google_protobuf` remains at v21.7, and versions up to
v25.5 can work after bumping `com_google_absl` to 20240722.0 and setting
C++17 compiler flags in `.bazelrc`.

This change enables Bazel 6 and 7 users to migrate their `rules_scala`
dependency from `WORKSPACE` to `MODULE.bazel` whenever they're ready.

After the next major version release includes this change, we can update
`com_google_protobuf`, `rules_java`, and related dependencies as part of
enabling Bazel 8 compatibility (bazelbuild#1652). The `rules_jvm_external` update
in that change will effectively end Bzlmod support for Bazel 6.5.0,
requiring another major version release after that.
@mbland
Copy link
Contributor

mbland commented Feb 20, 2025

I've clearly been slacking on the weekly updates, but not on the actual work. 😉

Overview

Toolchainization is done! Now #1703 is out to document all the changes. It adds the new scala_toolchains() API documentation to the README and removes all the macros replaced by it. It also touches up all the docs to various degrees.

And after that pull request lands, the final Bzlmodification pull request awaits in my (new!) bzlmod-enable branch in mbland/rules_scala. (This is not the same as the existing bzlmod branch, though I used bzlmod as the starting point, and have merged bzlmod-enable back into it.)

Here's how I anticipate things going from here:

Merged

Open

Documentation review requested!

I'd appreciate it if anyone interested could take a look at the updated README in #1703 and comment on the pull request. Go to "Files changed" and use "View file" to see the new version fully rendered. I'd like to know whether the documentation on the new API, breaking changes, etc. makes sense, or if it can be improved in specific areas.

Bazel Central Registry publishing

@Wyverald asked privately whether we could post a preliminary version of the Bzlmodified rules_scala on the BCR for super early adopters. I ultimately defer to @simuons and @liucijus whether we should do this, or just wait for Bzlmodification to land.

If they give me the green light, I'd be happy to file a pull request to add a prerelease to the BCR. That said, bzlmod-enable already contains the Publish to BCR app template files. @simuons or @liucijus would have to set up the app per the Publish to BCR app instructions before cutting the release.

Trying Bzlmod before the BCR release via git_override()

As I've mentioned before, anyone can try my bzlmod and bzlmod-bazel-8 branches. I've been updating them and making sure they pass all tests for various Bazel/WORKSPACE/Bzlmod configurations. (The new bzlmod-enable branch is not guaranteed to remain stable; please don't depend on it!)

For examples, see:

That said, I last updated those branches this past Sunday, 2025-02-16. I plan to merge the latest changes, test them locally, and push updates to both by later today. (Look at the latest commit to see if I've done so yet.)

When to release 7.0.0?

There's some discussion in #1699 regarding when to release 7.0.0 and what to include. As always, @simuons and @liucijus have the ultimate say here, but I'm ready for either of the following, once #1703 lands:

  • Releasing 7.0.0 without Bzlmod, so folks can migrate to scala_toolchains() and pick up other improvements right away, followed by 7.1.0 once the Bzlmodification changes land. This prioritizes releasing all the changes since v6.6.0 (2024-07-31) as soon as possible.

  • Waiting for the Bzlmod changes to land before releasing 7.0.0. This prioritizes making a single release, though it will take extra time for the Bzlmodification pull request review.

The scala_toolchains() interface is very similar to the upcoming scala_deps module extension, so migrating to scala_toolchains() should introduce hardly any friction later. In fact, scala_deps basically collects information from its tag class instances to make a call to scala_toolchains() under the hood.

I honestly don't have a preference. It's totally up to whatever the maintainers decide.

Trying out Stardoc

I created bzlmod-enable from bzlmod so I could clean up, refactor, test, and document its module extension implementations in a single, fresh commit. After having done so, I'm now looking forward to experimenting with the Stardoc documentation generator.

If this experiment works out, including the stardoc Bazel module in MODULE.bazel will likely land in rules_scala 8.0.0, not 7.x. This is because the stardoc Bazel module requires Bazel 7 and above. Since rules_scala 7.x will maintain Bzlmod compatibility with Bazel 6.5.0, we can't include it in the 7.x MODULE.bazel file, not even as a dev_dependency.

The good news is, rules_scala 8.0.0 should be ready rather shortly after we release 7.x with Bzlmod, so the wait wouldn't be for long. (8.0.0 will drop Bzlmod support for Bazel 6.5.0.)

@dmivankov
Copy link
Contributor

Looks like it doesn't yet resolve #1440
What's the bzlmod equivalent for rules_scala_toolchain_deps_repositories(overriden_artifacts=...)?

mbland added a commit to mbland/rules_scala that referenced this issue Feb 21, 2025
Explicitly notes that some `rules_scala` APIs may break, specifically
`setup_scala_toolchain`. Part of bazelbuild#1482.

Brought to my attention by @michalbogacz in a `#scala` thread in the
Bazel Slack workspace, which was in the context of
michalbogacz/scala-bazel-monorepo#26.

- https://bazelbuild.slack.com/archives/CDCKJ2KFZ/p1740144886159909
@mbland
Copy link
Contributor

mbland commented Feb 21, 2025

Last things first: Under Bzlmod, the equivalent of overriden_artifacts is overridden_artifacts (notice the new dd instead of the single d):

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

scala_deps.settings(overridden_artifacts = ...)

Under WORKSPACE:

load(
    "@rules_scala//scala/toolchains.bzl",
    "scala_register_toolchains",
    "scala_toolchains",
)

scala_toolchains(overridden_artifacts = ...)

Regarding #1440, I've done a lot of builds on my own machine, but I don't appear to have any sign of 2.13.6 lingering. But if I had to guess, this is because rules_scala defines a particular patch release for each major version at the top of its third_party/repositories/scala_*.bzl files. If you specify a different scala_version, you'll need to provide those overridden_artifacts yourself, as in #1440 (comment).

I'll add this to #1440 as well.

$ pushd "$(bazel info output_base)/external"

$ find *io_bazel_rules_scala_scala_library* -name '*.jar' 
+scala_deps+io_bazel_rules_scala_scala_library_2_12_20/scala-library-2.12.20-src.jar
+scala_deps+io_bazel_rules_scala_scala_library_2_12_20/scala-library-2.12.20.jar
+scala_deps+io_bazel_rules_scala_scala_library_2_13_15/scala-library-2.13.16.jar
+scala_deps+io_bazel_rules_scala_scala_library_2_13_15/scala-library-2.13.16-src.jar
+scala_deps+io_bazel_rules_scala_scala_library_2_3_1_3/scala-library-2.13.16.jar
+scala_deps+io_bazel_rules_scala_scala_library_2_3_1_3/scala-library-2.13.16-src.jar
+scala_deps+io_bazel_rules_scala_scala_library_2_3_3_5/scala-library-2.13.16.jar
+scala_deps+io_bazel_rules_scala_scala_library_2_3_3_5/scala-library-2.13.16-src.jar
+scala_deps+io_bazel_rules_scala_scala_library_2_3_6_3/scala-library-2.13.16.jar
+scala_deps+io_bazel_rules_scala_scala_library_2_3_6_3/scala-library-2.13.16-src.jar
+scala_deps+io_bazel_rules_scala_scala_library_3_1_3/scala3-library_3-3.1.3-src.jar
+scala_deps+io_bazel_rules_scala_scala_library_3_1_3/scala3-library_3-3.1.3.jar
+scala_deps+io_bazel_rules_scala_scala_library_3_3_5/scala3-library_3-3.3.5-src.jar
+scala_deps+io_bazel_rules_scala_scala_library_3_3_5/scala3-library_3-3.3.5.jar
+scala_deps+io_bazel_rules_scala_scala_library_3_6_3/scala3-library_3-3.6.3-src.jar
+scala_deps+io_bazel_rules_scala_scala_library_3_6_3/scala3-library_3-3.6.3.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_11_12/scala-library-2.11.12.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_11_12/scala-library-2.11.12-src.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_12_20/scala-library-2.12.20-src.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_12_20/scala-library-2.12.20.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_13_15/scala-library-2.13.16.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_13_15/scala-library-2.13.16-src.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_3_1_3/scala-library-2.13.16.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_3_1_3/scala-library-2.13.16-src.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_3_3_5/scala-library-2.13.16.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_3_3_5/scala-library-2.13.16-src.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_3_6_3/scala-library-2.13.16.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_2_3_6_3/scala-library-2.13.16-src.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_3_1_3/scala3-library_3-3.1.3-src.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_3_1_3/scala3-library_3-3.1.3.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_3_3_5/scala3-library_3-3.3.5-src.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_3_3_5/scala3-library_3-3.3.5.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_3_6_3/scala3-library_3-3.6.3-src.jar
_main~scala_deps~io_bazel_rules_scala_scala_library_3_6_3/scala3-library_3-3.6.3.jar
io_bazel_rules_scala_scala_library_2_12_20/scala-library-2.12.20-src.jar
io_bazel_rules_scala_scala_library_2_12_20/scala-library-2.12.20.jar
io_bazel_rules_scala_scala_library_2_13_15/scala-library-2.13.16.jar
io_bazel_rules_scala_scala_library_2_13_15/scala-library-2.13.16-src.jar
io_bazel_rules_scala_scala_library_2_3_1_3/scala-library-2.13.16.jar
io_bazel_rules_scala_scala_library_2_3_1_3/scala-library-2.13.16-src.jar
io_bazel_rules_scala_scala_library_2_3_3_5/scala-library-2.13.16.jar
io_bazel_rules_scala_scala_library_2_3_3_5/scala-library-2.13.16-src.jar
io_bazel_rules_scala_scala_library_2_3_6_3/scala-library-2.13.16.jar
io_bazel_rules_scala_scala_library_2_3_6_3/scala-library-2.13.16-src.jar
io_bazel_rules_scala_scala_library_3_1_3/scala3-library_3-3.1.3-src.jar
io_bazel_rules_scala_scala_library_3_1_3/scala3-library_3-3.1.3.jar
io_bazel_rules_scala_scala_library_3_3_5/scala3-library_3-3.3.5-src.jar
io_bazel_rules_scala_scala_library_3_3_5/scala3-library_3-3.3.5.jar
io_bazel_rules_scala_scala_library_3_6_3/scala3-library_3-3.6.3-src.jar
io_bazel_rules_scala_scala_library_3_6_3/scala3-library_3-3.6.3.jar

(As for why io_bazel_rules_scala_scala_library_2_13_15 shows scala-library-2.13.16.jar, apparently I accidentally bumped it as part of #1692. D'oh! All the more reason to merge #1700.)

@dmivankov
Copy link
Contributor

Thanks, I was trying scala_deps.toolchains( first, with

scala_deps.settings(
    overridden_artifacts = {
        "io_bazel_rules_scala_scala_library": {
           "artifact": "org.scala-lang:scala3-library_3:%s" % scala_version,
            "sha256": "26163f54674adb4c3e2151155f7f6f17095a0be10ebfb884ee8cdca98adca248",
        },
        "io_bazel_rules_scala_scala_compiler": {
            "artifact": "org.scala-lang:scala3-compiler_3:%s" % scala_version,
            "sha256": "f067da9a52ec450efa5d1cc1a3325b7f9882874a059b11728969460d170ed424",
        },
        "io_bazel_rules_scala_scala_library_2": {
            "artifact": "org.scala-lang:scala-library:2.13.15",
            "sha256": "8e4dbc3becf70d59c787118f6ad06fab6790136a0699cd6412bc9da3d336944e",
        },
    },
)

I get

(09:30:43) ERROR: Analysis of target ... failed; build aborted: in tag at .../MODULE.bazel:104:20, error converting value for attribute overridden_artifacts: expected value of type 'string' for dict value element, but got {"artifact": "org.scala-lang:scala3-library_3:3.3.5", "sha256": "26163f54674adb4c3e2151155f7f6f17095a0be10ebfb884ee8cdca98adca248"} (dict)

So either need to find a way to encode it into strings/list of strings, or a better-suiting bzlmod way of providing compiler.

Context is by the way trying to set scala_version = "3.3.5". Out of the box build fails with

...
  exception occurred while typechecking ...Something.scala

  An unhandled exception was thrown in the compiler.
  Please file a crash report here:
  https://github.com/lampepfl/dotty/issues/new/choose
  For non-enriched exceptions, compile with -Yno-enrich-error-messages.

     while compiling: ...Something.scala
        during phase: typer
                mode: Mode(ImplicitsEnabled)
     library version: version 2.13.16
    compiler version: version 3.3.5
...
Exception in thread "main" java.lang.AssertionError: assertion failed: failure to resolve inner class:
externalName = com.google.protobuf.Descriptors$EnumDescriptor,
outerName = com.google.protobuf.Descriptors,
innerName = EnumDescriptor
owner.fullName = com.google.protobuf.Descriptors
while parsing bazel-out/k8-fastbuild/bin/external/rules_jvm_external++maven+maven/com/google/cloud/google-cloud-spanner/6.86.0/header_google-cloud-spanner-6.86.0.jar(com/google/cloud/spanner/ValueBinder.class)
	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
...

which I didn't try to minimize yet

@mbland
Copy link
Contributor

mbland commented Feb 22, 2025

Thanks, I was trying scala_deps.toolchains( first, with

scala_deps.settings(
    overridden_artifacts = {
        "io_bazel_rules_scala_scala_library": {
           "artifact": "org.scala-lang:scala3-library_3:%s" % scala_version,
            "sha256": "26163f54674adb4c3e2151155f7f6f17095a0be10ebfb884ee8cdca98adca248",
        },
        "io_bazel_rules_scala_scala_compiler": {
            "artifact": "org.scala-lang:scala3-compiler_3:%s" % scala_version,
            "sha256": "f067da9a52ec450efa5d1cc1a3325b7f9882874a059b11728969460d170ed424",
        },
        "io_bazel_rules_scala_scala_library_2": {
            "artifact": "org.scala-lang:scala-library:2.13.15",
            "sha256": "8e4dbc3becf70d59c787118f6ad06fab6790136a0699cd6412bc9da3d336944e",
        },
    },
)

I get

(09:30:43) ERROR: Analysis of target ... failed; build aborted: in tag at .../MODULE.bazel:104:20, error converting value for attribute overridden_artifacts: expected value of type 'string' for dict value element, but got {"artifact": "org.scala-lang:scala3-library_3:3.3.5", "sha256": "26163f54674adb4c3e2151155f7f6f17095a0be10ebfb884ee8cdca98adca248"} (dict)

So either need to find a way to encode it into strings/list of strings, or a better-suiting bzlmod way of providing compiler.

@dmivankov Crap, no, it's not you...it's me. You've found a legit bug in the upcoming scala_deps design. Thanks! :-)

We must not yet have any tests to exercise overridden_artifacts (or overriden_artifacts [sic], which is how it ultimately appears in repositories() from third_party/repositories/repositories.bzl). I'll add a test, fix this problem, and ping you when I've updated the bzlmod branch (and the bzlmod-bazel-8 branch).

To let you know what to expect, this is what the API will become (there will also be an optional deps attribute of type attr.label_list):

scala_deps.overridden_artifact(
    name = "io_bazel_rules_scala_scala_library",
    artifact = "org.scala-lang:scala3-library_3:%s" % scala_version,
    sha256 = "26163f54674adb4c3e2151155f7f6f17095a0be10ebfb884ee8cdca98adca248",
)
scala_deps.overridden_artifact(
    name = "io_bazel_rules_scala_scala_compiler",
    artifact = "org.scala-lang:scala3-compiler_3:%s" % scala_version,
    sha256 = "f067da9a52ec450efa5d1cc1a3325b7f9882874a059b11728969460d170ed424",
)       
scala_deps.overridden_artifact(
    name = "io_bazel_rules_scala_scala_library_2", 
    artifact = "org.scala-lang:scala-library:2.13.15",
    sha256 = "8e4dbc3becf70d59c787118f6ad06fab6790136a0699cd6412bc9da3d336944e",
)

This because Bazel does not have an attr type of dict (where the members are arbitrary objects, including nested dicts). This essentially forces module extensions to define a schema whereby repeated instances of a tag class represent individual dict entries. The module extension can then iterate over these instances to build a proper dict as needed.

I actually already did this for the previous compiler_srcjars attribute, via the compiler_srcjar tag class. (See dt_patches/test_dt_patches_user_srcjar/MODULE.bazel in my branch for an example.) So this isn't a particularly tricky or groundbreaking fix; I just hadn't realized the need for it before now.

mbland added a commit to mbland/rules_scala that referenced this issue Feb 22, 2025
Fulfills most of bazelbuild#1482. Compatible with Bazel 6.5.0 and 7.5.0, but not
Bazel 8.

New `MODULE.bazel` files mirroring existing `WORKSPACE` configurations
comprise the bulk of the commit. The empty `WORKSPACE.bzlmod` files
ensure that Bzlmod won't evaluate the existing `WORKSPACE` files.

These new files comprise the most significant part of the change:

- scala/extensions/config.bzl
- scala/extensions/deps.bzl
- scala/private/extensions/dev_deps.bzl
- scala/private/macros/bzlmod.bzl

The first three files above are already thoroughly tested by existing
tests now that `MODULE.bazel` files are in place. The following files
thoroughly test the helpers from `scala/private/macros/bzlmod.bzl` in
specifically:

- scala/private/macros/test/BUILD.bzlmod_test
- scala/private/macros/test/MODULE.bzlmod_test
- scala/private/macros/test/bzlmod_test_ext.bzl
- test/shell/test_bzlmod_macros.sh

The pattern employed throughout the new module extensions is explained
in the `scala/private/macros/bzlmod.bzl` docstring. Adding
`test/shell/test_bzlmod_macros.sh` also precipitated adding a new
`assert_matches` helper to `test/shell/test_helper.sh`.

"Publish to BCR" configuration in the `.bcr` directory comes from:

- https://github.com/bazel-contrib/publish-to-bcr/tree/main/templates

The bazel-contrib/publish-to-bcr README contains further guidance on
configuring the app. Once that's done, we can use the app to publish a
new version to https://registry.bazel.build/ and then close bazelbuild#1482.

Per bazelbuild#1647, `com_google_protobuf` remains at v21.7, and versions up to
v25.5 can work after bumping `com_google_absl` to 20240722.0 and setting
C++17 compiler flags in `.bazelrc`.

This change enables Bazel 6 and 7 users to migrate their `rules_scala`
dependency from `WORKSPACE` to `MODULE.bazel` whenever they're ready.

After the next major version release includes this change, we can update
`com_google_protobuf`, `rules_java`, and related dependencies as part of
enabling Bazel 8 compatibility (bazelbuild#1652). The `rules_jvm_external` update
in that change will effectively end Bzlmod support for Bazel 6.5.0,
requiring another major version release after that.
mbland added a commit to mbland/rules_scala that referenced this issue Feb 24, 2025
Fulfills most of bazelbuild#1482. Compatible with Bazel 6.5.0 and 7.5.0, but not
Bazel 8.

New `MODULE.bazel` files mirroring existing `WORKSPACE` configurations
comprise the bulk of the commit. The empty `WORKSPACE.bzlmod` files
ensure that Bzlmod won't evaluate the existing `WORKSPACE` files.

These new files comprise the most significant part of the change:

- scala/extensions/config.bzl
- scala/extensions/deps.bzl
- scala/private/extensions/dev_deps.bzl
- scala/private/macros/bzlmod.bzl

The first three files above are already thoroughly tested by existing
tests now that `MODULE.bazel` files are in place, plus the new
`examples/overridden_artifacts` repo. The following files thoroughly
test the helpers from `scala/private/macros/bzlmod.bzl` specifically:

- scala/private/macros/test/...
- test/shell/test_bzlmod_macros.sh

The pattern employed throughout the new module extensions is explained
in the `scala/private/macros/bzlmod.bzl` docstring.

Adding `test/shell/test_bzlmod_macros.sh` also precipitated adding a new
`assert_matches` helper to `test/shell/test_helper.sh`.
`test/shell/test_helper.sh` also introduces a mechanism for
automatically finding and skipping tests, documented in the comment at
the bottom of the file.

"Publish to BCR" configuration in the `.bcr` directory comes from:

- https://github.com/bazel-contrib/publish-to-bcr/tree/main/templates

The bazel-contrib/publish-to-bcr README contains further guidance on
configuring the app. Once that's done, we can use the app to publish a
new version to https://registry.bazel.build/ and then close bazelbuild#1482.

Per bazelbuild#1647, `com_google_protobuf` remains at v21.7, and versions up to
v25.5 can work after bumping `com_google_absl` to 20240722.0 and setting
C++17 compiler flags in `.bazelrc`.

This change enables Bazel 6 and 7 users to migrate their `rules_scala`
dependency from `WORKSPACE` to `MODULE.bazel` whenever they're ready.

After the next major version release includes this change, we can update
`com_google_protobuf`, `rules_java`, and related dependencies as part of
enabling Bazel 8 compatibility (bazelbuild#1652). The `rules_jvm_external` update
in that change will effectively end Bzlmod support for Bazel 6.5.0,
requiring another major version release after that.
mbland added a commit to mbland/rules_scala that referenced this issue Feb 24, 2025
Fulfills most of bazelbuild#1482. Compatible with Bazel 6.5.0 and 7.5.0, but not
Bazel 8.

New `MODULE.bazel` files mirroring existing `WORKSPACE` configurations
comprise the bulk of the commit. The empty `WORKSPACE.bzlmod` files
ensure that Bzlmod won't evaluate the existing `WORKSPACE` files.

These new files comprise the most significant part of the change:

- scala/extensions/config.bzl
- scala/extensions/deps.bzl
- scala/private/extensions/dev_deps.bzl
- scala/private/macros/bzlmod.bzl

The first three files above are already thoroughly tested by existing
tests now that `MODULE.bazel` files are in place, plus the new
`examples/overridden_artifacts` repo. The following files thoroughly
test the helpers from `scala/private/macros/bzlmod.bzl` specifically:

- scala/private/macros/test/...
- test/shell/test_bzlmod_macros.sh

The pattern employed throughout the new module extensions is explained
in the `scala/private/macros/bzlmod.bzl` docstring.

Adding `test/shell/test_bzlmod_macros.sh` also precipitated adding a new
`assert_matches` helper to `test/shell/test_helper.sh`.
`test/shell/test_helper.sh` also introduces a mechanism for
automatically finding and skipping tests, documented in the comment at
the bottom of the file.

"Publish to BCR" configuration in the `.bcr` directory comes from:

- https://github.com/bazel-contrib/publish-to-bcr/tree/main/templates

The bazel-contrib/publish-to-bcr README contains further guidance on
configuring the app. Once that's done, we can use the app to publish a
new version to https://registry.bazel.build/ and then close bazelbuild#1482.

Per bazelbuild#1647, `com_google_protobuf` remains at v21.7, and versions up to
v25.5 can work after bumping `com_google_absl` to 20240722.0 and setting
C++17 compiler flags in `.bazelrc`.

This change enables Bazel 6 and 7 users to migrate their `rules_scala`
dependency from `WORKSPACE` to `MODULE.bazel` whenever they're ready.

After the next major version release includes this change, we can update
`com_google_protobuf`, `rules_java`, and related dependencies as part of
enabling Bazel 8 compatibility (bazelbuild#1652). The `rules_jvm_external` update
in that change will effectively end Bzlmod support for Bazel 6.5.0,
requiring another major version release after that.
@mbland
Copy link
Contributor

mbland commented Feb 24, 2025

@dmivankov OK, the new scala_deps.overridden_artifact tag is available in both the bzlmod and bzlmod-bazel-8 branches.

The only thing different from what I mentioned in #1482 (comment) is that the optional deps field is an attr.string_list, not an attr.label_list. (We could ultimately try to force it to become one, but attr.string_list works better with the underlying implementation in scala/scala_maven_import_external.bzl for now.)

I've also added examples/overridden_artifacts to test it (via test/shelll/test_examples.sh), and added more tests to test/shell/test_bzlmod_macros.sh to test the new repeated_tag_values() helper underlying its implementation.

@dmivankov
Copy link
Contributor

Interesting, there's some other change then compared to 6.6.0 or master, build fails with

  exception occurred while typechecking Something.scala

  An unhandled exception was thrown in the compiler.
  Please file a crash report here:
  https://github.com/lampepfl/dotty/issues/new/choose
  For non-enriched exceptions, compile with -Yno-enrich-error-messages.

     while compiling: Something.scala
        during phase: typer
                mode: Mode(ImplicitsEnabled)
     library version: version 2.13.15
    compiler version: version 3.3.5
...
Exception in thread "main" java.lang.AssertionError: assertion failed: class Ticket has non-class parent: AppliedType(TypeRef(TermRef(TermRef(ThisType(TypeRef(NoPrefix,module class scalapb)),object package),lenses),Updatable),List(TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class acl)),object ticket),class Ticket)))
	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
	at dotty.tools.dotc.core.SymDenotations$ClassDenotation.traverse$1(SymDenotations.scala:1993)
....

which was compiling before. Adding @maven//:com_thesamet_scalapb_lenses_3 as target dependency makes this one disappear and error becomes

Exception in thread "main" dotty.tools.dotc.core.MissingType: Cannot resolve reference to type fs2.type.Stream.
The classfile defining the type might be missing from the classpath.

repeating the cycle of adding deps that weren't previously required it ends up with

...
Error while emitting Something.scala
assertion failed: ClassBType.info not yet assigned: Lcats/Functor;
2 errors found
Exception in thread "main" io.bazel.rulesscala.scalac.ScalacWorker$CompilationFailed: Build failure with errors.
	at io.bazel.rulesscala.scalac.ScalacInvoker.invokeCompiler(ScalacInvoker.java:52)
	at io.bazel.rulesscala.scalac.ScalacWorker.compileScalaSources(ScalacWorker.java:272)
	at io.bazel.rulesscala.scalac.ScalacWorker.work(ScalacWorker.java:88)
	at io.bazel.rulesscala.worker.Worker.ephemeralWorkerMain(Worker.java:131)
	at io.bazel.rulesscala.worker.Worker.workerMain(Worker.java:51)
	at io.bazel.rulesscala.scalac.ScalacWorker.main(ScalacWorker.java:48)

So there's a difference in compiler versions or settings somewhere.

If it matters following customization is applied on toolchains level

load("@rules_scala//scala:scala_toolchain.bzl", "scala_toolchain")
l
scala_toolchain(
    name = "scala_toolchain_impl",
    dependency_mode = "transitive",
    dependency_tracking_method = "ast",
    strict_deps_mode = "error",
    unused_dependency_checker_mode = "off",
    visibility = ["//visibility:public"],
)

toolchain(
    name = "scala_toolchain",
    toolchain = "scala_toolchain_impl",
    toolchain_type = "@rules_scala//scala:toolchain_type",
    visibility = ["//visibility:public"],
)

plus some scalac options

    "-deprecation",  # Emit warning and location for usages of deprecated APIs.
    "-encoding",
    "utf-8",  # Specify character encoding used by source files.
    "-explaintypes",  # Explain type errors in more detail.
    "-explain",
    "-feature",  # Emit warning and location for usages of features that should be imported explicitly.
    "-language:existentials",  # Existential types (besides wildcard types) can be written and inferred
    "-language:experimental.macros",  # Allow macro definition (besides implementation and application)
    "-language:higherKinds",  # Allow higher-kinded types
    "-language:implicitConversions",  # Allow definition of implicit functions called views
    "-unchecked",  # Enable additional warnings where generated code depends on assumptions.
    "-Werror",  # Fail the compilation if there are any warnings.
    "-Ykind-projector",
    "-source:3.0-migration",
    "-Wconf:cat=deprecation:i",
    "-Xmax-inlines:128",

@mbland
Copy link
Contributor

mbland commented Feb 24, 2025

@dmivankov Perhaps @WojciechMazur can give you more insight into the compile error. At any rate, if you've got a standalone reproduction repository, it might help either Wojciech or me see what's happening.

I can say ScalaPB and protoc-bridge versions are sensitive to the version of protobuf, which has implications for rules_scala. See #1647 for the gory details. This is why there will be one release with Bzlmod, followed by another with Bazel 8 compatibility.

@dmivankov
Copy link
Contributor

I will try to make a standalone reproduction or at least minimize the breaking case, will just take some time.. so if there's any ideas I could quickly try that's very welcome 🙂

@WojciechMazur
Copy link
Contributor

The first errors seems like a typical errors related to missing entries on the classpath which is confirmed by being fixed after adding dependencies explicitly. The last error not yet assigned is something new, I've never seen it but I think it might also be related to missing entry for cats-core on the classpath.
What actually confuses me is fact that we get this kind of issue underdependency_mode = "transitive" which should provide all of the dependencies transitively.
dependency_tracking_method = "ast" should give us the dependencies used by macros (AFAIR) so it's really strange. Maybe there was some bug when porting Scala 2 logic.
Any way a standalone reproducer would be required. If possible let's move the further discussion to dedicated issue to not polute this thread any furhter

@crt-31
Copy link
Contributor

crt-31 commented Feb 25, 2025

I finally got a chance to review the changes and have a few questions and comments.

  • First off, great work on this! Looks like a lot of great work was done.
  • On version numbers… what is the versioning scheme that is trying to be followed? SemVer? Something else? (Unstable versioning and distribution structure #1496 implies first component is minimum bazel number).
  • I assume ideally there could just be a rules_scala 7.x release that is compatible with both Bazel 7 & 8. Can you enumerate what the breaking issues are that are making it so that rules_scala needs both a 7.x and an 8.x branch?
  • For what its worth, I think rules_scala 7.x could drop support for Bazel 6.
  • I am unclear of the reason the built-in toolchains were put into a separate repo, can you expound on the reasoning?
  • In my case, and I’d expect in many production systems, we specify specific scala version in scala_config, and therefore manage our own jars and setup custom toolchains. So in our case, we normally wouldn’t use scala_toolchains() or scala_deps at all ( I don’t think). But in this case, if I wanted to use say protobuf, could I use scala_toolchains() to setup just the protobuf toolchain even though I am using my own custom scala compiler toolchain?
  • Nit: suggest changing the “testing” parameter in scala_toolchains() to “all_testing” or “testing_all” or something like that.
  • Note that my biggest concern at the moment is keeping Workspace compatibility for the time being. (We are not in a position to go Bzlmod in our production just yet). That and ensuring all works in Windows. And being robust and reliable. And supporting using user-specific scala versions.
  • One specific issue I ran into about setup_testing_toolchains See setup_scala_testing_toolchain() failing when passed xxx_classpath #1706

@mbland
Copy link
Contributor

mbland commented Feb 25, 2025

I finally got a chance to review the changes and have a few questions and comments.

  • First off, great work on this! Looks like a lot of great work was done.

Thanks! 🙂

I presumed SemVer. That said, I've been looking at 7.x as fully supporting Bazel 7, and 8.x as fully supporting Bazel 8, with both supporting Bazel 6 (more so 7.x than 8.x) to ease migration. In my mind, it's good to support older Bazels with a path to adopting newer Bazels, rather than dropping older Bazel support altogether.

But as with all executive decisions, I defer to @simuons and @liucijus. I'm happy to support whichever option they choose. I wasn't aware of #1496, but as of now, it appears to be what I've just described, per #1482 (comment).

  • I assume ideally there could just be a rules_scala 7.x release that is compatible with both Bazel 7 & 8. Can you enumerate what the breaking issues are that are making it so that rules_scala needs both a 7.x and an 8.x branch?

Theoretically, there could be one release; but like I said, @simuons, at least, seems to prefer having both 7.x and 8.x to enable users to migrate gradually up to Bazel 8 and Bzlmod. I've enumerated all the known breaking changes in the README.md updates in #1703. (You'll likely want to select "View file" from the context menu.)

The main reason has to do with whether a release maintains Bazel 6 support:

  • 7.x: WORKSPACE and Bzlmod both work out of the box with Bazel 6, to support migration to Bazel 7 and Bzlmod in either order. Introduces the scala_toolchains() API (breaking the existing WORKSPACE API) and the Bzlmod API.
  • 8.x: WORKSPACE will require explicit C++ compiler flags to work with Bazel 6, and Bzlmod won't work at all. scala_toolchains() and Bzlmod APIs remain the same.

The "Compatible Bazel versions" section of the updated README.md in #1703 shows this.

  • For what its worth, I think rules_scala 7.x could drop support for Bazel 6.

I understand, but I also like the idea of giving folks who've been using Bazel 6 and WORKSPACE more of a gentle slope.

  • I am unclear of the reason the built-in toolchains were put into a separate repo, can you expound on the reasoning?

It's the only way Bzlmod can work without being annoying as hell. Without a separate toolchain repo generated by a builtin module extension, you have to import all the builtin rules_scala toolchain repositories in your own MODULE.bazel file!

This is because, under WORKSPACE, users can import and call macros that instantiate repositories into the global scope. Under Bzlmod, users can't call macros from MODULE.bazel, so any repos your module needs must be instantiated by a module extension, which users access via use_extension(). That module extension has its own scope, so if a user needs to refer to a repo from that extension, they must use use_repo() to bring it into scope explicitly.

Without "toolchainization", as I call it, the user has to call use_repo() on all required toolchain dependencies explicitly, because otherwise the module providing the toolchains won't have access to these dependency repos. With "toolchainization", there's no need, because the module's extension creates the toolchain repo with all the required dependencies in scope. The module's own MODULE.bazel then calls use_repo() to bring the toolchain repo into scope and passes it to register_toolchains(), so you don't have to.

(Arguably, separate extensions could provide individual toolchains, generating separate toolchain repos. But that can quickly get annoying, and the module's own MODULE.bazel file can't call register_toolchains() for you. As implemented, there's one toolchain repo, but it has a varying number of packages providing optional toolchains based on the configuration. The magic of the @repo_name//...:all target ensures all configured repos get registered no matter what.)

#1633 (the first "toolchainization" change introducing scala_toolchains()) speaks to this, but to make it concrete, here's what I had to do in EngFlow/example to get v6.6.0 to work with Bzlmod (plus writing my own module extensions:):

http_archive(
    name = "io_bazel_rules_scala",
    sha256 = "e734eef95cf26c0171566bdc24d83bd82bdaf8ca7873bec6ce9b0d524bdaf05d",
    strip_prefix = "rules_scala-6.6.0",
    url = "https://github.com/bazelbuild/rules_scala/releases/download/v6.6.0/rules_scala-v6.6.0.tar.gz",
    patches = ["//scala:rules_scala-6.6.0.patch"],
    patch_args = ["-p1"],
)

# This constant matches the default Scala version from rules_scala for now.
SCALA_VERSION = "2.13.12"
SCALA_VERSIONS = [SCALA_VERSION]

scala_config = use_extension("//scala/extensions:config.bzl", "scala_config")
scala_config.settings(
    scala_version = SCALA_VERSION,
    scala_versions = SCALA_VERSIONS,
)
use_repo(
    scala_config,
    "io_bazel_rules_scala_config",
)

repos = [
    "io_bazel_rules_scala_scala_compiler",
    "io_bazel_rules_scala_scala_library",
    "io_bazel_rules_scala_scala_parser_combinators",
    "io_bazel_rules_scala_scala_reflect",
    "io_bazel_rules_scala_scala_xml",
    "io_bazel_rules_scala_scalactic",
    "io_bazel_rules_scala_scalatest",
    "io_bazel_rules_scala_scalatest_core",
    "io_bazel_rules_scala_scalatest_compatible",
    "io_bazel_rules_scala_scalatest_featurespec",
    "io_bazel_rules_scala_scalatest_flatspec",
    "io_bazel_rules_scala_scalatest_freespec",
    "io_bazel_rules_scala_scalatest_funspec",
    "io_bazel_rules_scala_scalatest_funsuite",
    "io_bazel_rules_scala_scalatest_matchers_core",
    "io_bazel_rules_scala_scalatest_mustmatchers",
    "io_bazel_rules_scala_scalatest_shouldmatchers",
]

toolchains = [
    "@io_bazel_rules_scala//scala:toolchain",
    "@io_bazel_rules_scala//testing:scalatest_toolchain",
]

scala_deps = use_extension("//scala/extensions:deps.bzl", "scala_deps")
[
    (
        [use_repo(scala_deps, repo + suffix) for repo in repos],
        [register_toolchains(toolchain + suffix) for toolchain in toolchains],
    )
    # The v.replace() expression mimics the logic to generate version specific
    # repo suffixes from rules_scala.
    for suffix in ["_" + v.replace(".", "_") for v in SCALA_VERSIONS]
]

I described this process in Migrating to Bazel Modules (a.k.a. Bzlmod) - Module Extensions. By contrast, once Bzlmodification lands, all of that gets replaced by this (which I have working in a local EngFlow/example repo, but using a local_path_override()):

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

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

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

Note that I don't even have to call register_toolchains() on the builtin toolchains, because the MODULE.bazel file for rules_scala will do that for me. You can still use setup_scala_toolchain(), et. al., to create your custom toolchains (possibly using rules_jvm_external to provide the artifacts), and call register_toolchains() in your MODULE.bazel file so they take precedence over the builtin toolchains. But you don't need all the use_repo() and list comprehension business to just use the builtins.

  • In my case, and I’d expect in many production systems, we specify specific scala version in scala_config, and therefore manage our own jars and setup custom toolchains. So in our case, we normally wouldn’t use scala_toolchains() or scala_deps at all ( I don’t think). But in this case, if I wanted to use say protobuf, could I use scala_toolchains() to setup just the protobuf toolchain even though I am using my own custom scala compiler toolchain?

I believe so, yes. scala_toolchains() will always register the builtin toolchain for the configured Scala version, but defining and registering your own will still cause yours to take precedence. That said, just calling scala_toolchains(scala_proto = True) (or, under Bzlmod, scala_deps.toolchains(scala_proto = True)) will instantiate and register the scala_proto toolchain specifically, not the other optional toolchains.

(Now, when it comes to protobuf, that's a big reason for the proposed 7.x + 8.x release schema, because of the interplay between protobuf, Bazel, rules_java, the ScalaPB suite, and protoc-bridge. See that aforementioned matrix for "Compatible Bazel versions" in #1703 as well as #1647.)

  • Nit: suggest changing the “testing” parameter in scala_toolchains() to “all_testing” or “testing_all” or something like that.

I don't have a strong preference, but am happy to change it if @simuons or @liucijus prefer.

  • Note that my biggest concern at the moment is keeping Workspace compatibility for the time being. (We are not in a position to go Bzlmod in our production just yet). That and ensuring all works in Windows. And being robust and reliable. And supporting using user-specific scala versions.

Glad to hear all the WORKSPACE compatibility work will pay off for you! 🙂 After all, the build output should theoretically be the same (or as close as possible) between WORKSPACE and Bzlmod. The scala_toolchains() API and the scala_deps module extension API are designed to be very similar, and the module extension calls scala_toolchains() under the hood. It's mainly just a much improved configuration and maintenance experience.

(BTW, in case you or anyone reading didn't know, you can still use 'WORKSPACE' and Bzlmod together for the time being. You can actually keep your WORKSPACE in place and move pieces to MODULE.bazel piecemeal. But the clock is ticking, because Bazel 9 (later this year) will drop WORKSPACE support.)

And for one more shameless plug, I've written a blog series on solving Bzlmod migration issues, in case that's helpful. (I'm due to post another soon, which I've mostly drafted.)

Yes, thanks for catching that. Definitely a blocker. I'm on it!

mbland added a commit to mbland/rules_scala that referenced this issue Feb 25, 2025
Fulfills most of bazelbuild#1482. Compatible with Bazel 6.5.0 and 7.5.0, but not
Bazel 8.

New `MODULE.bazel` files mirroring existing `WORKSPACE` configurations
comprise the bulk of the commit. The empty `WORKSPACE.bzlmod` files
ensure that Bzlmod won't evaluate the existing `WORKSPACE` files.

These new files comprise the most significant part of the change:

- scala/extensions/config.bzl
- scala/extensions/deps.bzl
- scala/private/extensions/dev_deps.bzl
- scala/private/macros/bzlmod.bzl

The first three files above are already thoroughly tested by existing
tests now that `MODULE.bazel` files are in place, plus the new
`examples/overridden_artifacts` repo. The following files thoroughly
test the helpers from `scala/private/macros/bzlmod.bzl` specifically:

- scala/private/macros/test/...
- test/shell/test_bzlmod_macros.sh

The pattern employed throughout the new module extensions is explained
in the `scala/private/macros/bzlmod.bzl` docstring.

Adding `test/shell/test_bzlmod_macros.sh` also precipitated adding a new
`assert_matches` helper to `test/shell/test_helper.sh`.
`test/shell/test_helper.sh` also introduces a mechanism for
automatically finding and skipping tests, documented in the comment at
the bottom of the file.

"Publish to BCR" configuration in the `.bcr` directory comes from:

- https://github.com/bazel-contrib/publish-to-bcr/tree/main/templates

The bazel-contrib/publish-to-bcr README contains further guidance on
configuring the app. Once that's done, we can use the app to publish a
new version to https://registry.bazel.build/ and then close bazelbuild#1482.

Per bazelbuild#1647, `com_google_protobuf` remains at v21.7, and versions up to
v25.5 can work after bumping `com_google_absl` to 20240722.0 and setting
C++17 compiler flags in `.bazelrc`.

This change enables Bazel 6 and 7 users to migrate their `rules_scala`
dependency from `WORKSPACE` to `MODULE.bazel` whenever they're ready.

After the next major version release includes this change, we can update
`com_google_protobuf`, `rules_java`, and related dependencies as part of
enabling Bazel 8 compatibility (bazelbuild#1652). The `rules_jvm_external` update
in that change will effectively end Bzlmod support for Bazel 6.5.0,
requiring another major version release after that.
@simuons
Copy link
Collaborator

simuons commented Feb 26, 2025

Nit: suggest changing the “testing” parameter in scala_toolchains() to “all_testing” or “testing_all” or something like that.

I'd suggest to remove this attribute. If its sole purpose is to set other three to True then there is not much benefit in it.

mbland added a commit to mbland/rules_scala that referenced this issue Feb 26, 2025
Describes the new `scala_toolchains()` API, breaking changes, Bazel
compatibility matrix, and breaking of the `io_bazel_rules_scala` repo
name dependency. Part of bazelbuild#1482, bazelbuild#1647, bazelbuild#1652, and bazelbuild#1699, it also removes
obsolete `WORKSPACE` APIs in favor of `scala_toolchains()`, et. al.

Much of the README text regarding `WORKSPACE` configuration, Bazel
compatibility, and breaking changes comes from:

- bazelbuild#1482 (comment)

The "Breaking changes in `rules_scala` 7.x" section of `README.md`
describes the removed `WORKSPACE` macros, and provides guidance for
adopting the `scala_toolchains()` API. Also includes information about
the upcoming Bzlmod implementation (bazelbuild#1482) and the Bazel 8 compatibility
changes for `rules_scala` 8.x (bazelbuild#1652).

Contains a light editing pass over almost every Markdown file to resolve
`markdownlint` warnings when editing in VSCode. Also added
`.markdownlint.json` to silence rule `MD033/no-inline-html`, since
several docs contain `<br/>` and/or `<table>` elements.

- https://github.com/DavidAnson/vscode-markdownlint?tab=readme-ov-file#markdownlintconfig

Performed other opportunistic grammar edits and added new information,
including:

- `docs/coverage.md`: Describes how to determine the default JaCoCo
  version used by `rules_java`

- `scripts/README.md`: Updates `create_repository.py` docs extensively,
  and adds a section for `sync_bazelversion.sh`

- Replaces `starlark` code fences with `py`, since the syntax is
  identical and editors seem to support it better.

---

Since the next major release is imminent, ensuring the documentation
accurately reflects all the changes since v6.6.0 has become an urgent
priority.

Rather than leave the old `WORKSPACE` APIs in place, which could lead to
surprising failures, this change removes all of them. This also changes
some code that still depended on some of these obsolete macros,
including `scala_toolchains()`. Since all the toolchainization changes
led to the entire project already using `scala_toolchains()` and
`scala_register_toolchains()` exclusively, this proved a low risk
refactoring.

With some Bzlmod and Bazel 8 information already in place, very little
will need to change when these implementations land. The commits that
contain those implementations will also include their relevant
documentation updates.
mbland added a commit to mbland/rules_scala that referenced this issue Feb 26, 2025
It seems the README won't expand refs like bazelbuild#1482. This updates such refs
to use the repo prefix, e.g., bazelbuild#1482.
mbland added a commit to mbland/rules_scala that referenced this issue Feb 26, 2025
Explicitly notes that some `rules_scala` APIs may break, specifically
`setup_scala_toolchain`. Part of bazelbuild#1482.

Brought to my attention by @michalbogacz in a `#scala` thread in the
Bazel Slack workspace, which was in the context of
michalbogacz/scala-bazel-monorepo#26.

- https://bazelbuild.slack.com/archives/CDCKJ2KFZ/p1740144886159909
mbland added a commit to mbland/rules_scala that referenced this issue Feb 26, 2025
Removed in favor of using the existing `scalatest`, `junit`, and
`specs2` parameters at @simuons's suggestion in:

- bazelbuild#1482 (comment)

Also updated the `scala_toolchains()` docstring slightly and added `doc`
parameters to the `attrs` for `_scala_toolchains_repo()`.
@mbland
Copy link
Contributor

mbland commented Feb 26, 2025

Nit: suggest changing the “testing” parameter in scala_toolchains() to “all_testing” or “testing_all” or something like that.

I'd suggest to remove this attribute. If its sole purpose is to set other three to True then there is not much benefit in it.

@simuons Done in c789cb0 from #1703.

mbland added a commit to mbland/rules_scala that referenced this issue Feb 26, 2025
Shortens `@io_bazel_rules_scala_config` to `@rules_scala_config` in
light of the `@io_bazel_rules_scala` removal in bazelbuild#1696. Part of bazelbuild#1482.

Adds a section to `README.md` indicating this as a breaking change, with
advice on working around any breakages that aren't immediately fixable.

Per @simuons's advice in
bazelbuild#1703 (comment).
mbland added a commit to mbland/rules_scala that referenced this issue Feb 26, 2025
Fulfills most of bazelbuild#1482. Compatible with Bazel 6.5.0 and 7.5.0, but not
Bazel 8.

New `MODULE.bazel` files mirroring existing `WORKSPACE` configurations
comprise the bulk of the commit. The empty `WORKSPACE.bzlmod` files
ensure that Bzlmod won't evaluate the existing `WORKSPACE` files.

These new files comprise the most significant part of the change:

- scala/extensions/config.bzl
- scala/extensions/deps.bzl
- scala/private/extensions/dev_deps.bzl
- scala/private/macros/bzlmod.bzl

The first three files above are already thoroughly tested by existing
tests now that `MODULE.bazel` files are in place, plus the new
`examples/overridden_artifacts` repo. The following files thoroughly
test the helpers from `scala/private/macros/bzlmod.bzl` specifically:

- scala/private/macros/test/...
- test/shell/test_bzlmod_macros.sh

The pattern employed throughout the new module extensions is explained
in the `scala/private/macros/bzlmod.bzl` docstring.

Adding `test/shell/test_bzlmod_macros.sh` also precipitated adding a new
`assert_matches` helper to `test/shell/test_helper.sh`.
`test/shell/test_helper.sh` also introduces a mechanism for
automatically finding and skipping tests, documented in the comment at
the bottom of the file.

"Publish to BCR" configuration in the `.bcr` directory comes from:

- https://github.com/bazel-contrib/publish-to-bcr/tree/main/templates

The bazel-contrib/publish-to-bcr README contains further guidance on
configuring the app. Once that's done, we can use the app to publish a
new version to https://registry.bazel.build/ and then close bazelbuild#1482.

Per bazelbuild#1647, `com_google_protobuf` remains at v21.7, and versions up to
v25.5 can work after bumping `com_google_absl` to 20240722.0 and setting
C++17 compiler flags in `.bazelrc`.

This change enables Bazel 6 and 7 users to migrate their `rules_scala`
dependency from `WORKSPACE` to `MODULE.bazel` whenever they're ready.

After the next major version release includes this change, we can update
`com_google_protobuf`, `rules_java`, and related dependencies as part of
enabling Bazel 8 compatibility (bazelbuild#1652). The `rules_jvm_external` update
in that change will effectively end Bzlmod support for Bazel 6.5.0,
requiring another major version release after that.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment