How to override the dependency of an sbt plugin? - plugins

I've written an sbt plugin called sbt-jumi which implements sbt integration for Jumi. Right now the sbt-jumi plugin depends on the current Jumi release.
Here is the relevant line from the plugin's build.sbt:
libraryDependencies += "fi.jumi" % "jumi-launcher" % "0.5.376"
And a user of the plugin would add this to his project/plugins.sbt file:
addSbtPlugin("fi.jumi.sbt" % "sbt-jumi" % "0.1.0")
Now let's say that Jumi 0.6.400 is released and it's backward compatible. How can a user of the sbt-jumi plugin configure it to use Jumi 0.6.400, without me having to release a new version of the plugin?
Here is how to do it in Maven. But how to do it in sbt?

Overriding the dependencies of plugins happens the same way as overriding normal dependencies, except that the configuration must be entered into project/plugins.sbt. Overriding dependencies is explained in Library Management. Here is a summary:
If the version you wish to use is greater than the dependency that you would get transitively, sbt will use the larger version by default. You may change the conflict manager to change the default behavior - for example this will create an error on conflict:
conflictManager := ConflictManager.strict
In other words, this in project/plugins.sbt would work:
libraryDependencies += "fi.jumi" % "jumi-launcher" % "0.6.400"
You may check your plugin dependencies using reload plugins and then show update. It should now show the older version as "(EVICTED)".
If the version you wish to use is lower than the default dependency, then you will need to override differently. One way is to force the dependency:
libraryDependencies += "fi.jumi" % "jumi-launcher" % "0.4.350" force()
Another way is to use the dependencyOverrides setting:
dependencyOverrides += "fi.jumi" % "jumi-launcher" % "0.4.350"
The difference between the two methods is that overriding doesn't introduce a direct dependency. I don't think the difference matters for plugins, but for published artifacts it has some differences.

Related

Why is the scala-compiler.jar included as library in my artefact

When I build an artefact with
sbt universal:packageZipTarball
the scala-compiler.jar is included as a lib in my artefact.
Why is the scala-compiler needed at runtime? In my understanding it shouldn't be needed.
How can I exclude this jar?
It is probably pulled in as a transitive dependency by one of your libraryDependencies. You can use this sbt plugin to find out which one:
https://github.com/sbt/sbt-dependency-graph
Once you found out, you can block it by appending exclude("org.scala-lang", "scala-compiler") to the relevant dependency.
For instance, older versions of the pureconfig library used to erroneously pull this dependency in. It can be fixed like so:
libraryDependencies +=
"com.github.pureconfig" %% "pureconfig" % "0.10.0" exclude("org.scala-lang", "scala-compiler")

when specify the scalaVersion and sbtVersion to resolve the plugin dependencies via “extra”,it doesn't work

I'm trying to add a plugin like this :
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2" extra ("scalaVersion" -> "2.10", "sbtVersion" -> "0.13"))
But when I start sbt session ,the search path still be
https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/com.eed3si9n/sbt-assembly/scala_2.12/sbt_1.0//0.11.2/ivys/ivy.xml
the scalaVersion and sbtVersion still is the one which I'm using.
Could you tell me What should I do?
Thank you!
That is what addSbtPlugin does: it adds the appropriate scalaVersion and sbtVersion to the mentioned artifact (in your case overriding what you have specified manually).
If you want to have full control, do not use addSbtPlugin:
libraryDependencies += "com.eed3si9n" % "sbt-assembly" % "0.11.2" extra ("scalaVersion" -> "2.10", "sbtVersion" -> "0.13")
BUT beware, usually this sort of thing will not work if you fail to add the right attributes appropriate for your SBT version at hand.
In your case, you are apparently using SBT 1.x, which in turn uses Scala 2.12. Trying to use an artifact build with Scala 2.10, ie. for SBT 0.13.x, will break.

Finding resolver and version of dependency, say play-json, in sbt?

Say I want to include a dependency on the play-json library in my sbt file. How and where can I find that information?
I tried searching central repo, play git repository -- couldn't find anything.
First of all, when you want to include a dependency, you've somehow been told about it - about the required version and where to find it. Ask the person this question and you're done. The official source should always be the home page of a dependency.
I'd use http://search.maven.org/ or http://mvnrepository.com/ and pick whatever version is the most current. In your case, however, esp. after the comment where you pointed at Adding Play JSON Library to sbt the answer was right there - in the answers - see https://stackoverflow.com/a/20475410/1305344:
Play 2.2 is out and can be added separately from rest of Play
Framework. in build.sbt:
resolvers += "Typesafe Repo" at "http://repo.typesafe.com/typesafe/releases/"
libraryDependencies += "com.typesafe.play" %% "play-json" % "2.2.1"
The trick is to set up resolvers properly and using the above resolver gives http://repo.typesafe.com/typesafe/releases/com/typesafe/play/play-json_2.10.
When you've got resolvers and any version in your build configuration, you may want to use sbt-updates that's (quoting the plugin's headline) "SBT plugin that can check maven repositories for dependency updates". Quite handy to have it installed as a global plugin, i.e. .sbt/0.13/plugins/sbt-updates.sbt with the following:
resolvers += Classpaths.sbtPluginSnapshots
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.6-SNAPSHOT")
When you execute dependencyUpdates you're told what needs version update.
> dependencyUpdates
[info] Found 1 dependency update for superapp
[info] org.jacoco:org.jacoco.agent:jacoco : 0.6.4.201312101107 -> 0.6.5.201403032054 -> 0.7.0.201403182114
[success] Total time: 1 s, completed 2014-03-28 18:30:12
As you can see, I need to upgrade jacoco.
If the project you depend on releases to some known repositories, running sbt-updates regularly will ultimately tell you about the update. I'd strongly recommend reading RELEASE_NOTES for an update before upgrading since it may be introducing some breaking changes you'd rather know about before going to production.

How to add native library dependencies to sbt project?

I want to add a Java library (e.g. Apache PDFBox) to an sbt project.
This is the Ivy dependency:
dependency org="org.apache.pdfbox" name="pdfbox" rev="1.8.2"
I first tried to do the following:
resolvers += "Sonatype releases" at "http://oss.sonatype.org/content/repositories/releases/"
libraryDependencies += "org.apache.pdfbox" %% "pdfbox" % "1.8.2"
But it gives me errors of the type
[warn] ==== public: tried [warn]
http://repo1.maven.org/maven2/org/apache/pdfbox/pdfbox_2.10/1.8.2/pdfbox_2.10-1.8.2.pom
So I understand that with this syntax I can just manage Scala dependencies. I am sure that there is a way to manage Java dependencies, but how?
I tried to search in Google for "sbt add java dependencies" but did not find (recognize) a relevant result.
You should replace the %% (double percent) with single one.
libraryDependencies += "org.apache.pdfbox" % "pdfbox" % "1.8.2"
The double-percent is a convenience operator, and causes adding the _+scalaVersion postfix inside the path, which is _2.10 in your case. Single percent should fix the problem.
Short answer:
Use
libraryDependencies += "org.apache.pdfbox" % "pdfbox" % "1.8.2"
For java libraries, and
libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.8"
For Scala libraries, where the difference is the double % for the scala library.
Long answer:
Scala is not backward compatible across major version, so a library compiled for scala 2.12.x cannot be used by a project written in scala 2.13.x.
So when writing a scala library, you will need to compile and publish it one time per scala major version you would like to support. When using a library in a project, you would then have to pick the version compiled for the same Scala major version as your are using. Doing this manually would be cumbersome, so SBT has built in support for it.
When publishing a library, you can add the crossScalaVersions key to SBT like
crossScalaVersions := Seq( "2.10.6", "2.11.11", "2.12.3" )
And then publish with sbt +publish. This will make SBT build and publish a version of the library for both scala 2.10.6, 2.11.11 and 2.12.3. Note that the minor number is in-relevant, when it comes to compatibility for libraries. The published libraries, will have the name suffixed with _2.10, _2.11 and _2.12 to show what scala version it is for. An alternative to using the SBT build in support for this, is to use the experimental plugin sbt-projectmatrix as this gives a lot more options, and often faster builds.
When using a library sbt can also help your use the one compiled for the correct scala version, and thats where %% comes into play. When specifying a library without the _ suffix in the name, but instead use %%, then sbt will fill in suffix matching the Scala major version your use, and thereby fetch the correct version of the library.

When does a SBT package get downloaded/built?

I want to use http://dispatch.databinder.net/Dispatch.html .
The site indicates I must add this to project/plugins.sbt:
libraryDependencies += "net.databinder.dispatch" %% "core" % "0.9.1"
which I did. I then restarted the play console and compiled.
Importing doesnt work:
import dispatch._
Guess I have been silly, but then I never used a build system when using Java.
How must I trigger the process that downloads/builds the package? Where are the jars (or equivalent) stored; can I reuse them? When is the package available for use by the Play application?
It doesn't say you should add it to project/plugins.sbt. That is the wrong place. It says to add to the build.sbt file, on the root of your project. Being a Play project, project/Build.scala might be more appropriate -- I don't know if it will pick up settings from build.sbt or not.
To add the dependency in your Build.scala:
val appDependencies = Seq(
"net.databinder.dispatch" %% "core" % "0.9.1"
)
You probably need to run sbt update.
From the sbt Command Line Reference:
update Resolves and retrieves external dependencies as described in library dependencies.