Reputation: 307
I would like to have the following SBT build setup:
object MyBuild extends Build {
lazy val core = Project("core", file("core"))
.dependsOn(testkit % "test")
lazy val testkit = Project("testkit", file("testkit"))
.dependsOn(core % "compile")
}
When core
is the main module, including domain objects, and testkit
is a module for testing support code (builders, matchers, test drivers, etc.; not the tests themselves) that depends on the domain objects and other classes/utils in core
.
For this setup SBT gives a Cyclic reference
error, although there isn't really a cyclic dependency because of the use of different configurations (core
compiles, then testkit
compiles depending on core
, then core
test
is compiled depending on both).
I found a dirty way to get around this problem by replacing one of the dependsOn
use unmanagedClasspath
, for example:
.settings(unmanagedClasspath in Compile <+= (packageBin in (LocalProject("core"), Compile)))
This feels like a hack, and also makes sbt-idea
generate incorrect IntelliJ projects (among other things).
Any idea for a better solution? Does SBT support such a structure?
Upvotes: 6
Views: 456
Reputation: 11244
Sbt only checks projects when it looks for cyclic dependencies. It does not take configurations into account. The dependency check is executed in multiple places. One of the most important ones is in the constructor of LoadedBuild
.
It would require changes in a few places and probably some extensive testing. If you really want this feature I think it could theoretically be added.
The closest you can get to the way sbt itself adds the dependency:
lazy val core = project.in( file("core") )
.settings(
internalDependencyClasspath in Test <++=
exportedProducts in Compile in LocalProject("testkit")
)
lazy val testkit = project.in( file("testkit") )
.settings(
internalDependencyClasspath in Compile <++=
exportedProducts in Compile in LocalProject("core")
)
Upvotes: 2