Dependency Resolution in Root Project of Pure Cross Project
bpholt opened this issue · 2 comments
The cats-scalatest project set up a Pure
cross project for JVM and JS platforms on several Scala versions. Dependency resolution seems to work fine throughout the matrix, except for the root project. The broken config is available for reference on the scalajs-cross-pure-broken
branch.
sbt:cats-scalatest> projects
[info] In file: ~/cats-scalatest/
[info] * cats-scalatest
[info] catsScalatestJS
[info] catsScalatestJVM
Running sbt test
or sbt compile
results in compilation failures in the root (cats-scalatest
) project that indicate missing dependencies, e.g.:
[info] Compiling 5 Scala sources to ~/cats-scalatest/target/scala-2.12/classes ...
[error] ~/cats-scalatest/src/main/scala/cats/scalatest/EitherMatchers.scala:3:12: object scalatest is not a member of package org
[error] import org.scalatest.matchers.{BeMatcher, MatchResult, Matcher}
[error] ^
Running sbt catsScalatestJS/compile
or sbt catsScalatestJVM/compile
both work fine.
I would have expected compile
or cats-scalatest/compile
to call the platform-specific projects' compile
tasks, not execute one of its own.
FWIW, I noticed that setting the Scala version using ++
excludes the core project:
sbt:cats-scalatest> ++ 2.11.12 -v
[info] Setting Scala version to 2.11.12 on 2 projects.
[info] Switching Scala version on:
[info] catsScalatestJVM (2.11.12, 2.12.10, 2.13.1)
[info] catsScalatestJS (2.11.12, 2.12.10, 2.13.1)
[info] Excluding projects:
[info] * cats-scalatest (2.12.10)
[info] Reapplying settings...
[info] Set current project to cats-scalatest (in build file:~/cats-scalatest/)
Maybe cats-scalatest
should be excluded more broadly, and it's not for some reason?
We worked around the issue by switching to a Full
cross project on the primary branch. The broken config is preserved on the scalajs-cross-pure-broken
branch. (There is no platform-specific code for this project, so ideally it will switch back to Pure
once we figure out what's going wrong.)
I had this occur too. I think it is due to the combination of .crossType(Pure)
and .in(file("."))
.
What I think happens is sbt-crossproject
creates three subprojects (xxxJVM, xxxJS and the "shared" project xxx). However, the "shared" xxx project conflicts with SBTs default "root" project (because SBT doesn't recognize a crossProject(...).in(file("."))
as being a root project, unlike project.in(".")
)
Thus, settings added to the crossProject
don't get propagated to the "shared" project as it's "overwrriten" by SBT's aggregate root. This also breaks the .dependsOn
relationships that sbt-crossproject
usually sets up.
I think the best workarounds are either to use CrossType.Full
or to move your code into a subproject (ie, don't use .in(file("."))
)
That is a general problem with root projects in sbt. There's nothing sbt-crossproject can do about it.
Remember that crossProject
is only a builder for two project
s: one for JVM and one for JS. The third project that is actually in "."
is the auto-generated root project, which has nothing to do with sbt-crossproject
. By default it aggregates all projects in the build but also exists on its own. In a Pure
setting, the directory layout will be such that sources of the cross-project also appear as sources of the root project, but none of the settings or any of the other configurations apply.
There are several workarounds:
- Never call any task (but
clean
) on the root project - Put your pure cross-project in a subdirectory
- Redefine the tasks you're interested to call so that they do nothing in the root project (e.g.,
Compile / compile := sbt.internal.inc.Analysis.Empty
); this is tedious
There are probably others.
Anyway, I'm going to close this issue because, as I said, there's nothing we can do about it.