SBT doesn't seem to download transitive dependencies with a custom repository? - sbt

I'm new to SBT, using version 1.0 and a custom repository, and I've set the "retrieveManaged" flag mentioned here, but it seems that SBT only downloads the directly requested JARs, but not any of the JARs upon which those JARs depend. And yes, the repository is using the customary default format described in the answers here (though SBT/Ivy doesn't seem capable of retrieving snapshots, either, but that's a separate problem, I expect). The repository does not require any kind of authentication, FYI.
Here's a slightly generified version of my built.sbt file:
name := "MyProject"
organization := "com.myorg"
version := "0.1"
scalaVersion := "2.9.0"
scalacOptions += "-deprecation"
retrieveManaged := true
resolvers += Resolver.url("myorg", url("http://host.com//content/groups/public"))
libraryDependencies += "com.myorg" % "otherproject" % "1.0"
fork in run := true
The requested "otherproject" JAR file loads fine, but SBT/Ivy seems to have no interest in opening up its POM and downloading the other JARs it needs to operate. This seems like it should be a fairly basic function (Maven does it, for example) but I have no idea how to convince SBT/Ivy to do so. (And the documentation assures us that SBT is, in fact, supposed to do this: "By default, these declarations fetch all project dependencies, transitively".)
I believe I must be doing something wrong, but have no idea -- given how simple and vanilla this basic configuration is -- what it could be.

Standard, Maven-style repositories are declared like:
resolvers += "myorg" at "http://host.com/content/groups/public"
More details are at the Library Management page you linked to and on the Resolvers page.
Typically, one only uses Resolver.url when specifying non-standard layouts.

Related

How to edit the ivy.xml file that sbt produces for publishLocal (or publish)

sbt seems to create an ivy.xml file, along with a pom file, during a publishLocal, even though ThisBuild / publishMavenStyle := true. It doesn't seem to be a problem with publish, because the ivy.xml file never makes it to the server. An sbt consumer of the locally published snapshot seems to use the ivy.xml file rather than the pom file. I've edited the pom file that gets produced using ThisBuild / pomPostProcess := ??? and would like to edit the ivy.xml similarly. We have access to ivySbt (and lots of other things), but I don't see how to edit the string or the XML nodes of the ivy file. Can anyone show how that might be done?

Modify libraryDependcies inside of SBT

I use SBT / Console as a prototyping tool and therefore don't want to start with a pre-defined build.sbt file.
What I want to do is to run the sbt tool and then modify the libraryDependencies setting. then run console and go and use my newly imported library. If I need something more. I can exit the console and import more stuff and then come back in the console.
is this possible? or should I always start with a predefined build.sbt file?
set libraryDependencies += group % art % version
I understand ammonite is good at this as well

Playframework 2.3.9 dependency override

As of Play 2.3, Play is added as an SBT Plugin as follows in my Build.scala as follows:
Project("root", file(".")).enablePlugins(play.PlayScala)
Also have a look at the documentation.
I need a specific dependeny updated, namely Fluentlenium (Play 2.3.9 still uses 0.9.3):
"org.fluentlenium" % "fluentlenium-core" % "0.10.3"
How can I replace the old version and replace it with a newer one? Simply adding the library to the libraryDependencies leaves me with both versions in the class path.
Edit: After digging a bit deeper, it seems as if the (new?) feature of dependencyOverrides that comes with SBT 13.8 could be a solution:
Overriding a version. But also have a look at Conflict Management from the very same documentation.
With this you can override single dependencies, which means that you have to override each transititve dependency manually.
Simply adding the library to the libraryDependencies leaves me with both versions in the class path.
Are you sure about this? sbt (Ivy) should evict the older one if there are multiple versions in the same configuration.
In most cases
libraryDependencies += "org.fluentlenium" % "fluentlenium-core" % "0.10.3"
should be ok, granted that 0.9.x are binary compatible with 0.10.x. If you want to make sure that it is overridden during transitive dependency resolution, dependencyOverrides might be the way to go:
dependencyOverrides += "org.fluentlenium" % "fluentlenium-core" % "0.10.3"

Are sbt library dependencies order dependent?

Empirically, the order of declared library dependencies in a build.sbt appears to matter. Is this true? If so, it is worth a brief mention in the sbt library management section of the documentation.
Yes, the order listed is the order used to resolve dependencies. This includes defaults if you merely append to defaults. Therefore you should put less likely candidates after more likely candidates. In the following example, the default resolvers are checked, then Sonatype snapshots, then dependencies only available on the local machine in the .m2 directory:
resolvers ++= Seq(
Resolver.sonatypeRepo("snapshots"),
"Local .m2 Repository" at s"file:${ Path.userHome.absolutePath }/.m2/repository"
)
The defaults have changed over the years. To be certain you control the resolvers, another way to write this, without relying on defaults, is:
resolvers = Seq(
allResolvers,
Resolver.sonatypeRepo("snapshots"),
"Local .m2 Repository" at s"file:${ Path.userHome.absolutePath }/.m2/repository"
)

Handling unmanaged classpath jars in a library using SBT so that a dependent project can access them

I'm writing a library which depends on code (let's call it foo.jar) which is only available as a binary jar. As is standard, I'm putting this in the lib/ directory so SBT will treat is as an unmanaged dependency. This is fine so far.
However, since this is a library, I'd like to be able to publish it so that other projects which depend on it to also have access to the unmanaged code in foo.jar without having to manually locate it. I originally thought I could use a fat jar plugin such as SBT Assembly to create a jar with the dependencies, but that doesn't affect what is actually published using sbt publish-local – it only creates a fat jar when you run sbt assembly. Is there some standard simple way to handle this? It seems like a bad idea for every library which uses unmanaged dependencies to break when used by other projects downstream so I wonder if I'm missing something obvious.
I don't know if that's a good use of sbt-assembly, since other libraries could depend on a different version of foo.jar etc.
One way to work around it is to publish foo.jar in a Maven repository yourself. Some people in Scala and/or sbt community have been talking about bintray. It's still in beta, but looks promising if you want some jars published.
You might be able to get the result you want by manipulating the mappings in (Compile, packageBin) to include the files you want your packaged jar to have (publish uses the output from packageBin). This technique will allow you to include absolutely any file you want within the jar. The official sbt doc is here: http://www.scala-sbt.org/0.12.3/docs/Howto/package.html#contents
As an example, consider the common case of including a .properties file within your jar. Lets say you need to include "messages.properties" under the path "com/bigco/messages.properties" in your packaged jar. And lets say that this file is under src/main/scala/ ... You can add the following to your build.sbt:
mappings in (Compile, packageBin) <+= baseDirectory map { base =>
(base / "src" / "main" / "scala" / "com" / "bigco" / "messages.properties") -> "com/bigco/messages.properties"
}
To attempt to answer your original question, you could unzip foo.jar and add each one of the class files within to the packaged jar, according to their correct package paths. So something similar to
mappings in (Compile, packageBin) <+= baseDirectory map { base =>
(base / path / to / unzipped / file.class) -> "path.to.unzipped.file.class"
...
}
Or you might be able to get away with simply including foo.jar at the root of the packaged jar like so:
mappings in (Compile, packageBin) <+= baseDirectory map { base =>
(base / "lib" / "foo.jar") -> "foo.jar"
}

Resources