rules_scala icon indicating copy to clipboard operation
rules_scala copied to clipboard

per-target dependency options

Open dsilvasc opened this issue 4 years ago • 5 comments

I have scala targets that rely on dependency_mode = "plus-one" to compile. For example, one target depends on circe-derivation and uses the deriveEncoder macro from it, which expands to a reference to the type cats.Contravariant, which isn't (and shouldn't be?) on my target's deps list.

I also have other bazel projects consuming my project. Those consumers need to also use dependency_mode = "plus-one" or they won't be able to compile my targets. That's a bummer for them, because they might want/need another dependency mode for their own targets, or for some other repo they consume.

Would it be possible to make dependency options (dependency_mode, strict_deps_mode, dependency_tracking_method) into attributes for scala_library and scala_binary targets, similar to how scalacopts, scalac_jvm_flags, and unused_dependency_checker_mode already are?

dsilvasc avatar Jun 28 '20 21:06 dsilvasc

Technically this is doable but I’m not sure I think it’s a good idea. Two initial thoughts:

  1. Bazel is very biased towards uniformity and global shared configurations. External workspaces can be thought of as merely a way to patch together directories to a single mono repo. This means IMHO that per target configurations are the exception and not the rule.
  2. Technically your suggestion can be problematic for people using persistent workers since it will either invalidate them or mean that using this attribute will opt you out from persistent workers. This might be ok if this is a conscious decision but I fear people won’t understand using this attribute will cause this.

Maybe this means that root/library workspaces need to support both dependency modes? For example this can be done by adding the additional dependency in your build file and adding it to ignored.

Finally I’m not 100% sure I’m against your suggestion but it sounds problematic.

@Jamie5 @liucijus wdyt?

ittaiz avatar Jun 29 '20 03:06 ittaiz

Do the existing target attributes scalacopts, scalac_jvm_flags, and unused_dependency_checker_mode have the same impact on uniformity and persistent worker reuse as the other dependency options would?

The trouble is that applying a single set of options across all workspaces breaks composition. If I use build_stack_rules_proto and build my workspace with

--extra_toolchains=@io_bazel_rules_scala//scala:minimal_direct_source_deps

then my build fails with:

ERROR: /Users/dsilva/Snapchat/Dev/tmp/_bazel_dsilva/c65e62889b3448fbc3eab4f5ca51b208/external/build_stack_rules_proto/scala/BUILD.bazel:66:1: scala @build_stack_rules_proto//scala:compiler_plugin failed (Exit 1): scalac failed: error executing command   | (cd /Users/dsilva/Snapchat/Dev/tmp/_bazel_dsilva/c65e62889b3448fbc3eab4f5ca51b208/execroot/example &&
  | exec env -
  | bazel-out/host/bin/external/io_bazel_rules_scala/src/java/io/bazel/rulesscala/scalac/scalac @bazel-out/host/bin/external/build_stack_rules_proto/scala/compiler_plugin_scalac_worker_input)   | Execution platform: @local_config_platform//:host   | error: Target '@com_google_protobuf//:protobuf_java' is specified as a dependency to @build_stack_rules_proto//scala:compiler_plugin but isn't used, please remove it from the deps.

dsilvasc avatar Jun 29 '20 11:06 dsilvasc

They actually might have the same impact. I'll try to take a look at the code later and reply.

ittaiz avatar Jun 29 '20 12:06 ittaiz

I think this is somewhat similar to #1046 . I kind of lean towards that generally one would wish to consume external deps as jars. But I think in the other ticket there were some questions to be resolved (I know the tickets don't ask for exactly the same thing but they seem kind of similar)

Jamie5 avatar Jun 30 '20 01:06 Jamie5

rules_java and build_stack_rules_proto do not vend their scala code as jars :)

https://github.com/bazelbuild/rules_scala/blob/056d5921d2c595e7ce2d54a627e8bc68ece7e28d/scala/support/BUILD#L5 https://github.com/stackb/rules_proto/blob/b2913e6340bcbffb46793045ecac928dcf1b34a5/scala/BUILD.bazel#L68

I can see the argument for consuming public libraries as maven jars: the ecosystem's already there and binary artifacts isolate consumers from the library's build logic. On the other hand, consuming some libraries with fragile ABIs (like guava) can be scary and consuming from source alleviates the fear of NoSuchMethodError or ClassNotFoundException at runtime.

For private libraries, I suppose different teams could still have different requirements. Or one might want the strictest settings possible throughout an organization's many repos, with exceptions where that doesn't work (macros, maybe other cases).

dsilvasc avatar Jun 30 '20 01:06 dsilvasc