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

Proposal: Deps Toolchain Infrastructure #1067

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions scala/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ load(
_declare_scalac_provider = "declare_scalac_provider",
)
load("//scala:scala_toolchain.bzl", "scala_toolchain")
load("//scala/toolchains:toolchains.bzl", "declare_deps_toolchain")
load("//scala:providers.bzl", "declare_deps_provider")

toolchain_type(
name = "toolchain_type",
Expand Down Expand Up @@ -94,3 +96,36 @@ java_library(
srcs = ["PlaceHolderClassToCreateEmptyJarForScalaImport.java"],
visibility = ["//visibility:public"],
)

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

toolchain(
name = "deps_toolchain",
toolchain = "@io_bazel_rules_scala//scala:deps_toolchain_impl",
toolchain_type = "@io_bazel_rules_scala//scala:deps_toolchain_type",
visibility = ["//visibility:public"],
)

declare_deps_provider(
name = "scala_xml_provider",
visibility = ["//visibility:public"],
deps = ["//external:io_bazel_rules_scala/dependency/scala/scala_xml"],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this for backwards compatibility? if so have you thought of how/when we should break it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it's for backwards compatibility. To get rid of it we need to provide users with an alternative for binds (*_repositories without binds, toolchains, or something loader specific).

)

declare_deps_provider(
name = "parser_combinators_provider",
visibility = ["//visibility:public"],
deps = ["//external:io_bazel_rules_scala/dependency/scala/parser_combinators"],
)

declare_deps_toolchain(
name = "deps_toolchain_impl",
dep_providers = {
"@io_bazel_rules_scala//scala:scala_xml_provider": "scala_xml",
"@io_bazel_rules_scala//scala:parser_combinators_provider": "parser_combinators",
},
visibility = ["//visibility:public"],
)
2 changes: 1 addition & 1 deletion scala/private/common_attributes.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ resolve_deps = {
"_scala_toolchain": attr.label_list(
default = [
Label(
"//external:io_bazel_rules_scala/dependency/scala/scala_library",
"@io_bazel_rules_scala//scala/private/toolchain_deps:scala_library_classpath",
),
],
allow_files = False,
Expand Down
7 changes: 6 additions & 1 deletion scala/private/macros/scala_repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ def scala_repositories(
),
maven_servers = _default_maven_server_urls(),
scala_extra_jars = _default_scala_extra_jars(),
fetch_sources = False):
fetch_sources = False,
register_scalatest_toolchain = True):
(scala_version, scala_version_jar_shas) = scala_version_shas
major_version = _extract_major_version(scala_version)

Expand Down Expand Up @@ -250,3 +251,7 @@ def scala_repositories(
name = "io_bazel_rules_scala/dependency/scala/scalactic/scalactic",
actual = "@io_bazel_rules_scala_scalactic",
)

# for bakcwards compatibility
if register_scalatest_toolchain:
native.register_toolchains("@io_bazel_rules_scala//scala/scalatest/toolchain:scalatest_toolchain")
2 changes: 1 addition & 1 deletion scala/private/rules/scala_junit_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ _junit_resolve_deps = {
"_scala_toolchain": attr.label_list(
default = [
Label(
"//external:io_bazel_rules_scala/dependency/scala/scala_library",
"@io_bazel_rules_scala//scala/private/toolchain_deps:scala_library_classpath",
),
Label("//external:io_bazel_rules_scala/dependency/junit/junit"),
Label(
Expand Down
6 changes: 3 additions & 3 deletions scala/private/rules/scala_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ _scala_test_attrs = {
"jvm_flags": attr.string_list(),
"_scalatest": attr.label(
default = Label(
"//external:io_bazel_rules_scala/dependency/scalatest/scalatest",
"@io_bazel_rules_scala//scala/scalatest/toolchain:scalatest_classapth",
),
),
"_scalatest_runner": attr.label(
Expand All @@ -81,10 +81,10 @@ _test_resolve_deps = {
"_scala_toolchain": attr.label_list(
default = [
Label(
"//external:io_bazel_rules_scala/dependency/scala/scala_library",
"@io_bazel_rules_scala//scala/private/toolchain_deps:scala_library_classpath",
),
Label(
"//external:io_bazel_rules_scala/dependency/scalatest/scalatest",
"@io_bazel_rules_scala//scala/scalatest/toolchain:scalatest_classapth",
),
],
allow_files = False,
Expand Down
27 changes: 27 additions & 0 deletions scala/private/toolchain_deps/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
load(":toolchain_dep_rules.bzl", "common_toolchain_deps", "scala_toolchain_deps")

# dependencies from ScalacProvider
scala_toolchain_deps(
name = "scala_compile_classpath",
from_classpath = "default_repl_classpath",
visibility = ["//visibility:public"],
)

scala_toolchain_deps(
name = "scala_library_classpath",
from_classpath = "default_classpath",
visibility = ["//visibility:public"],
)

# dependencies from DepsInfo
common_toolchain_deps(
name = "scala_xml",
provider_id = "scala_xml",
visibility = ["//visibility:public"],
)

common_toolchain_deps(
name = "parser_combinators",
provider_id = "parser_combinators",
visibility = ["//visibility:public"],
)
29 changes: 29 additions & 0 deletions scala/private/toolchain_deps/toolchain_dep_rules.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
load("@io_bazel_rules_scala//scala:providers.bzl", _ScalacProvider = "ScalacProvider")
load("//scala/private/toolchain_deps:toolchain_deps.bzl", "expose_toolchain_deps", "java_info_for_deps")

def _scala_toolchain_deps(ctx):
_toolchain_type = "@io_bazel_rules_scala//scala:toolchain_type"
from_classpath = ctx.attr.from_classpath

scalac_provider = ctx.toolchains[_toolchain_type].scalac_provider_attr[_ScalacProvider]
classpath_deps = getattr(scalac_provider, from_classpath)
return java_info_for_deps(classpath_deps)

scala_toolchain_deps = rule(
implementation = _scala_toolchain_deps,
attrs = {
"from_classpath": attr.string(mandatory = True),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to check my understanding: Is it correct to say that we need this (and we can't use expose_toolchain_deps here because of preexisting code that defines ScalacProvider and some other things, right?
Is there an intrinsic reason why we can't drop ScalacProvider and model everything with expose_toolchain_deps, or is it because it would be hard to change?

Either way is fine by me, even if we were to remove ScalacProvider I'd vote for doing it in a follow-up PR. I just want to wrap my head around this :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ScalacProvider comes from the existing scala toolchain, and it would be a breaking change for some users if it gets modified. I would like, if possible, to have no breaking changes with the introduction of this toolchains infra. If it looks something that needs to be refactored into unified version, I think it's better to have a separate PR, which would be easier to revert if that changes becomes problematic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks! Seems reasonable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate PR sounds very reasonable while also important since I think having multiple mental models would make things really hard

},
toolchains = ["@io_bazel_rules_scala//scala:toolchain_type"],
)

def _common_toolchain_deps(ctx):
return expose_toolchain_deps(ctx, "@io_bazel_rules_scala//scala:deps_toolchain_type")

common_toolchain_deps = rule(
implementation = _common_toolchain_deps,
attrs = {
"provider_id": attr.string(mandatory = True),
},
toolchains = ["@io_bazel_rules_scala//scala:deps_toolchain_type"],
)
18 changes: 18 additions & 0 deletions scala/private/toolchain_deps/toolchain_deps.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
load("@io_bazel_rules_scala//scala:providers.bzl", "DepsInfo")

def _log_required_provider_id(target, toolchain_type_label, provider_id):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't it misleading? it's called log but you're actually failing

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree.

fail(target + " requires mapping of " + provider_id + " provider id on the toolchain " + toolchain_type_label)

def java_info_for_deps(deps):
return [java_common.merge([dep[JavaInfo] for dep in deps])]

def expose_toolchain_deps(ctx, toolchain_type_label):
dep_provider_id = ctx.attr.provider_id
dep_providers_map = getattr(ctx.toolchains[toolchain_type_label], "dep_providers")
dep_provider = {v: k for k, v in dep_providers_map.items()}.get(dep_provider_id)

if dep_provider == None:
_log_required_provider_id(ctx.attr.name, toolchain_type_label, dep_provider_id)

deps = dep_provider[DepsInfo].deps
return java_info_for_deps(deps)
21 changes: 21 additions & 0 deletions scala/providers.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,24 @@ declare_scalac_provider = rule(
"default_macro_classpath": attr.label_list(allow_files = True),
},
)

DepsInfo = provider(
doc = "Dependencies needed for specifc rules",
fields = [
"deps",
],
)

def _declare_deps_provider(ctx):
return [
DepsInfo(
deps = ctx.attr.deps,
),
]

declare_deps_provider = rule(
implementation = _declare_deps_provider,
attrs = {
"deps": attr.label_list(allow_files = True),
},
)
3 changes: 1 addition & 2 deletions scala/scalatest/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ scala_import(
name = "scalatest",
jars = [],
exports = [
"//external:io_bazel_rules_scala/dependency/scala/scalactic/scalactic",
"//external:io_bazel_rules_scala/dependency/scala/scalatest/scalatest",
"//scala/scalatest/toolchain:scalatest_classapth",
],
)
37 changes: 37 additions & 0 deletions scala/scalatest/toolchain/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
load("@io_bazel_rules_scala//scala/toolchains:toolchains.bzl", "declare_deps_toolchain")
load("@io_bazel_rules_scala//scala:providers.bzl", "declare_deps_provider")
load("//scala/scalatest/toolchain:toolchain.bzl", "scalatest_toolchain_deps")

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

toolchain(
name = "scalatest_toolchain",
toolchain = ":scalatest_toolchain_impl",
toolchain_type = ":scalatest_toolchain_type",
visibility = ["//visibility:public"],
)

declare_deps_provider(
name = "scalatest_deps_provider",
deps = [
"//external:io_bazel_rules_scala/dependency/scala/scalactic/scalactic",
"//external:io_bazel_rules_scala/dependency/scala/scalatest/scalatest",
],
)

declare_deps_toolchain(
name = "scalatest_toolchain_impl",
dep_providers = {
":scalatest_deps_provider": "scalatest_classpath",
},
visibility = ["//visibility:public"],
)

scalatest_toolchain_deps(
name = "scalatest_classapth",
provider_id = "scalatest_classpath",
visibility = ["//visibility:public"],
)
16 changes: 16 additions & 0 deletions scala/scalatest/toolchain/toolchain.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
load("//scala/private/toolchain_deps:toolchain_deps.bzl", "expose_toolchain_deps")

toolchain_type_label = "@io_bazel_rules_scala//scala/scalatest/toolchain:scalatest_toolchain_type"

def _scalatest_toolchain_deps(ctx):
return expose_toolchain_deps(ctx, toolchain_type_label)

scalatest_toolchain_deps = rule(
toolchains = [toolchain_type_label],
attrs = {
"provider_id": attr.string(
mandatory = True,
),
},
implementation = _scalatest_toolchain_deps,
)
2 changes: 1 addition & 1 deletion scala/support/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ scala_library(
],
visibility = ["//visibility:public"],
deps = [
"//external:io_bazel_rules_scala/dependency/scala/scala_xml",
"//external:io_bazel_rules_scala/dependency/scalatest/scalatest",
"//scala/private/toolchain_deps:scala_xml",
],
)
6 changes: 5 additions & 1 deletion scala/toolchains.bzl
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
def scala_register_toolchains():
native.register_toolchains("@io_bazel_rules_scala//scala:default_toolchain")
native.register_toolchains(
"@io_bazel_rules_scala//scala:deps_toolchain",
"@io_bazel_rules_scala//scala:default_toolchain",
)

def scala_register_unused_deps_toolchains():
native.register_toolchains(
"@io_bazel_rules_scala//scala:deps_toolchain",
"@io_bazel_rules_scala//scala:unused_dependency_checker_error_toolchain",
)
1 change: 1 addition & 0 deletions scala/toolchains/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading