2

I maintain a open source bitcoin library called bitcoin-s. If you look at the build.sbt file you will see that the testkit project depends on the rpc project, and the rpc project depends on the testkit project as a publish dependency inside of our Deps.scala file.

This is unfortunate because if we change the api in the rpc project at all, we have to publish a new testkit snapshot to be able to reflect the changes in the rpc api, and then run tests in the rpc project. You can see a more detailed guide of the build process here

I would like to make it so that we can just have each project depend on each other in build.sbt with something like this:

lazy val rpc = project .in(file("rpc")) .enablePlugins() .settings(commonSettings: _*) .dependsOn( core, testkit % "test->test" ) .settings( testOptions in Test += Tests.Argument("-oF") ) lazy val bench = project .in(file("bench")) .enablePlugins() .settings(assemblyOption in assembly := (assemblyOption in assembly).value .copy(includeScala = true)) .settings(commonSettings: _*) .settings( libraryDependencies ++= Deps.bench, name := "bitcoin-s-bench" ) .dependsOn(core) lazy val eclairRpc = project .in(file("eclair-rpc")) .enablePlugins() .settings(commonSettings: _*) .dependsOn( core, rpc testkit % "test->test" ) lazy val testkit = project .in(file("testkit")) .enablePlugins() .settings(commonSettings: _*) .dependsOn( core, rpc, eclairRpc ) 

However this creates a circular dependency between the projects which leads to a stackoverflow when loading build.sbt.

Is there any way to avoid this? We have a very complicated process of publishing the dependency currently which ends up depending on SNAPSHOTS of the project (not full releases) as the bitcoinsV

2 Answers 2

2
+200

Break the dependency cycle.

One way to do that might be to break rpc into separate rpc and rpc-test projects, so your dependency graph is

rpc-test >--+--> testkit >--+ \ \ +---------------+--> rpc 
Sign up to request clarification or add additional context in comments.

Comments

0

Did you try something like this but I'm not really sure if this will do the work.

lazy val middleProject = (project in file("middle-project")) .settings( name := "middle-project", libraryDependencies ++= Seq( // Dependencies here.. ) ) .aggregate(project1, project2) .dependsOn(project1, project2) lazy val project1 = (project in file("project-1")) .settings( name := "project-1", libraryDependencies ++= Seq( // Dependencies here... ) ) lazy val project2 = (project in file("project-2")) .settings( name := "project-2", libraryDependencies ++= Seq( // Dependencies here... ) ) 
  • Aggregation means that running a task on the aggregate project will also run it on the aggregated projects.
  • The middle project will do the process and serve as connector to those two projects.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.