generating jacoco code coverage report for all sub modules - scala

I'm trying to integrate JaCoCo in my Play Scala project, I want it to run code coverage for all sub modules in one report.
When I add the "jacoco.settings" to the root project, jacoco doesn't recognize the tests for the sub modules. in order to do so, I configured the jacoco setting for each one of the modules, and then run the coverage for each one of them (see comment out code). the result is one report for each module.
I would like to generate one report for the whole project, any Idea what can I do?
object PlutusBuild extends Build {
lazy val root = Project(id = "Plutus", base = file("."))
.aggregate(common, importer, crawler, ref_webapp)
.settings(graphSettings: _*)
.settings(jacoco.settings: _*)
lazy val common = Project(id = "Plutus-Common", base =
file("common"))
/*.settings(jacoco.settings: _*)*/
lazy val importer = Project(id = "Plutus-Importer", base =
file("importer")).dependsOn(common)
/*.settings(jacoco.settings: _*)*/
lazy val crawler = Project(id = "Plutus-Crawler", base =
file("crawler")).dependsOn(common).
configs(Atmos).settings(atmosSettings:_*)
/*.settings(jacoco.settings: _*)*/
...
Thanks...

I take it you're using jacoco4sbt? This was recently fixed in version 2.1.4.
You need to use this setting:
Keys.fork in jacoco.Config := true

Related

Different project on the same base-directory (or share a single file between projects)

My initial setup had two separate projects (sbt 1.2.6);
a web app (huge codebase, lot of dependencies, slow compile)
a command-line app (basically one file with 3-4 separate dependencies)
The feature request came in; we should show the "valid" values in the command line app. The valid values are in an enum in the web app. So I fired up the sbt documentation and came up with an idea which looked like this;
//main webapp
lazy val core = project
.in(file("."))
.withId("core") //I tried this just in case, not helped...
//... here comes all the plugins and deps
//my hack to get a single-file compile
lazy val `feature-signer-helper` = project
.in(file("."))
.withId("feature-signer-helper")
.settings(
target := { baseDirectory.value / "target" / "features" },
sources in Compile := {
((scalaSource in Compile).value ** "Features.scala").get
}
)
//the command line app
lazy val `feature-signer` = project
.in(file("feature-signer"))
.dependsOn(`feature-signer-helper`)
.settings(
libraryDependencies ++= signerDeps
)
The problem is that it seems like, that whatever the last lazy val xxx = project.in(file(y)) that will be the only project for the y dir.
Also, I don't want to move that one file to a separate directory structure... And logically the command line app and the web app are not "depends on" each other, they have different dependencies (and really different build times).
My questions are;
is there any quick-win in this situation? (I will copy the file worst-case...)
why we have this rich project and source settings if I can't bind them to the same dir?
EDIT:
The below code can copy the needed file (if you have the same dir structure). I'm not super happy with it, but it works. Still interested in other methods.
import sbt._
import Keys._
object FeaturesCopyTask {
val featuresCopyTask = {
sourceGenerators in Compile += Def.task {
val outFile = (sourceManaged in Compile).value / "Features.scala"
val rootDirSrc = (Compile / baseDirectory).value / ".." / "src"
val inFile: File = (rootDirSrc ** "Features.scala").get().head
IO.copyFile(inFile, outFile, preserveLastModified = true)
Seq(outFile)
}.taskValue
}
}
lazy val `feature-signer` = project
.in(file("feature-signer"))
.settings(
libraryDependencies ++= signerDeps,
FeaturesCopyTask.featuresCopyTask
)
I would have the tree be something more like
+- core/
+- webapp/
+- cli/
core is the small amount (mostly model type things) that webapp and cli have in common
webapp depends on core (among many other things)
cli depends on core (and not much else)
So the build.sbt would be something like
lazy val core = (project in file("core"))
// yadda yadda yadda
lazy val webapp = (project in file("webapp"))
.dependsOn(core)
// yadda yadda yadda
lazy val cli = (project in file("cli"))
.dependsOn(core)
// yadda yadda yadda
lazy val root = (project in file("."))
.aggregate(
core,
webapp,
cli
)

Intellj doesn't see changes in multi project sbt

I have a multi module sbt project. When I change some source code in a module, other modules don't see the changes in IntelliJ .
When I try to navigate, it goes to declaration, instead of navigating to the source it navigates to compiled jar file.
It works fine when I remove the jar from library dependencies in project settings. I think because it recompiles so works fine till next change. And sbt compiles works fine but I guess problem because of Build.scala settings, project dependencies can have order issues. Here is the dependencies;
lazy val root = Project(id = "xx-main", base = file("."), settings = commonSettings)
.aggregate(utils, models, commons, dao, te)
.dependsOn(utils, models, commons, dao)
lazy val utils = Project(id = "xx-utils", base = file("xx-utils"))
.settings(commonSettings: _*)
lazy val commons = Project(id = "xx-commons", base = file("xx-commons"))
.settings(commonSettings: _*)
.dependsOn(utils, models)
lazy val models =
Project(id = "xx-models", base = file("xx-models"), settings = commonSettings)
.dependsOn(utils)
lazy val dao = Project(id = "xx-dao", base = file("xx-dao"))
.settings(commonSettings: _*)
.dependsOn(utils, models)
lazy val te = Project(id = "xx-te", base = file("xx-te"))
.settings(commonSettings: _*)
.dependsOn(utils, models, dao, commons)

Deep nesting of project folder in a SBT multi-project project

I have an SBT project that aggregates over multiple projects like this:
object ClientCore extends Build {
/**
* This is the root project
*/
lazy val rootProj = Project(id = "clientcore", base = file(".")) aggregate(
utilsProj,
commonUiProj,
spatialMathProj,
sessionManagerProj,
lobbyProj,
)
/**
* This is a utils library
*/
lazy val utilsProj = Project(id = "utils", base = file("Utils"))
/**
* A shared library for UI elements
*/
lazy val commonUiProj = Project(id = "commonui", base = file("CommonUI"))
/**
* This is a spatial math library
*/
lazy val spatialMathProj = Project(id = "spatialmath", base = file("SpatialMath"))
lazy val sessionManagerProj = Project(id = "sessionmanager", base = file("sessionManager"),
settings = buildSettings ++ assemblySettings) settings(
outputPath in assembly := new File(s"$outDir\\SessionManagerClient.jar"),
jarName in assembly := "SessionManagerClient.jar",
test in assembly := {}
) dependsOn(utilsProj)
lazy val lobbyProj = Project(id = "lobby", base = file("Lobby"),
settings = buildSettings ++ assemblySettings) settings(
outputPath in assembly := new File(s"$outDir\\Lobby.jar"),
jarName in assembly := "Lobby.jar",
test in assembly := {}
) dependsOn(utilsProj)
}
For some reason some of the projects end up with a deep nesting of 'project' folders. For example Utils might look like: 'Util/project/project/project/project/...
I'm using Intellij's SBT plugin to sync the presentation but managing the project with SBT. I'm not certain whether this is an SBT issue or an Intellij one.
Thanks for any help you can provide.
Kurt
This is an IntelliJ issue (among many others related to the SBT plugin...)
I think you may have refreshed your config somewhere before defining a module and adding that module to the root project aggregates, which has a tendency to make a mess in IntelliJ.
This can be fixed in IntelliJ:
detach your project from IntelliJ
restart IntelliJ
reimport your project

How to enable sbt plugins of root project for all subprojects?

I have a project/build.scala file that defines a root project and a bunch of sub projects:
lazy val root = Project(
id="root",
base=file(".")).aggregate(subA, subB).enablePlugins(MyPlugin)
lazy val subA = Project(
id="subA",
base=file("a"))
lazy val subB = Project(
id="subB",
base=file("b"))
How do I make MyPlugin available in subA and subB without specifying it on each of them? I just want them to inherit the plugins from the root project.
Someone in IRC suggested overriding projects in my build object in build.scala:
override def projects = super.projects map { _.enablePlugins(...) }

SBT create sub-projects using a collection

I've been searching if this is possible for a while with little success.
Using SBT, can you create a sub-project programmatically, without explicitly assigning each project to it's own val?
My current project structure looks something like this:
root/
common/ <--- This is another sub-project that others dependOn
project/
build.scala
src/main/scala
apps/ <--- sub-projects live here
Sub1/
Sub2/
Sub1 and Sub2 are both their own SBT projects.
My first attempt to link these projects together looked like this:
// root/project/build.scala
import sbt._
import Keys._
object build extends Build {
lazy val common = project /* Pseudo-code */
val names = List("Sub1", "Sub2")
lazy val deps = names map { name =>
Project(id = name, base = file(s"apps/$name")).dependsOn(common)
}
lazy val finalDeps = common :: deps
lazy val root = project.in(file(".")).aggregate(finalDeps.map(sbt.Project.projectToRef) :_*)
.dependsOn(finalDeps.map(ClassPathDependency(_, None)) :_*)
}
However, because SBT uses reflection to build it's projects and sub-projects, this doesn't work.
It only works if each sub-project is stated explicitly:
lazy val Sub1 = project.in(file("apps/Sub1"))
So the question:
Is there a way to programmatically build sub-project dependencies in SBT?
Sbt allows for making a build definition for the build itself:
http://www.scala-sbt.org/release/docs/Getting-Started/Full-Def.html
You can try creating a project/project/build.scala file that contains a source generator, something like this:
// project/project/build.scala
sourceGenerators in Compile <+= sourceManaged in Compile map { out =>
Generator.generate(out / "generated")
}
EDIT: You should implement the Generator object yourself.
This source generator will in turn scan the topmost apps folder and create a source for an object that contains all the subprojects.
// project/subprojects.scala
// This is autogenerated from the source generator
object Subprojects{
lazy val Sub1 = project.in(file("apps/Sub1"))
lazy val Sub2 = project.in(file("apps/Sub2"))
lazy val all = Seq(Sub1,Sub2)
}
Now in your main build.scala just write:
// project/build.scala
lazy val root = project.in(file("."))
.aggregate(Subprojects.all.map(sbt.Project.projectToRef) :_*)
.dependsOn(Subprojects.all.map(ClassPathDependency(_, None)) :_*)
I didn't run all this through a compiler so some errors are possible but the principle should work.
EDIT: I created a repo on Github where I implemented the solution. Go there and see how it is done.
https://github.com/darkocerdic/sbt-auto-subprojects