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

Single deps toolchain #2

Closed
wants to merge 6 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
40 changes: 40 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,41 @@ 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"],
)

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",
"@io_bazel_rules_scala//scala/scalatest/toolchain:scalatest_deps_provider": "scalatest_classpath",
"@io_bazel_rules_scala//scala_proto/toolchain:scalapb_compile_deps_provider": "pb_compile_deps",
"@io_bazel_rules_scala//scala_proto/toolchain:scalapb_grpc_deps_provider": "grpc_deps",
"@io_bazel_rules_scala//specs2/toolchain:specs2_deps_provider": "specs2",
"@io_bazel_rules_scala//specs2/toolchain:specs2_junit_deps_provider": "specs2_junit",
},
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
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),
},
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"],
)
30 changes: 30 additions & 0 deletions scala/private/toolchain_deps/toolchain_deps.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
load("@io_bazel_rules_scala//scala:providers.bzl", "DepsInfo")

def _files_of(deps):
files = []
for dep in deps:
files.append(dep[JavaInfo].transitive_compile_time_jars)
return depset(transitive = files)

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

def java_info_for_deps(deps):
deps_files = _files_of(deps).to_list()
deps_providers = [JavaInfo(output_jar = jar, compile_jar = jar) for jar in deps_files]
return [java_common.merge(deps_providers)]

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
deps_files = _files_of(deps).to_list()
deps_providers = [JavaInfo(output_jar = jar, compile_jar = jar) for jar in deps_files]
return [java_common.merge(deps_providers)]
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",
],
)
26 changes: 26 additions & 0 deletions scala/scalatest/toolchain/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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/private/toolchain_deps:toolchain_dep_rules.bzl", "common_toolchain_deps")

declare_deps_provider(
name = "scalatest_deps_provider",
visibility = ["//visibility:public"],
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"],
)

common_toolchain_deps(
name = "scalatest_classapth",
provider_id = "scalatest_classpath",
visibility = ["//visibility:public"],
)
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 @@

96 changes: 96 additions & 0 deletions scala/toolchains/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Toolchains for Deps

## Exporting deps via toolchains

Toolchains can be used to provide dependencies indirectly. For rules which are not aware of specific toolchains,
dependencies can be provided by adding to deps a target which knows how to export from a toolchain. Eg.:
```python
# target which exports toolchain deps from provider with ID "compile_deps"
proto_toolchain_deps(
name = "default_scalapb_compile_dependencies",
provider_id = "compile_deps",
visibility = ["//visibility:public"],
)

# provider declaration
declare_deps_provider(
name = "scalapb_grpc_deps_provider",
deps = ["@dep1", "@dep2"],
visibility = ["//visibility:public"],
)

# toolchain declaration:
toolchain_type(
name = "proto_toolchain_type",
visibility = ["//visibility:public"],
)

toolchain(
name = "proto_toolchain",
toolchain = ":proto_toolchain_impl",
toolchain_type = ":proto_toolchain_type",
visibility = ["//visibility:public"],
)

declare_deps_toolchain(
name = "proto_toolchain_impl",
dep_providers = {
":scalapb_compile_deps_provider": "compile_deps",
":scalapb_grpc_deps_provider": "grpc_deps"
},
visibility = ["//visibility:public"],
)
```

To define toolchain deps with deps exporting, the follwoing steps need to be taken:
1. Declare dep providers with `declare_deps_provider`
2. Define `toolchain_type`, declare toolchain with infra helper `declare_deps_toolchain`, wire them up with `toolchain`
3. Create rule exposing toolchain deps using infra helper `expose_toolchain_deps`
4. Declare deps targets
5. Use deps targets instead of bind targets!

## Reusable infra code to define toolchains for dependencies

### Reusable symbols
- provider `DepsProvider` - provider with a field `deps`, which contains dep list to be provided via toolchain
- rule `declare_deps_provider` - used to declare target with `DepsProvider`. Eg.:
```python
declare_deps_provider(
name = "scalapb_grpc_deps_provider",
deps = ["@dep1", "@dep2"],
visibility = ["//visibility:public"],
)
```
- rule `declare_deps_toolchain` - used to declare toolchains for deps providers. Eg.:
```python
declare_deps_toolchain(
name = "proto_toolchain_impl",
dep_providers = {
":scalapb_compile_deps_provider": "compile_deps",
":scalapb_grpc_deps_provider": "grpc_deps"
},
visibility = ["//visibility:public"],
)

```
Attribute `dep_providers` is maps dep provider label to an id used for indirection in toolchain exporting rules

- `def expose_toolchain_deps(ctx, toolchain_type_label)` - helper to export export deps from toolchain. Intended to be
used when defining toolchain deps exporting rules. Eg.:
```python
load("//scala/private/toolchain_deps:toolchain_deps.bzl", "expose_toolchain_deps")

def _toolchain_deps(ctx):
toolchain_type_label = "@io_bazel_rules_scala//scala_proto/toolchain:proto_toolchain_type"
return expose_toolchain_deps(ctx, toolchain_type_label)

proto_toolchain_deps = rule(
implementation = _toolchain_deps,
attrs = {
"provider_id": attr.string(
mandatory = True,
),
},
toolchains = ["@io_bazel_rules_scala//scala_proto/toolchain:proto_toolchain_type"],
)
```
16 changes: 16 additions & 0 deletions scala/toolchains/toolchains.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
load("@io_bazel_rules_scala//scala:providers.bzl", "DepsInfo")

def _deps_toolchain(ctx):
toolchain_info = platform_common.ToolchainInfo(
dep_providers = ctx.attr.dep_providers,
)
return [toolchain_info]

declare_deps_toolchain = rule(
attrs = {
"dep_providers": attr.label_keyed_string_dict(
providers = [DepsInfo],
),
},
implementation = _deps_toolchain,
)
10 changes: 6 additions & 4 deletions scala_proto/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ toolchain(
visibility = ["//visibility:public"],
)

java_library(
load("//scala/private/toolchain_deps:toolchain_dep_rules.bzl", "common_toolchain_deps")

common_toolchain_deps(
name = "default_scalapb_compile_dependencies",
provider_id = "pb_compile_deps",
visibility = ["//visibility:public"],
exports = DEFAULT_SCALAPB_COMPILE_DEPS,
)

java_library(
common_toolchain_deps(
name = "default_scalapb_grpc_dependencies",
provider_id = "grpc_deps",
visibility = ["//visibility:public"],
exports = DEFAULT_SCALAPB_GRPC_DEPS,
)
Loading