Scala SBT Inline Dependency Declaration - scala

Scala SBT manual apparently says that there is some "lightweight alternative to Ivy" called "inline declarations"
http://www.scala-sbt.org/0.13/docs/Library-Management.html
I have a single jar file ( printer_2.11-1.0.jar ) with no dependencies or imports what so ever that I created with "sbt package". I want to get this jar to a place on the internet where I can include it into my future projects as soon as possible. I don't know how to use Ivy or Maven. Can someone give me a solution that can get my jar listed as fast as possible?
Solved:
libraryDependencies += "printer" % "printer" % "2.11" from "https://dl.dropboxusercontent.com/u/214507961/printer_2.11-1.0.jar"
^ The jar file is posted to a public dropbox folder.

You are misreading the manual. Going to section Inline Declarations. The text reads:
Inline declarations are a basic way of specifying the dependencies to be automatically retrieved. They are intended as a lightweight alternative to a full configuration using Ivy.
This is an example inline definition of a dependency:
libraryDependencies += groupID % artifactID % revision
which will be normally resolved through Ivy. The sentence does not say 'lightweight alternative to Ivy', it means:
They are intended as an Ivy based automatically resolved lightweight alternative to specifying a full configuration manually.
The latter being:
Manually managing dependencies involves copying any jars that you want to use to the lib directory.

This is the solution...
libraryDependencies += "printer" % "printer" % "2.11" from "https://dl.dropboxusercontent.com/u/214507961/printer_2.11-1.0.jar"
^ The jar file is posted to a public dropbox folder. This jar file makes print statements easier to locate.

Related

Scala "not found: object com" - should i really add entry in build.sbt if there are no other dependencies?

I have created basic Scala Play application with https://www.playframework.com/getting-started play-scala-seed. This project compiles and runs with sbt run. But I have another Scala project that compiles and runs and which I have submitted to my local Ivy repository with command sbt publishLocal. This other project was saved at C:\Users\tomr\.ivy2\local\com.agiintelligence\scala-isabelle_2.13\master-SNAPSHOT as a result of this command.
Then I imported (exactly so - imported, no just opened) my Play project in IntelliJ and I used Project - Open Module Settings - Project Settings - Libraries to add com.agiintelligence jar from my ivy2 location. After such operations IntelliJ editor recognizes com.agiintelligence classes. That is fine.
But when I am trying to run my Play application with sbt run, I experience the error message not found: object com that is exactly when compiling import com.agiintelligence line in my Scala controller file of Play application.
Of course - such error has been reported and resolved with, e.g. object play not found in scala application
But that solution suggests to append build.sbt file. My build.sbt file is pretty bare:
name := """agiintelligence"""
organization := "com.agiintelligence"
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.13.5"
libraryDependencies += guice
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "5.0.0" % Test
// Adds additional packages into Twirl
//TwirlKeys.templateImports += "com.skaraintelligence.controllers._"
// Adds additional packages into conf/routes
// play.sbt.routes.RoutesKeys.routesImport += "com.skaraintelligence.binders._"
My Play application contains (as can bee seen from the IntelliJ project pane) some tens of 'external libraries' (it shows my com.agiintelligence jar as well), but why should I add my own ivy2 library in build.sbt file if no other libraries are listed here? What is different with my library? It is on my computer, in the repository as expected already?
Of course, I can try to add it build.sbt and issue sbt update and see what happens, but I can not understand this logic? Can someone explain it and provide some clue to intelligible solution of my error message?
My Play application contains (as can bee seen from the IntelliJ project pane) some tens of 'external libraries'
Those are probably just transitive dependencies of your Play dependency, that is why sbt downloaded all of them and put them in your classpath so you could use them without you needing to tell it about them; because the pom of Play already did.
It is not that the build tool or the IDE magically added all those dependencies for you because they read your mind and magically understood you wanted them. And that for some reason the magic stopped working for your own library.
Why it is not sufficient to list it Project-Setting--External Libraries in IntelliJ only?
That is sufficient for the IDE to work, but not for the build tool. The build tool is independent of the IDE; it doesn't know about it. sbt just knows about the dependencies you configured in your definition file.
Even more, you should always configure your dependencies on your build tool and then import that in the IDE; rather than the opposite. IDEs are graphical tools, so their state can not be committed, can not be shared, can not keep track of changes, can not be used in CI / CD environments; additionally, different teammates may want to use different IDEs.
I resolved the error message by adding line in build.sbt file
libraryDependencies += "de.unruh" %% "scala-isabelle" % "master-SNAPSHOT"
and by subsequent run of sbt update.
Error is solved, but the main question still stand - why I had to do this? Why there are tens of dependencies that are not listed in build.sbt and why should I list my dependency in build.sbt and why it is not sufficient to list it Project-Setting--External Libraries in IntelliJ only?
OK, comment by #Luis_Miguel_Mejía_Suárez gave the explanation, that comment is the actual and expected answer to my question.

SBT Plugin in an unmanaged jar file

The requirement: an SBT plugin code is in an unmanaged jar, for example in lib/unmanaged-sbt-plugin-0.0.1.jar.
I was expecting the jar file would be picked up by SBT automatically and the plugin would work out-of-the-box, i.e.: the tasks would be accessible from SBT command line, but that is not the case.
The jar file has the sbt/sbt.autoplugins file in it and the plugin works if pulled from a remote repo into the local one and imported via addSbtPlugin(...). Please note I cannot do that - it's a requirement to get it to load from the lib/unmanaged-sbt-plugin-0.0.1.jar and not from the local/remote repo.
Putting the following line in the build.sbt doesn't make the plugin work (there's not error either):
unmanagedJars in Compile += file("lib/unmanaged-sbt-plugin-0.0.1.jar")
The implementation of addSbtPlugin(...) is simply (according to http://www.scala-sbt.org/0.12.2/docs/Getting-Started/Using-Plugins.html):
def addSbtPlugin(dependency: ModuleID): Setting[Seq[ModuleID]] =
libraryDependencies <+= (sbtBinaryVersion in update, scalaBinaryVersion in update)
{ (sbtV, scalaV) => sbtPluginExtra(dependency, sbtV, scalaV) }
I'm wondering if the above info can be used to resolve my issue?
Thank you in advance!
So you can specify an explicit URL for library dependencies (ModuleID):
addSbtPlugin("org.my-org" % "unmanaged-sbt-plugin" % "0.0.1"
from "file:///./lib/unmanaged-sbt-plugin-0.0.1.jar")
Have been struggling to get this to work.
Could not get it to work with proposed solution using from "file://.." (using sbt 1.0.4).
Got it to work by putting the plugin in project/lib folder and adding all the plugin dependencies to plugins.sbt using libraryDependencies ++= Seq(..) like in build.sbt. You can find the plugin dependencies by looking at the plugin pom file, usually in .ivy2/local/<org>/<pluginname>/poms folder.

How to use multiple versions of a library in Scala?

I am using a library say A in Scala which is dependent on version x.11 of another library say Z.
Now, I am also using a library say B which is dependent on version x.31 of Z.
This leads to compile error because we will have two versions of library Z, how can I use both libraries A and B in scala's sbt? Is there any way to specify it.
If completely replacing one dependency with a newer version happens to work, then Sparko's solution works. However, that isn't always the case.
If you want to include both versions of a library in the uber-jar produced by sbt-assembly, you'll need to use shading. See this post for an overview of what shading is, and some of the drawbacks associated with it.
Shading is covered in sbt-assembly's documentation here, but if you're anything like me, their way of explaining it will leave you more confused than you started. There's a good blog post, Spark, Uber Jars and Shading with sbt-assembly (waybackmachine link), that helps to demystify it a bit. Here's the relevant section:
I can shade over my typesafe config version, giving it a different
name so Spark won’t get confused between the versions. I quickly went
to my build.sbt file, and added the following code:
assemblyShadeRules in assembly := Seq(
ShadeRule.rename("com.typesafe.config.**" -> "my_conf.#1")
.inLibrary("com.typesafe" % "config" % "1.3.0")
.inProject )
According to the documentation, this should place any class under
com.typesafe.config under the new package my_conf.
For your case, the solution would be adding something like this to your build.sbt file:
assemblyShadeRules in assembly := Seq(
ShadeRule.rename("com.somecompany.**" -> "my_conf.#1")
.inLibrary("com.somecompany" % "libraryZ" % "0.11")
.inProject
)
In sbt, conflicts between libraries are configured using the conflict manager. By default, the latest revision is selected but this can also be overridden in you .sbt file:
conflictManager := ConflictManager.strict
If you're using sbt 0.13.6 or greater you will be warned when you have an incompatible binary version between your dependencies. In this situation, you could configure an override in your sbt file for the specific library:
dependencyOverrides += "org.raman" % "Z" % "x.11"
This will force the resolved version of Z to x.11 but not pull a direct dependency in.

adding external url jar as an sbt unmanaged dependency

I am working on an sbt project and I need to pull a jar, available via url, into my project as an unmanaged dependency.
As an example:
I want to retrieve a jar file available at
http://www.sourceGorge.net/fooProject/v4.2/lib/bar.jar. If the jar file is absent from myProject/lib then simply download the source jar, do nothing otherwise.
One possible solution I found on the web suggests the following:
libraryDependencies += "net.sf.proguard" % "proguard-base" % "5.0"
from "file:///tmp/proguard5.0beta2/lib/proguard.jar"
But my question would then be: what am I supposed to substitute for "net.sf.proguard", "program-base", and "5.0" if all I have is a url of the form specified in the above example?
Thank you in advance, and happy holidays if this is your holiday season.
If you're pulling the jar from a url, it doesn't matter what you call it--preferably something informative. sbt uses the organization/artifact/version to resolve dependencies from a repository. If you're providing an exact url, then it doesn't really matter.
For example, I can resolve joda-time like this, and it works just fine:
libraryDependencies += "doesn't" % "matter" % "2.1" from "http://central.maven.org/maven2/joda-time/joda-time/2.1/joda-time-2.1.jar"
It also uses the organization/artifact/version combination to store the jar in a specific directory in your local ivy repository. The above line downloaded the jar to:
~/.ivy2/cache/doesn't/matter/jars/matter-2.1.jar

Should I generate idea project with command line or should I import with the SBT plugin?

I have had problems with openning project generated from build.sbt file. I prefer the command line approach because it seems more standard. But I got an error when compiling the project in IDE:
Error:scalac: Output path xxx is shared between: Module 'domainRegistrar-build' tests, Module 'domain_registrar-build' tests
......
The problem of this issues is two modules domainRegistrar-build and domain_registrar-build share same output path.
file -> project structure -> modules -> path
Change Output path to different one. (Normally it should add module name to distinguish the path)
Also, the two module names are similar, maybe you rename or manually create it, so refresh sbt project and rebuild project may be needed.
update the scala-idea plugin in the plugins.sbt file. just like below:
resolvers += "sbt-idea-repo" at "http://mpeltonen.github.com/maven/"
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.5.1")