Question: Inter-Project Dependencies
diesalbla opened this issue · 2 comments
This is an issue-discussion, but I have no inner SBT knowledge to know if this is feasible.
This is a great plugin for detecting the unused or undeclared entries in libraryDependencies
, the ones that SBT has to resolve through ivy
. However, there are Scala repositories that may be organised with a multi-project build, which may have scores of subprojects, which are also interconnected with interproject dependencies. This creates several challenges for explicit dependency declaration.
- First, the same non-explicit transitive dependencies between libraries, may also appear between subprojects, for example if a subproject A declares a dependency on
B
, andB
declares one onC
, butA
is invoking a function fromC
through its declared dependency onB
. - Second, and also between subprojects, it may happen that
A
declares dependency on subprojectB
that is not needed. - Finally, there is the interaction between library dependencies and dependencies between sub-projects. One sub-project
A
, which declares a dependency on a sub-projectB
, may be using a library dependency that it nether declares, nor is it a transitive library dependency of those that A declares, but which is a library dependency (explicit of transitive) of sub-projectB
.
The goal of this issue would be to investigate how these problems can be solved in this plugin.
I had a quick play around with what's available in sbt and zinc, and I think we could do something.
foo := {
println("Declared dependencies:")
println(buildDependencies.value.classpathRefs(thisProjectRef.value))
println("allExternalDeps:")
compile.in(Compile).value.asInstanceOf[sbt.internal.inc.Analysis].relations.allExternalDeps.foreach(println)
}
sbt:scalacache> cats-effect/foo
Declared dependencies:
List(ProjectRef(file:/Users/chris/code/scalacache/,coreJVM))
allExternalDeps:
scalacache.Async
scalacache.Mode
The first part of the output shows us that the cats-effect
project (in ScalaCache) declares a dependency on the coreJVM
project.
The second part shows that the project depends on 2 classes in other projects for its compilation. Both of these classes are in the coreJVM
project.
So a rough implementation would look like:
-
Get the list of projects that this project declares a dependency on
-
Compile all projects
-
Look in each project's target directory to build a data structure of which projects contain which classes. So a
Map[ProjectRef, Set[String]]
or something similar. (Maybe there's an easier way to get this info from sbt without having to traverse the target directory.) -
Use that data, along with the
allExternalDeps
, to work out which projects this project actually depends on for compilation. Let's call this resultactual dependencies
.
Then it's simply
undeclared dependencies = actual dependencies - declared dependencies
and
unused dependencies = declared dependencies - actual dependencies
This plugin is great to find unused dependencies on single project.
Any updates on how to find unused dependencies in multi-project using this plugin?