How to add a github java dependency in sbt config? - scala

I've added this code to my Build.scala.
lazy val root = Project("root", file(".")) dependsOn(jbcrypt)
lazy val jbcrypt = RootProject(uri("https://github.com/jeremyh/jBCrypt.git"))
But sbt fails with the error:
[error] (root/*:update) sbt.ResolveException: unresolved dependency: default#jbcrypt_2.11;0.1-SNAPSHOT: not found
How to tell sbt that it is Java not Scala?
How to reference to a specific branch or tag?
Thank you.

Building a project from source is only possible if the referenced project is a sbt project. sbt doesn't know of all the different build systems out there, so how is it supposed to know how to build a non sbt project?
It is possible to add support for other build systems through a sbt plugin but this may be a lot of work.
Your referenced project is a simple Maven project, which means that you can easily create a sbt project from it. Just fork the repo and create a build.sbt with the following content:
scalaVersion := "2.11.5"
projectDependencies += "junit" % "junit" % "3.8.1" % "test"
publishTo := {
val nexus = "https://oss.sonatype.org/"
if (isSnapshot.value) Some("snapshots" at nexus + "content/repositories/snapshots")
else Some("releases" at nexus + "service/local/staging/deploy/maven2")
}
This is the minimal code that was necessary to get it up and running. sbt seems to require that a publish repo is specified, it also seems to require an explicit Scala version. The dependency is already specified by your linked Maven project.
Of course, you know need to change the URI of RootProject to point to the location of your fork.
To your second question: You can reference a commit/tag/branch by appending it to the URI, separated with a # sign:
uri("git://github.com/your/repo#<commit-hash/tag/branch>")

Related

sbt: set the base-directory of a remote RootProject

Disclaimer: I am new to sbt and Scala so I might be missing obvious things.
My objective here is to use the Scala compiler as a library from my main project. I was initially doing that by manually placing the scala jars in a libs directory in my project and then including that dir in my classpath. Note that at the time I wasn't using sbt. Now, I want to use sbt and also download the scala sources from github, build the scala jars and then build my project. I start by creating 2 directories: myProject and myProject/project. I then create the following 4 files:
The sbt version file:
// File 1: project/build.properties
sbt.version=0.13.17
The plugins file (not relevant to this question):
// File 2: project/plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0")
The build.sbt file:
// File 3: build.sbt
lazy val root = (project in file(".")).
settings(
inThisBuild(List(
organization := "me",
scalaVersion := "2.11.12",
version := "0.1.0-SNAPSHOT"
)),
name := "a name"
).dependsOn(ScalaDep)
lazy val ScalaDep = RootProject(uri("https://github.com/scala/scala.git"))
My source file:
// File 4: Test.scala
import scala.tools.nsc.MainClass
object Test extends App {
println("Hello World !")
}
If I run sbt inside myProject then sbt will download the scala sources from github and then try to compile them. The problem is that the base-directory is still myProject. This means that if the scala sbt source files refer to something that is in the scala base-directory they won't find it. For example, the scala/project/VersionUtil.scala file tries to open the scala/versions.properties file that lies in the scala base-directory.
Question: How can I set sbt to download a github repo and then build it using that project's base-directory instead of mine's (by that I mean the base-directory of myProject in the above example) ??
Hope that makes sense.
I would really appreciate any feedback on this.
Thanks in advance !
In the Scala ecosystem you usually depend on binary artifacts (libraries) that are published in Maven or Ivy repositories. Virtually all Scala projects publish binaries, including the compiler. So all you have to do is add the line below to your project settings:
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
dependsOn is used for dependencies between sub-projects in the same build.
For browsing sources you could use an IDE. IntelliJ IDEA can readily import Sbt projects and download/attach sources for library dependencies. Eclipse has an Sbt plugin that does the same. Ensime also, etc. Or just git clone the repository.

Scala Play and Multi Project SBT Builds

I created a scala play project like this
activator new foo play-event-sourcing-starter
the project was generated successfully and I can go inside and easily compile and run the app.
However what I want is that I should have a multi project sbt build. I googled and found this https://www.playframework.com/documentation/2.5.x/SBTSubProjects
But this is not the same as what I want because here they have play as the root project. whereas what I want is that I have an empty root project with a build.sbt file and then multiple "peer" projects. One of them is play.
So I changed the steps to
mkdir -p LearnPlay/project
cd LearnPlay
activator new foo play-event-sourcing-starter
Now I went inside foo and moved the build.sbt to the LearnPlay directory. I also moved the build.properties and plugins.sbt files into LearnPlay/project folder.
I edited the build.sbt file so that the root project becomes
lazy val root = (project in file("foo")).enablePlugins(PlayScala)
However now sbt cannot compile the project anymore and it cannot find any of the play framework dependencies.
sbt.ResolveException: unresolved dependency: com.typesafe.play#play-server_2.10;2.5.9: not found
unresolved dependency: com.typesafe.play#play-netty-server_2.10;2.5.9: not found
unresolved dependency: com.typesafe.play#play-logback_2.10;2.5.9: not found
unresolved dependency: com.typesafe.play#play-test_2.10;2.5.9: not found
unresolved dependency: com.typesafe.play#play-omnidoc_2.10;2.5.9: not found
at sbt.IvyActions$.sbt$IvyActions$$resolve(IvyActions.scala:313)
These are the contents of my plugins.sbt file. The resolver is defined correctly so I am not sure why sbt will not be able to find the dependencies after the file was moved from sub-project to root project. it was able to resolve everything when the file was in the project directory of the foo project.
resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.9")
// web plugins
addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.0")
The thing that gave me some ideas what's the problem there is:
unresolved dependency: com.typesafe.play#play-server_2.10;2.5.9: not found
Aren't you surprised, that sbt tries to download the version of play server for Scala 2.10, which doesn't exist for Play 2.5.x, since it's already out of lifecycle.
In my projects this is happening, if I'm not specifying scala version in build.sbt or set it to the 2.10, e.g.
lazy val root = (project in file("foo")).settings(
scalaVersion := "2.10.6",
so, I think you just need to add scalaVersion parameter and set it to something from 2.11.x or 2.12.x

Why can't sbt find my local package

Searching for examples of library use I downloaded this project.
https://github.com/marcusatbang/Hooks
I then moved the build.bat up one directory. Commented out the xsbt-gpg dependency lines in build.sbt and Build.scala since sbt couldn't find the package. I checked the source to comment out any imports of xsbt-gpg -- there were none. ( Surprise! )
So I managed to compile the project. I then did sbt publish-local. find ~/.ivy2 -iname "\*hooks*jar" generated the following line: .ivy2/local/cc.minotaur/hooks_2.9.0/0.1/jars/hooks_2.9.0.jar.
I then entered the examples folder and tried to build the example project.
The build.scala contains the line: libraryDependencies += "cc.minotaur" %% "hooks" % "0.1", and it generates the error: unresolved dependency: cc.minotaur#hooks_2.9.1;0.1: not found
So how do I fix this error? It seems to me it should be finding the hooks jar/
That could be that your resolver doesn't see local directory. Try something like:
val ivyLocal = Resolver.file("local", file(Path.userHome.absolutePath +
"/.ivy2/local"))(Resolver.ivyStylePatterns)
externalResolvers += ivyLocal
It seems to me that you are using two versions of Scala. The one you are generating the jar is 2.9.0 while the one you are using in the example project is 2.9.1. Probably will solve the problem setting the same version in both projects.
I think your scala version is 2.9.1, u have generated jar for version 2.9.0
change your library dependency as mentioned below.
libraryDependencies += "cc.minotaur" % "hooks_2.9.0" % "0.1"
or add scalaVersion := "2.9.0" in your build.sbt file

sbt direct git source dependency - not fetching transitive library dependencies?

I'm trying out sbt's direct dependsOn feature with a git repository ("project A") hosted at Github. I am using a stable tag reference, and in my test project ("project B"), sbt does clone project A from source and starts compiling. However compilation fails with project A's own dependencies seemingly missing (i.e. it doesn't seem to pick up anything defined in project A's build.sbt).
Is this a different from maven/ivy managed dependencies? Do I need to include all the transitive dependencies in my child project B? Sounds a bit weird to me. That would kind of kill off the whole effort, as I'm having like a dozen libraries on which project A depends.
To illustrate:
Project A (online on Github as source):
// build.sbt:
version := "1.2.3"
libraryDependencies += "org.foo" %% "bar" % "1.0"
Project B (local):
// project/Build.scala
import sbt._
import Keys._
object Build extends sbt.Build {
lazy val projA = RootProject(uri("git://github.com/me/projA.git#v1.2.3"))
lazy val projB = Project(id = "project-B", base = file(".").dependsOn(projA)
}
This goes:
[info] Compiling 678 Scala sources to /Users/me/.sbt/staging/
5666eafa865fdf605be3/target/scala-2.10/classes...
[error] /Users/me/.sbt/staging/5666eafa865fdf605be3/src/main/scala/com/me/
BarKeeper.scala:3: not found: object bar
[error] import org.foo.bar
[error] ^
So do I have to re-declare the library dependency on "org.foo" %% "bar" % "1.0"? I hope not!
This was purely my own fault, not sbt's. I had overseen an unmanaged library (folder lib) in project A. After exchanging it for a Maven managed version (folder lib_managed), project A now correctly compiles from source in the staging for project B.

How to inform SBT to consume specific scala version for plugins?

Now I somehow messed up my global sbt plugins (~/.sbt/plugins/build.sbt). They were always fine retrieved against Scala 2.9.1 which seems to be the version that sbt 0.11.3 wants, and all the plugins (sbt-gpg-plugin, sbt-idea-plugin) are published against 2.9.1.
Now whatever I do, it persistently tries to find them built against 2.9.2:
[warn] Note: Some unresolved dependencies have extra attributes. Check that these dependencies exist with the requested attributes.
[warn] com.github.mpeltonen:sbt-idea:1.0.0 (sbtVersion=0.11.3, scalaVersion=2.9.2)
[warn] com.jsuereth:xsbt-gpg-plugin:0.6 (sbtVersion=0.11.3, scalaVersion=2.9.2)
...
[error] {file:...}default-50be6e/*:update: sbt.ResolveException: unresolved dependency: com.github.mpeltonen#sbt-idea;1.0.0: not found
How can I fix this, so sbt retrieves the plugins for Scala 2.9.1 as before?
For the sake of completeness, this is how my files look after the suggestions:
// project-home/build.sbt
scalaVersion := "2.9.2"
...
 
// project-home/project/plugins.sbt
resolvers += "less is" at "http://repo.lessis.me"
addSbtPlugin( "me.lessis" % "ls-sbt" % "0.1.1" )
scalaVersion := "2.9.1" // "just in case it helps"
 
// ~/.sbt/plugins/build.sbt
scalaVersion := "2.9.1" // "just in case it helps"
resolvers += "sbt-idea-repo" at "http://mpeltonen.github.com/maven/"
resolvers += Resolver.url( "sbt-plugin-releases", url( "http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases" ))( Resolver.ivyStylePatterns )
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.0.0")
addSbtPlugin( "com.jsuereth" % "xsbt-gpg-plugin" % "0.6" )
What is even worse, the problem persists, even after I removed ~/.sbt/plugins/build.sbt. So there are no more references (at least visible to me) to either sbt-idea or xsbt-gpg-plugin. Still I cannot compile any project any more, because sbt still tries to find those two plugins. Epic fail.
You could provide the Scala version of plugin. I didn't use ~/.sbt/, but I think it will works too.
The following is my project configuration using Scala 2.9.2 as my project compiler, and using some pluign that are compiled from Scala 2.9.1. Since Scala 2.9.1 and Scala 2.9.2 is binary compatible, I don't encounter any problem yet.
// MyProject/build.sbt
name := "MyProject"
version := "0.1"
scalaVersion := "2.9.2"
The following is plugin configuration:
// File: MyProject/project/plugins.sbt
import sbt._
import Defaults._
resolvers += Resolver.url("sbt-plugin-releases",
new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases/"))(
Resolver.ivyStylePatterns)
// Resolved to:
//
// http://..../com.untyped/sbt-less/scala_2.9.1/sbt_0.11.3/0.4/jars/sbt-less.jar
//
libraryDependencies += sbtPluginExtra(
m = "com.untyped" % "sbt-less" % "0.4", // Plugin module name and version
sbtV = "0.11.3", // SBT version
scalaV = "2.9.1" // Scala version compiled the plugin
)
Some references:
SBT plugins are versioned to the scala version they were built with.
You're not the only one... Again, no answers.
And another case study, this may have answers.
A possibly relevant quote? " Remember to also remove the project/plugins -directory, because if the directory exists, project/plugins.sbt is ignored."
You can also specify sbtVersion and scalaVersion. There is an overloaded addSbtPlugin -
addSbtPlugin(dependency : sbt.ModuleID, sbtVersion : scala.Predef.String, scalaVersion : scala.Predef.String)
Ok, I went back to all the events that could have led to this. And because I found that other projects were still building, I started to understand that the problem with this particular project B was that it appeared that the two plugins were regular dependencies of project A which it depended on.
When sbt refused to acknowledge the presence of the GPG plugin which I uncommented in ~/.sbt/plugins/build.sbt, I renamed that file to ~/.sbt/plugins.sbt, and back again. That intermediate position somehow meant that the plugins were not any more plugins (despite being added as addSbtPlugin), but regular dependencies for the project A when I publish that.
I tried to find that messed up A's ivy.xml across all known Ivy2 cache directories. It was not possible to find the one that sbt was obviously seeing.
Long story, short answer: I had to bump the version of A artificially to get rid of the wrong ivy.xml cached somewhere in a hidden place. That forced sbt to re-find A with the correct ivy.xml (not depending any more on the plugins).
Now I'm just worried what happens if I put my global plugin settings into place :-#
Future advise: Never ever ever put anything into ~/.sbt/plugins.sbt. If you need sbt to understand that you changed ~/.sbt/plugins/build.sbt: Reboot your computer. Don't touch any file.