Jorge
Jorge

Reputation: 804

How can I resolve a dependency in sbt that has a different packaging ivy type?

In my example, I need to resolve a dependency whose artifacts don't have the conventional jar as the packaging type, but rather maven-plugin (more concretely, the artifact i'm interested in is a Maven plugin). This, in Maven land, is specified via the <packaging> XML tag.

When I add the plugin my project depends on in the sbt build, sbt successfully updates the project but the resolved dependency is not in the classpath. How can I get sbt to add the artifact to my classpath so that code that depends on such dependency compiles?

Code that I used to add the maven plugin to my build:

libraryDependencies += "net.alchim31.maven" % "scala-maven-plugin" % "3.3.1"

Upvotes: 0

Views: 646

Answers (1)

Jorge
Jorge

Reputation: 804

There are two reasons why sbt doesn't add the desired artifact to the classpath, and hence compilation fails.

The first reason is that, by default, sbt only recognises artifacts whose packaging type is limited (jar, bundle and a few more). In order to tell sbt we're interested in an artifact whose packaging type is maven-plugin, we'll need to explicitly tell which artifacts we want from the dependency with:

libraryDependencies += ("net.alchim31.maven" % "scala-maven-plugin" % "3.3.1")
  .withExplicitArtifacts(Vector("scala-maven-plugin", "maven-plugin", "jar"))

Once we've done this, we can confirm that sbt did indeed get our artifact by running the following code in consoleProject:

Keys.update.in(myScope).in(myProject).eval.allFiles
  .find(_.getAbsolutePath.contains("net"))

Note that myScope must be either Compile, Test or Runtime (usually, it's Compile) and that myProject must be a reference to the project you have declared the dependency in. The result of the previous operation, if everything has gone well, will be Some(...), indicating that the artifact was indeed resolved and detected.

However, we're not done. If we run myProject/dependencyClasspath, this time from the sbt shell, we won't see our artifact there. This is where the second step is required: we need to add our new packaging type to classpathTypes so that sbt adds the artifact to our compilation classpath.

classpathTypes += "maven-plugin"

With all this done, we should run myProject/dependencyClasspath and see our artifact present.

But the story is not over, and here we enter "bug" territory. Sbt does not automatically add the packaging types in classpathTypes to the pom configuration that is responsible for declaring the dependencies in the pom file. Note that otherwise your application will fail with ClassNotFoundException or a similar issue because not all the dependent artifacts have been resolved and classloaded.

So in order to have a working application, you'll need to do it yourself:

makePomConfiguration :=
  makePomConfiguration.value.withIncludeTypes(classpathTypes.value)

The fact that this is not done by default it's just an sbt bug in 1.x.

Upvotes: 2

Related Questions