-
-
Notifications
You must be signed in to change notification settings - Fork 354
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
Build fails when using scala ivydep in scalamodule with java moduledep #860
Comments
On a first glance, it looks like when resolving the ivy deps of |
2 workaround come to my mind:
|
as suggested by @lefou a workaround is to make javaapi a |
We could transform ivy-deps of other modules to be just "java" dependencies without any cross-version semantic. This can of course lead to issues too. Thinking a bit more about this issue, I think we need some more safe-guarding when using transitive dependencies of |
I currently hit this issue again when working on a polyglot project, which has Java, Java + AspectJ, Scala and Kotlin modules. But I think this issue will hit us more frequently now, when people start the try out the new Scala 2.13 - Scala 3 forward compatibility feature. I think the fact, that we bind the cross value for transitive dependencies in the dependent module is wrong. Instead, each modules should resolve the cross- and platform placeholder by itself. This has the downside, that it is possible to bring more that one Scala-binary-version-line into the dependency tree. We probably should invent some other mechanism to check for consistency, or maybe we can offload that to coursier (I don't know how)? |
I think each module should implement some checks, e.g. a |
I'm facing probably another instance of this issue in Ammonite, where Scala 3 dependencies are converted into Scala 2.13 dependencies when we try to make a Scala 2.13 module depend on a Scala 3 module. For example, given this project: import mill._
import mill.scalalib._
object scala213 extends ScalaModule {
def scalaVersion = "2.13.6"
def moduleDeps = Seq(scala3)
def scalacOptions = Seq("-Ytasty-reader")
}
object scala3 extends ScalaModule {
def scalaVersion = "3.0.2"
def ivyDeps = Agg(
ivy"com.lihaoyi::upickle:1.4.0"
)
} the ivyDepsTree is:
While in Sbt the dependencies are resolved using the lazy val scala213 = project
.settings(
scalaVersion := "2.13.6",
scalacOptions += "-Ytasty-reader"
)
.dependsOn(scala3)
lazy val scala3 = project
.settings(
scalaVersion := "3.0.2",
libraryDependencies += "com.lihaoyi" %% "upickle" % "1.4.0"
)
|
As stated [here](com-lihaoyi/mill#860 (comment)) Mill doesn't handle correctly the Scala 2.13 modules depending on Scala 3 modules. This happens because dependencies are resolved at using the suffix from the leaf module instead of every module resolving its dependencies on its own. So if a module compiled with Scala 3 depends on libraries with the `_3` suffix, once another module using Scala 2.13 depends on it all the dependencies get transformed to use the `_2.13` suffix. Sbt maintains instead the original suffixes. This commit introduces a preprocessing on the dependencies to convert them to manually add the `_3` suffix
I haven't looked at the code right now, but we have a defined way to translate each mill-dependency to a coursier-dependency. I think it's |
I now have a fully working PR, which fixes this issue. It comes with a slight API change. I'd welcome any review or feedback on it. If there are no objections, I'm going to merge it in the next days. |
`mill.scalalib.Dep` represents a generic dependency, which include potential cross-compilation properties. E.g. it knows whether it is specific to a `platform` but it does not specify the platform. And it knows whether it is specific to a Scala binary or full version, but it does not specify the exact Scala version. This mean we can define a `Dep` without knowing those context. In this PR I introduce a new type `mill.scalalib.BoundDep`, which is kind-of a `Dep` where all these potential open context bindings are bound to an exact context. There is no further cross-resolution necessary nor possible. By having a separate type, we always know with what kind of dependency we work. Also, we can be explicit about the "when" the binding happens. When mixing dependencies of multiple modules, we also mix contexts. Until this PR, we had no way to get it right, as `Dep`s could come from different contexts. Now, we can safely mix `BoundDep`s as they are already context-bound. We could encode the bound-state in the `Dep`, but this would result in only a dynamic property. To ensure a resolved state, we always would need to run some runtime checks. Also, it could lead to situations, where we need a resolved dep, but have not the proper context to do the resolution. This is exactly what I implemented in the initial attempt, but it didn't worked out very well. With the separated types, it is always clear from the API, what kind of dependency we expect. We could also just resolve to a `coursier.Dependency`, but that would loose the `force` flag. Also, we want to rather decouple our API from the coursier API, which seem easier when we avoid to hand over direct coursier API to the user. I `@deprecated` the existing `CoursierModule.resolveCoursierDependency` and bases the new `CoursierModule.bindDependency` on this old task. This should ease the transition. It's up for revisit, when we decouple from coursier API altogether. This fixes #860.
Given
attempting to compile will yield
on 0.6.2
The text was updated successfully, but these errors were encountered: