Dependency missing from classpath - sbt

I have project that collects dependencies for an installer (sbt-install4j) using dependencyClasspath. It works most of the time, except when I have one specific dependency:
libraryDependencies += "org.bytedeco" % "javacpp" % "0.10"
"javacpp" will not be added to the dependencyClasspath. You can create a simple SBT project with only that dependency above and try show dependencyClasspath, it will print:
[info] List(Attributed(C:\Users\me\.sbt\boot\scala-2.10.4\lib\scala-library.jar))
there is no "javacpp". Any clues what may be happening? Is this an SBT bug?

sbt excludes certain packaging types from the classpaths it generates, because not all packaging types make sense to depend on. Unfortunately, it seems to do this exclusion silently - and the default value of classpathTypes isn't always what you want.
The packaging type of the dependency can be found in the dependency's pom.xml or ivy.xml (as applicable). There are two main cases:
If the packaging type is actually pom, this probably means it's a parent pom and you are trying to depend on the wrong thing - look for the specific Maven module you actually want!
If on the other hand, it's maven-plugin - as in this particular case - you need to add the packaging type to classpathTypes, using: classpathTypes += "maven-plugin"
Other cases are probably going to be similar to one of the above two cases.

Related

how do I put sbt-assembly in artifactory and have sbt retrieve it

For some reason I am having trouble downloading the sbt-assembly plugin using
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.7")
from plugins.sbt. It says the pom is not found. I'm using scala 2.12.10 at the moment but this has been an irritation with 2.13.1, too. As an alternative, I tossed it in an artifactory repository. When sbt concocts the URL to retrieve the pom, it comes up with
http:/.../com/eed3si9n/sbt-assembly_2.12_1.0/0.14.7/sbt-assembly-0.14.7.pom
as opposed to
http:/.../com/eed3si9n/sbt-assembly/0.14.7/sbt-assembly-0.14.7.pom
which will actually retrieve it. Any insight would be appreciated.
Looking under custom resolvers in the sbt reference manual tells you to match relevant values from the build. Maybe something like:
resolvers += Resolver.url("red angus", new java.net.URL(
"http:/..."))(
Patterns("[organisation]/[module]/[revision]/[artifact]-[revision].[ext]") ).
withAllowInsecureProtocol(true)

Why two different versions of sbt in the project

In my Play project I notice that build.properties has sbt version addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.12")
and build.properties has sbt.version=0.13.15.
1) Why are there two enteries?
2) What is the difference between them
3) Should their versions be different?
There is a difference between SBT proper and SBT plugin. Play Framework is an SBT plugin. The version of SBT is specified in project/build.properties:
sbt.version=0.13.15
whilst the version of Play SBT plugin is specified in project/plugins.sbt:
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.12")
Scala Play SBT plugin (PlayScala) is enabled in build.sbt like so:
lazy val root = (project in file(".")).enablePlugins(PlayScala)
SBT plugins enrich build definitions with additional useful tasks, commands, settings, and dependencies. Here are some examples from Play SBT plugin:
object PlayKeys {
val playDefaultPort = SettingKey[Int]("playDefaultPort", "The default port that Play runs on")
val playDefaultAddress = SettingKey[String]("playDefaultAddress", "The default address that Play runs on")
val playRunHooks = TaskKey[Seq[PlayRunHook]]("playRunHooks", "Hooks to run additional behaviour before/after the run task")
...
So for example to change the default port that Play runs on we can define in build.sbt:
PlayKeys.playDefaultPort := 9009
Note when upgrading SBT version we need to make sure it is compatible with corresponding Play SBT plugin. For example, to use Play with SBT 1 we need to update Play sbt-plugin to 2.6.6.
SBT plugin best practice artifact naming convention encurages the following naming scheme:
sbt-$projectname
For example, sbt-scoverage, sbt-buildinfo, sbt-release, sbt-assembly, however Play named it sbt-plugin, which arguably can be confusing.

How can I specify a different library jar for a sbt plugin dependency?

I'm using the sbt-scalariform plugin with sbt, which is built with a dependency on the default version of scalariform (mdr/scalariform). I'd like it to use a different/forked version of scalariform (daniel-trinh/scalariform) for my project.
Is there a configuration I can use in sbt in my project to specify the version of scalariform I want or do I need to fork/build my own custom version of sbt-scalariform built against daniel-trinh/scalariform?
(I'm not worried about compatibility between the two versions of sbt-scalariform. sbt-scalariform is really just a wrapper.)
I can add dependencies to my project but that's for my compiled code, not the build process itself, right (Build.scala in my case)?
addSbtPlugin(org % name % version exclude (scalariformorg, scalariform))
libraryDependencies += scalariformorg % scalariformorg % version
Fill in the fields as appropriate for what you want to replace. This goes into project/plugins.sbt

Is there a concept of a build script dependency?

In Gradle, there is a concept of a buildscript dependency, in that you can add an external dependency that the build script depends on to run. This is similar to SBT's plugins, except way more lightweight. With Gradle, I can add X as a dependency and then write Groovy code using the contents of X. I need to use an external Java library inside of my build script and the mechanisms to do this are far from obvious to me in SBT.
With SBT, the closest thing I've found in the documentation is addSbtPlugin, which works great if there is an X SBT plugin, but it isn't in this case.
Sbt builds are recursive, you can add a project/build.sbt file then add libraryDependency += ... to it.

Add JavaFX (of JDK8) in sbt (using the play framework)

The goal is to have a standalone Play Framework (2.2) application having an additional status window open containing some javafx (javafx-8) elements.
Since JavaFX classes are now on the default runtime classpath for an Oracle Java 8 implementation using javafx.* in my classes and compiling with sbt should just be fine.
However sbt can't find these classes and quits with
play.api.UnexpectedException: Unexpected exception[NoClassDefFoundError: javafx/application/Application]
when executing
..\path-to-play-framework-2.2\play project run
The best way to fix this problem seems to be the modification of build.sbt in the project directory. What can I do to add the missing (class) path?
Sadly JavaFX doesn't link that easily to an sbt build. You need to set your JAVA_HOME environment variable and do modifications to your build file.
Here I have a repository where this is set up. The important bit if you are using an sbt build rather than a scala build is this one:
unmanagedJars in Compile += Attributed.blank(
file(System.getenv("JAVA_HOME") + "/jre/lib/jfxrt.jar")),
fork in run := true
The reason for this is that jfxrt.jar is the archive containing the JavaFX runtime and it is not included in the classpath of an sbt project by default.
Anotherway is to set the Classpath for sbt. This can be done on the machines which can't resolve JavaFX.
SBT_OPTS="-Xbootclasspath/p:/usr/share/java/openjfx/jre/lib/ext/jfxrt.jar"

Resources