Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent SBT to include test dependencies into the POM

Tags:

scala

sbt

I have a small utilities scala build with test classes under a dedicated test folder. Compiling and then publish-local creates the package in my local repository.

As expected, the test folder is automatically excluded from the local jar of the utilities package.

However, the resulting POM still contains the related dependencies as defined in the sbt. The SBT dependencies:

libraryDependencies ++= Seq(
  "org.scalactic" %% "scalactic" % "3.0.0" % Test,
  "org.scalatest" %% "scalatest" % "3.0.0" % Test
)

The segment of the POM:

<dependency>
    <groupId>org.scalactic</groupId>
    <artifactId>scalactic_2.11</artifactId>
    <version>3.0.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.scalatest</groupId>
    <artifactId>scalatest_2.11</artifactId>
    <version>3.0.0</version>
    <scope>test</scope>
</dependency>

The scope clearly needs to be test in order to prevent issues in another project (main) that uses this library. In particular, the testing of the main project otherwise includes these test libraries, which causes version conflicts etc.

As these dependencies are only for the not included test package, having them listed in the POM seems silly. How do I tell SBT to not include these test scope dependencies into the final POM?

like image 930
calloc_org Avatar asked Jan 16 '17 05:01

calloc_org


1 Answers

There was a similar question asked here: sbt - exclude certain dependency only during publish.

Riffing on the answer provided by lyomi, here's how you can exclude all <dependency> elements that contains a child <scope> element, including test and provided.

import scala.xml.{Node => XmlNode, NodeSeq => XmlNodeSeq, _}
import scala.xml.transform.{RewriteRule, RuleTransformer}

// skip dependency elements with a scope
pomPostProcess := { (node: XmlNode) =>
  new RuleTransformer(new RewriteRule {
    override def transform(node: XmlNode): XmlNodeSeq = node match {
      case e: Elem if e.label == "dependency"
          && e.child.exists(child => child.label == "scope") =>
        def txt(label: String): String = "\"" + e.child.filter(_.label == label).flatMap(_.text).mkString + "\""
        Comment(s""" scoped dependency ${txt("groupId")} % ${txt("artifactId")} % ${txt("version")} % ${txt("scope")} has been omitted """)
      case _ => node
    }
  }).transform(node).head
}

This should generate a POM that looks like this:

<dependencies>
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-library</artifactId>
        <version>2.12.5</version>
    </dependency>
    <!-- scoped dependency "org.scalatest" % "scalatest_2.12" % "3.0.5" % "test" has been omitted -->
</dependencies> 
like image 69
Eugene Yokota Avatar answered Nov 16 '22 01:11

Eugene Yokota