Andy MacKinlay
Andy MacKinlay

Reputation: 1374

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.

Upvotes: 5

Views: 1222

Answers (2)

Malcolm
Malcolm

Reputation: 2488

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"
}

Upvotes: 2

Eugene Yokota
Eugene Yokota

Reputation: 95624

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.

Upvotes: 4

Related Questions