Gradle + Scala Plugin + Zinc 1.3.5 leaks Protobuf 3.7 to the compiler classpath - scala

While debugging compilation errors of the generated Protobuf code after upgrading a Scala project to Gradle 6 & Zinc 1.3.5 I found that the compiler classpath contains two versions of the protobuf jar - the one I need (3.9.x) and 3.7. The latter is a dependency of the Zinc.
What is the correct way to run Zinc Scala build in Gradle without leaking its own dependencies to the classpath?

This was resolved with sbt/zinc PR 799 that was merged and included in the 1.4.0 release of Zinc.
With this MR they started shading the protobuf dependency (see this commit).
Unfortunately, it's not currently possible to use this version of Zinc with Gradle as Gradle issue #15491 was never resolved (note the issue title mentions Zinc 1.4.3 but applies for all versions of Zinc after the 1.3.x series).
It doesn't look like there's any plans to address #15491 but it looks like the issue will get solved as a side-effect of PR 18001 which is actively being developed with the intention of adding Scala 3 support to Gradle (and also involves cleaning up various long standing issues classpath related issues).

Related

Error downloading org.scalameta:semanticdb-scalac_2.13.6:4.4.10

I recently upgraded to Scala 2.13.6 and I am seeing:
Error downloading org.scalameta:semanticdb-scalac_2.13.6:4.4.10
when I try to build.
I had a similar error when I upgraded to 2.13.5, but was able to add semanticdbVersion := "4.4.11" to build.sbt to get it to work.
This is not working this time.
You can check on the central Maven repository which versions of the project is available for which version of Scala:
https://mvnrepository.com/artifact/org.scalameta/semanticdb-scalac
The only version built for Scala 2.13.6 is 4.4.18 as of today.
This info is probably also available on their GitHub release note oages
I assume you are using the sbt-scalafix plugin in your build. This kind of error can happen if you update the scala version before you update the scalafix plugin to the latest version because the semanticdb version is usually set via this setting in your build.sbt (At least this is the official recommendation):
semanticdbVersion := scalafixSemanticdb.revision
In case of scala v2.13.6 I needed to bump the version of sbt-scalafix to v0.9.28 to fix the error you described.

Dependency upgrade along with transitive dependencies

I have quite a big Play/Akka project on Scala 2.11 with literally dozens of dependencies, for which we need to migrate to all new stack: newest Play, Akka, Scala etc.
But along the upgrade way, our team constantly facing unexpected issues after certain lib update that another lib has transitive dependency on it, which was evicted and suddenly starting to crash in runtime somewhere in internals. E.g. play-pac4j has transitive dependency on Play, which we forgot to upgrade properly after Play upgrade from 2.5 to 2.7.
Question: is there any sbt plugin, which can say in advance which dependencies I need to change to which version version, if I want to update dependency group % name from version-x to version-y?
I'm aware of sbt-dependency-graph plugin and we are using, but I want some automation. Meaning: sbt-dependency-graph has whatDependsOn command, but I don't want to manually verify which version is compatible with transitive dependency i want to go to.
Thank you.

Understanding eclipse maven dependency hierarchy

I want to understand the dependencies for a multi-module maven project and for that referred to eclipse dependency hierarchy.
I did understand fairly, however some of the things I am not able to understand at all.
Below is the screen shot.
The things which I didn't understand are:
--> managed from 1.0.2 [Compile}
--> managed from 1.0.2 (omitted for conflict with 1.0.0) [Compile]
I did search online but I got information in traces. Can anyone help me understand what they mean in easy to understand?
Thanks.
Maven builds a flat classpath from the dependency tree each for compiling ([compile]), for testing, and for running.
In a flat classpath, unlike OSGi, a dependency can only exist in one version. In your cropped screenshot, there is on the second level among other things:
kafka-streams 1.0.2 and
kafka-clients 1.0.0.
kafka-streams 1.0.2 requires kafka-clients 1.0.2 which conflicts to kafka-clients 1.0.0. Therefore kafka-streams 1.0.2 is omitted for conflicts with 1.0.0 even if the version 1.0.2 is required here ("managed from 1.0.2").
More detailed:The classpath which is used to compile or run a plain Java application is flat: all required libraries are globally specified as an ordered list. It is not possible to use a library of a specific version for one package and for another package the same library in a different version.In Maven dependencies builds a tree: each dependency might have its own dependencies. Maven maps the tree of dependencies to the classpath, an ordered list of libraries. If in the Maven dependencies tree the same library exists in different versions, it is not possible to create a flat classpath. This is a conflict.This conflict is resolved by picking one version and omitting all other versions. At the place where the picked version is used instead of the required version, (managed from <required but not picked version>) and (omitted for conflict with <picked version to use instead>) is displayed.In addition, Maven can create different classpaths to compile, to test or to run a Java application via so-called scopes. The [compile] scope is the default scope for using a library in all tasks: compiling, testing and running.
Make sure that the versions specified in the pom.xml file are compatible with each other (which is not yet the case in your screenshot): you have to upgrade kafka-clients from 1.0.0 to 1.0.2 (or downgrade the other libraries).

Cross build scala using gradle

I've got a Scala project that is built with Gradle. The Scala code is source compatible with scala 2.9 and 2.10 and I'd like to cross build it to both major Scala versions. Does Gradle support this?
For example, my gradle project will have a single module:
build.gradle
src/main/scala/foo.scala
and I'd like the resulting published jars to be:
org-foo_2.9-0.1.jar (with dependency on scala-library 2.9)
org-foo_2.10-0.1.jar (with dependency on scala-library 2.10)
Gradle's Scala plugin doesn't currently support cross-building. It's possible to implement it yourself, though. In my Polyglot Gradle talk, I presented a proof-of-concept.
I am searching for a good example of this. The Gradle manual doesn't mention how to specify Scala version but looking at the source code for the Scala plugin it seems to infer it from the Scala library jar that you specify.
The best example I could find is the Apache Kafka build system. It specifies the Scala version and then uses some additional logic to resolve the correct version of the Scala libraries. It also uses some logic to attach the correct label to the jars its builds to correspond to the correct Scala version.
This feels like a lot of work and something that the build system should do for you like in SBT.

Sbt plugin binary incompatibility

I am using the sbtantlr plugin and adapting it to use antlr v3.5. It used to work fine with scala 2.9.2.
Today I upgraded my scala to 2.10.0.
And I compiled the plugin in 2.10.0 and put the plugin 'sbtantlr.jar' in the 'lib' directory of my main scala project.
SBT stopped working with this error message:
Binary incompatibility in plugins detected.
I revert the compiler version to 2.9.2 and it works fine.
Is it because SBT (the official binary release) was built with 2.9? Where can I find the information?
Yes, sbt 0.12.x are built with 2.9x and all plugins need to match the binary Scala version.
To add more information to what Yann said, Scala only guarantees compatibility between minor versions. That is, code compiled with any 2.8.x version is compatible with code compiled with any other 2.8.x version, but no code compiled with 2.8.x is compatible with code compiled by a 2.9.x version.
Now, SBT is a Scala application, and both the plugins and build configuration are libraries to it. SBT 0.12.x was compiled with Scala 2.9.x, so all plugins and project build configuration must also be compiled with Scala 2.9.x.
The project itself can be compiled with any version, as SBT does not need to interact with it.