Skip to content

Commit

Permalink
Toolchainize //scala:toolchain_type
Browse files Browse the repository at this point in the history
Moves the `toolchain` targets for `//scala:toolchain_type` to a new
`@io_bazel_rules_scala_toolchains` repository as a step towards
Bzlmodification. Part of #1482.

Instantiating toolchains in their own repository enables module
extensions to define the the repositories required by those toolchains
within the extension's own namespace. Bzlmod users can then register the
toolchains from this repository without having to import all the
toolchains' dependencies into their own namespace via `use_repo()`.

---

The `scala_toolchains_repo()` macro wraps the underlying repository rule
and assigns it the standard name `io_bazel_rules_scala_toolchains`.
Right now it's only instantiating the main Scala toolchain via the
default `scala = True` parameter. Future changes will expand this
macro and repository rule with more boolean parameters to instantiate
other toolchains, specifically:

- `scalatest`
- `junit`
- `specs2`
- `twitter_scrooge`
- `jmh`
- `scala_proto` and `scala_proto_enable_all_options`
- `testing` (includes all of `scalatest`, `junit`, and `specs2`)
- `scalafmt`

---

`WORKSPACE` users will now have to import and call the
`scala_toolchains_repo()` macro to instantiate
`@io_bazel_rules_scala_toolchains`.

```py
load("@io_bazel_rules_scala//:scala_config.bzl", "scala_config")

scala_config()

load(
    "//scala:scala.bzl",
    "rules_scala_setup",
    "rules_scala_toolchain_deps_repositories",
    "scala_toolchains_repo",
)

rules_scala_setup()

rules_scala_toolchain_deps_repositories()

scala_toolchains_repo()

register_toolchains("@io_bazel_rules_scala_toolchains//...:all")
```

This is what the corresponding `MODULE.bazel` setup would look like:

```py
module(name = "rules_scala", version = "7.0.0")

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

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

The `register_toolchains()` call in `WORKSPACE` isn't strictly required
at this point, but is recommended. However, all the `WORKSPACE` files in
this repo already register their required toolchains using existing
macros, which have been updated in this change.

In fact, calling `register_toolchains()` right after
`scala_toolchains_repo()` as shown above breaks two tests that depend on
the existing `WORKSPACE` toolchain registration:

- `test_compilation_fails_with_plus_one_deps_undefined` from
  `test/shell/test_compilation.sh` depends on
  `scala_register_unused_deps_toolchains()` setting up its toolchain to
  resolve first. `//scala:unused_dependency_checker_error_toolchain`
  sets the `scala_toolchain()` parameters `dependency_tracking_method =
  "ast-plus"` and `unused_dependency_checker_mode = "error"`, and the
  `@io_bazel_rules_scala_toolchains//scala` toolchains don't.

- `test_scala_binary_allows_opt_in_to_use_of_argument_file_in_runner_for_improved_performance`
  from `test/shell/test_scala_binary.sh` depends on the
  `use_argument_file_in_runner` parameter of `scala_toolchain` being
  `False`. This is the default, but the
  `@io_bazel_rules_scala_toolchains//scala` toolchains explicitly set
  this to `True` instead.

In the Bzlmod case, the `register_toolchains()` call isn't necessary at
all. This is because `@io_bazel_rules_scala_toolchains` includes one
package per set of toolchains, and the rules_scala `MODULE.bazel` calls
`register_toolchains("@io_bazel_rules_scala_toolchains//...:all")`. This
will automatically register all configured rules_scala toolchains, while
allowing users to override any of them using `register_toolchains()` in
their own `MODULE.bazel` files.

Technically, the `scala_deps.toolchains()` call isn't required when only
using the default `scala = True` parameter; the rules_scala
`MODULE.bazel` will instantiate this automatically, too.
  • Loading branch information
mbland committed Oct 24, 2024
1 parent 9bbdc8a commit 85924ce
Show file tree
Hide file tree
Showing 24 changed files with 202 additions and 98 deletions.
9 changes: 8 additions & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,19 @@ load("@io_bazel_rules_scala//:scala_config.bzl", "scala_config")

scala_config(enable_compiler_dependency_tracking = True)

load("//scala:scala.bzl", "rules_scala_setup", "rules_scala_toolchain_deps_repositories")
load(
"//scala:scala.bzl",
"rules_scala_setup",
"rules_scala_toolchain_deps_repositories",
"scala_toolchains_repo",
)

rules_scala_setup()

rules_scala_toolchain_deps_repositories(fetch_sources = True)

scala_toolchains_repo()

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")

rules_proto_dependencies()
Expand Down
3 changes: 3 additions & 0 deletions dt_patches/test_dt_patches/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ load(
"@io_bazel_rules_scala//scala:scala.bzl",
"rules_scala_setup",
"rules_scala_toolchain_deps_repositories",
"scala_toolchains_repo",
)
load(
"@io_bazel_rules_scala//scala:scala_cross_version.bzl",
Expand Down Expand Up @@ -74,6 +75,8 @@ rules_scala_toolchain_deps_repositories(
validate_scala_version = False,
)

scala_toolchains_repo()

register_toolchains(":dt_scala_toolchain")

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")
Expand Down
3 changes: 3 additions & 0 deletions dt_patches/test_dt_patches_user_srcjar/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ load(
"@io_bazel_rules_scala//scala:scala.bzl",
"rules_scala_setup",
"rules_scala_toolchain_deps_repositories",
"scala_toolchains_repo",
)
load(
"@io_bazel_rules_scala//scala:scala_cross_version.bzl",
Expand Down Expand Up @@ -123,6 +124,8 @@ rules_scala_toolchain_deps_repositories(
validate_scala_version = False,
)

scala_toolchains_repo()

register_toolchains(":dt_scala_toolchain")

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")
Expand Down
3 changes: 3 additions & 0 deletions examples/crossbuild/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,15 @@ load(
"@io_bazel_rules_scala//scala:scala.bzl",
"rules_scala_setup",
"rules_scala_toolchain_deps_repositories",
"scala_toolchains_repo",
)

rules_scala_setup()

rules_scala_toolchain_deps_repositories()

scala_toolchains_repo()

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")

rules_proto_dependencies()
Expand Down
3 changes: 3 additions & 0 deletions examples/scala3/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ load(
"@io_bazel_rules_scala//scala:scala.bzl",
"rules_scala_setup",
"rules_scala_toolchain_deps_repositories",
"scala_toolchains_repo",
)

rules_scala_setup()

rules_scala_toolchain_deps_repositories(fetch_sources = True)

scala_toolchains_repo()

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")

rules_proto_dependencies()
Expand Down
3 changes: 3 additions & 0 deletions examples/semanticdb/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@ load(
"@io_bazel_rules_scala//scala:scala.bzl",
"rules_scala_setup",
"rules_scala_toolchain_deps_repositories",
"scala_toolchains_repo",
)

rules_scala_setup()

rules_scala_toolchain_deps_repositories(fetch_sources = True)

scala_toolchains_repo()

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")

rules_proto_dependencies()
Expand Down
3 changes: 3 additions & 0 deletions examples/testing/multi_frameworks_toolchain/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ load(
"@io_bazel_rules_scala//scala:scala.bzl",
"rules_scala_setup",
"rules_scala_toolchain_deps_repositories",
"scala_toolchains_repo",
)

rules_scala_setup()

rules_scala_toolchain_deps_repositories(fetch_sources = True)

scala_toolchains_repo()

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")

rules_proto_dependencies()
Expand Down
3 changes: 3 additions & 0 deletions examples/testing/scalatest_repositories/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ load(
"@io_bazel_rules_scala//scala:scala.bzl",
"rules_scala_setup",
"rules_scala_toolchain_deps_repositories",
"scala_toolchains_repo",
)

rules_scala_setup()

rules_scala_toolchain_deps_repositories(fetch_sources = True)

scala_toolchains_repo()

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")

rules_proto_dependencies()
Expand Down
3 changes: 3 additions & 0 deletions examples/testing/specs2_junit_repositories/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ load(
"@io_bazel_rules_scala//scala:scala.bzl",
"rules_scala_setup",
"rules_scala_toolchain_deps_repositories",
"scala_toolchains_repo",
)

rules_scala_setup()

rules_scala_toolchain_deps_repositories(fetch_sources = True)

scala_toolchains_repo()

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")

rules_proto_dependencies()
Expand Down
84 changes: 24 additions & 60 deletions scala/BUILD
Original file line number Diff line number Diff line change
@@ -1,43 +1,49 @@
load("@rules_java//java:defs.bzl", "java_import", "java_library")
load("//scala:providers.bzl", "declare_deps_provider")
load("//scala:scala_cross_version.bzl", "version_suffix")
load("//scala/private:macros/setup_scala_toolchain.bzl", "default_deps", "setup_scala_toolchain")
load("@io_bazel_rules_scala_config//:config.bzl", "SCALA_VERSION", "SCALA_VERSIONS")
load("//scala:scala_toolchain.bzl", "scala_toolchain")
load("@io_bazel_rules_scala_config//:config.bzl", "SCALA_VERSION")
load("@rules_java//java:defs.bzl", "java_import", "java_library")

toolchain_type(
name = "toolchain_type",
visibility = ["//visibility:public"],
)

[
setup_scala_toolchain(
name = "toolchain" + version_suffix(scala_version),
scala_version = scala_version,
use_argument_file_in_runner = True,
)
for scala_version in SCALA_VERSIONS
]

# Alias for backward compatibility
alias(
name = "default_toolchain",
actual = "toolchain" + version_suffix(SCALA_VERSION),
actual = (
"@io_bazel_rules_scala_toolchains//scala:toolchain" +
version_suffix(SCALA_VERSION)
),
)

setup_scala_toolchain(
name = "unused_dependency_checker_error_toolchain",
scala_toolchain(
name = "unused_dependency_checker_error_toolchain_impl",
dependency_tracking_method = "ast-plus",
unused_dependency_checker_mode = "error",
)

setup_scala_toolchain(
name = "minimal_direct_source_deps",
scala_toolchain(
name = "minimal_direct_source_deps_impl",
dependency_mode = "plus-one",
dependency_tracking_method = "ast",
strict_deps_mode = "error",
unused_dependency_checker_mode = "error",
)

[
toolchain(
name = tc,
toolchain = tc + "_impl",
toolchain_type = "//scala:toolchain_type",
visibility = ["//visibility:public"],
)
for tc in [
"unused_dependency_checker_error_toolchain",
"minimal_direct_source_deps",
]
]

java_import(
name = "bazel_test_runner_deploy",
jars = ["@bazel_tools//tools/jdk:TestRunner_deploy.jar"],
Expand All @@ -49,45 +55,3 @@ java_library(
srcs = ["PlaceHolderClassToCreateEmptyJarForScalaImport.java"],
visibility = ["//visibility:public"],
)

declare_deps_provider(
name = "scala_compile_classpath_provider",
deps_id = "scala_compile_classpath",
visibility = ["//visibility:public"],
deps = default_deps("scala_compile_classpath", SCALA_VERSION),
)

declare_deps_provider(
name = "scala_library_classpath_provider",
deps_id = "scala_library_classpath",
visibility = ["//visibility:public"],
deps = default_deps("scala_library_classpath", SCALA_VERSION),
)

declare_deps_provider(
name = "scala_macro_classpath_provider",
deps_id = "scala_macro_classpath",
visibility = ["//visibility:public"],
deps = default_deps("scala_macro_classpath", SCALA_VERSION),
)

declare_deps_provider(
name = "scala_xml_provider",
deps_id = "scala_xml",
visibility = ["//visibility:public"],
deps = default_deps("scala_xml", SCALA_VERSION),
)

declare_deps_provider(
name = "parser_combinators_provider",
deps_id = "parser_combinators",
visibility = ["//visibility:public"],
deps = default_deps("parser_combinators", SCALA_VERSION),
)

declare_deps_provider(
name = "semanticdb_provider",
deps_id = "semanticdb",
visibility = ["//visibility:public"],
deps = default_deps("semanticdb", SCALA_VERSION),
)
Empty file added scala/private/extensions/BUILD
Empty file.
75 changes: 75 additions & 0 deletions scala/private/extensions/toolchains.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""Creates a repo containing Scala toolchain packages"""

def _scala_toolchains_repo_impl(repository_ctx):
repo_attr = repository_ctx.attr
format_args = {
"rules_scala_repo": Label("//:all").repo_name,
}
toolchains = {}

if repo_attr.scala:
toolchains["scala"] = _SCALA_TOOLCHAIN_BUILD

if len(toolchains) == 0:
fail("no toolchains specified")

for pkg, build in toolchains.items():
repository_ctx.file(
pkg + "/BUILD",
content = build.format(**format_args),
executable = False,
)

_scala_toolchains_repo = repository_rule(
implementation = _scala_toolchains_repo_impl,
attrs = {
"scala": attr.bool(default = True),
},
)

def scala_toolchains_repo(**kwargs):
_scala_toolchains_repo(
name = "io_bazel_rules_scala_toolchains",
**kwargs
)

_SCALA_TOOLCHAIN_BUILD = """
load(
"@@{rules_scala_repo}//scala/private:macros/setup_scala_toolchain.bzl",
"default_deps",
"setup_scala_toolchain",
)
load("@@{rules_scala_repo}//scala:providers.bzl", "declare_deps_provider")
load("@@{rules_scala_repo}//scala:scala_cross_version.bzl", "version_suffix")
load(
"@io_bazel_rules_scala_config//:config.bzl",
"SCALA_VERSION",
"SCALA_VERSIONS",
)
[
setup_scala_toolchain(
name = "toolchain" + version_suffix(scala_version),
scala_version = scala_version,
use_argument_file_in_runner = True,
)
for scala_version in SCALA_VERSIONS
]
[
declare_deps_provider(
name = deps_id + "_provider",
deps_id = deps_id,
visibility = ["//visibility:public"],
deps = default_deps(deps_id, SCALA_VERSION),
)
for deps_id in [
"scala_xml",
"parser_combinators",
"scala_compile_classpath",
"scala_library_classpath",
"scala_macro_classpath",
"semanticdb",
]
]
"""
6 changes: 3 additions & 3 deletions scala/private/macros/setup_scala_toolchain.bzl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
load("//scala:scala_toolchain.bzl", "scala_toolchain")
load("//scala:providers.bzl", "declare_deps_provider")
load("//scala:scala_cross_version.bzl", "version_suffix")
load("//scala:scala_cross_version.bzl", "repositories", "version_suffix")
load("@io_bazel_rules_scala_config//:config.bzl", "SCALA_VERSION")

def setup_scala_toolchain(
Expand Down Expand Up @@ -97,7 +97,7 @@ def setup_scala_toolchain(
native.toolchain(
name = name,
toolchain = ":%s_impl" % name,
toolchain_type = "@io_bazel_rules_scala//scala:toolchain_type",
toolchain_type = Label("//scala:toolchain_type"),
target_settings = ["@io_bazel_rules_scala_config//:scala_version" + version_suffix(scala_version)],
visibility = visibility,
)
Expand Down Expand Up @@ -155,4 +155,4 @@ _DEFAULT_DEPS = {
def default_deps(deps_id, scala_version):
versions = _DEFAULT_DEPS[deps_id]
deps = versions.get("any", []) + versions.get(scala_version[0], [])
return [dep + version_suffix(scala_version) for dep in deps]
return repositories(scala_version, deps)
Loading

0 comments on commit 85924ce

Please sign in to comment.