Why are transitive dependencies not detected? - scala

I have Scala library based on SBT, which I publish to Maven repository:
organization := "com.mycompany"
name := "mylib"
version := "0.0.1"
scalaVersion := "2.10.6"
crossScalaVersions := Seq("2.10.6", "2.11.7")
scalacOptions ++= Seq("-feature", "-unchecked", "-deprecation")
libraryDependencies ++= Seq(
"org.scalaj" %% "scalaj-http" % "2.2.0",
"org.json4s" %% "json4s-jackson" % "3.3.0",
"org.slf4j" % "slf4j-api" % "1.7.13",
"org.slf4j" % "slf4j-simple" % "1.7.13"
)
isSnapshot := true
publishMavenStyle := true
publishTo := {
Some(s3resolver.value("My Repo", s3("mybucket")).withMavenPatterns)
}
I include this library into another project:
libraryDependencies ++= Seq(
"com.mycompany" %% "mylib" % "0.0.1"
)
Running sbt sbt-dependency dependencyTree only shows:
[info] Done updating.
[info] default:another-project_2.10:1.2 [S]
[info] +-com.mycompany:mylib_2.10:0.0.1
[info]
I'm not able to see all the 3rd party dependencies: org.scalaj, org.json4s, etc.
EDIT: Moreover, when building an assembly, these dependencies are missing from the uberjar as well.
The .pom file deployed to the Maven repository do contain all the mentioned dependencies, while ~/.ivy2/cache/com.mycompany/mylib_2.10/ivy-0.0.1.xml does not.
Running sbt about in mylib/ shows:
[info] Loading global plugins from /home/michael/.sbt/0.13/plugins
[info] Loading project definition from /home/michael/Dev/projects/mylib/project
[info] Set current project to mylib (in build file:/home/michael/Dev/projects/mylib/)
[info] This is sbt 0.13.9
[info] The current project is {file:/home/michael/Dev/projects/mylib/}mylib 0.0.1
[info] The current project is built against Scala 2.10.6
[info] Available Plugins: sbt.plugins.IvyPlugin, sbt.plugins.JvmPlugin, sbt.plugins.CorePlugin, sbt.plugins.JUnitXmlReportPlugin, com.typesafe.sbteclipse.plugin.EclipsePlugin, ohnosequences.sbt.SbtS3Resolver
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.5
Running sbt about in otherproject/ shows:
[info] Loading global plugins from /home/michael/.sbt/0.13/plugins
[info] Loading project definition from /home/michael/Dev/projects/otherproject/project
[info] Set current project to otherproject (in build file:/home/michael/Dev/projects/otherproject/)
[info] Updating {file:/home/michael/Dev/projects/otherproject/}otherproject...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] This is sbt 0.13.9
[info] The current project is {file:/home/michael/Dev/projects/otherproject/}otherproject 1.2
[info] The current project is built against Scala 2.10.6
[info] Available Plugins: sbt.plugins.IvyPlugin, sbt.plugins.JvmPlugin, sbt.plugins.CorePlugin, sbt.plugins.JUnitXmlReportPlugin, com.typesafe.sbteclipse.plugin.EclipsePlugin, ohnosequences.sbt.SbtS3Resolver, net.virtualvoid.sbt.graph.DependencyGraphPlugin, sbtassembly.AssemblyPlugin
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.5
Here's the output from publishing to a local directory:
[info] Loading global plugins from /home/michael/.sbt/0.13/plugins
[info] Loading project definition from /home/michael/Dev/projects/mylib/project
[info] Set current project to mylib (in build file:/home/michael/Dev/projects/mylib/)
[info] Updating {file:/home/michael/Dev/projects/mylib/}mylib...
[info] Packaging /home/michael/Dev/projects/mylib/target/scala-2.10/mylib_2.10-0.0.1-sources.jar ...
[info] Done packaging.
[info] Wrote /home/michael/Dev/projects/mylib/target/scala-2.10/mylib_2.10-0.0.1.pom
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] :: delivering :: com.mycompany#mylib_2.10;0.0.1 :: 0.0.1 :: integration :: Sat Jan 09 16:10:20 IST 2016
[info] delivering ivy file to /home/michael/Dev/projects/mylib/target/scala-2.10/ivy-0.0.1.xml
[info] Main Scala API documentation to /home/michael/Dev/projects/mylib/target/scala-2.10/api...
[info] Packaging /home/michael/Dev/projects/mylib/target/scala-2.10/mylib_2.10-0.0.1.jar ...
[info] Done packaging.
model contains 9 documentable templates
[info] Main Scala API documentation successful.
[info] Packaging /home/michael/Dev/projects/mylib/target/scala-2.10/mylib_2.10-0.0.1-javadoc.jar ...
[info] Done packaging.
[info] published mylib_2.10 to /home/michael/Dev/projects/mylib/releases/com/mycompany/mylib_2.10/0.0.1/mylib_2.10-0.0.1.pom
[info] published mylib_2.10 to /home/michael/Dev/projects/mylib/releases/com/mycompany/mylib_2.10/0.0.1/mylib_2.10-0.0.1.jar
[info] published mylib_2.10 to /home/michael/Dev/projects/mylib/releases/com/mycompany/mylib_2.10/0.0.1/mylib_2.10-0.0.1-sources.jar
[info] published mylib_2.10 to /home/michael/Dev/projects/mylib/releases/com/mycompany/mylib_2.10/0.0.1/mylib_2.10-0.0.1-javadoc.jar
[success] Total time: 4 s, completed Jan 9, 2016 4:10:23 PM
What am I doing wrong?

Your build.sbt file contains the line
publishMavenStyle := true
According to the documentation
a POM is generated by the makePom action and published to the
repository instead of an Ivy file
I can suppose that ivy.xml is just not generated and the one that you see is a residue from a previous run, when publishMavenStyle was not (yet) set.
Since your artifact is published into the Maven repository, have you tried to remove the one from ~/.ivy2/cache/com.mycompany/mylib_2.10 and check the result of dependency tree listing?

Related

How to deal with library eviction when writing sbt plugin?

I try to write a simple sbt plugin which is using jsch. Due to the security reasons (ecdsa) my requirement is to use jsch in 0.1.53. I have declared the dependency in my build.sbt file:
libraryDependencies += "com.jcraft" % "jsch" % "0.1.53"
Unfortunately org.scala-sbt:ivy 2.3.0 introduces dependency on 0.1.46. SBT says that there was an eviction of the older version though in the runtime when using my plugin I can see that it's still running against 0.1.46 jsch.
[info] com.jcraft:jsch
[info] - 0.1.46
[info] status: release
[info] publicationDate: Thu Feb 02 13:39:27 CET 2012
[info] resolver: sbt-chain
[info] artifactResolver: sbt-chain
[info] evicted: true
[info] evictedData: latest-revision
[info] homepage: http://www.jcraft.com/jsch/
[info] isDefault: false
[info] configurations: default, compile, runtime, default(compile), master
[info] licenses: (Revised BSD,Some(http://www.jcraft.com/jsch/LICENSE.txt))
[info] callers: org.scala-sbt:ivy:0.13.11
[info] - 0.1.53
[info] status: release
[info] publicationDate: Fri Jun 05 17:32:00 CEST 2015
[info] resolver: sbt-chain
[info] artifactResolver: sbt-chain
[info] evicted: false
[info] homepage: http://www.jcraft.com/jsch/
[info] isDefault: false
[info] configurations: default, compile, runtime, default(compile), master
[info] licenses: (Revised BSD,Some(http://www.jcraft.com/jsch/LICENSE.txt))
[info] callers: com.evojam:sbt-ssh:0.1.1-SNAPSHOT (scalaVersion=2.10, sbtVersion=0.13), org.scala-sbt:ivy:0.13.11
I use sbt in version 0.13.11.
I have added my plugin to the test project. When running my sbt task I get clear log message:
[info] Local version string: SSH-2.0-JSCH-0.1.46
and an error about unsupported algorithm which leads me to the conclusion that my version of jsch has been overridden somehow.
The question is how to deal with library eviction when writing sbt plugin?
May be you could try with:
dependencyOverrides += "com.jcraft" % "jsch" % "0.1.53"
But I suspect the sbt version of jsch is loaded in the jvm classpath before your plugin.
There is a sbt issue to update to ivy 2.4; that would also update the used jsch version: https://github.com/sbt/sbt/issues/1920

Specs2 unable to find my tests using sbt

I have build a simple project for Spec2 testing using simple sbt.
package main.specs
import org.specs2._
class QuickStartSpec extends Specification {
def is = s2"""
This is my first specification
it is working $ok
really working! $ok
"""
}
And here is my build.sbt file:
name := "QuickStartSpec"
version := "1.0"
scalaVersion := "2.10.1"
libraryDependencies ++= Seq("org.specs2" %% "specs2-core" % "3.6.5" % "test")
scalacOptions in Test ++= Seq("-Yrangepos")
But when I run this command in sbt
testOnly main.specs.QuickStartSpec
I am getting this:
[info] Updating {file:/Users/nabajeet/workspace/SpecsTest/}specstest...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for test:testOnly
I am following this page to create the example:
https://etorreborre.github.io/specs2/website/SPECS2-3.6.5/quickstart.html
I am unable to figure out the reason why my tests are not detected.
My sbt version in 0.13.8
By declaring
libraryDependencies ++= Seq("org.specs2" %% "specs2-core" % "3.6.5" % "test")
You restrict the scope of specs2 to only classes in the test source directories. You won't be able to reference specs2 classes in the production code (all the code under src/main/)
In your comment you indicate that you placed your spec in /Users/nabajeet/workspace/SpecsTest/src/main/specs/quickStartSpec.scala
Try moving your file to /Users/nabajeet/workspace/SpecsTest/src/test/scala/specs/quickStartSpec.scala
The incorrect location is why it you spec not picked up by SBT (and I feel confident to say that it doesn't compile either).
By default, SBT applies maven's standard directory layout adding src/main/scala/ and src/test/scala/ for scala code. This is documented in the SBT tutorial
I just created a project with the following layout
.
./built.sbt
./src
./src/test
./src/test/scala
./src/test/scala/QuickStartSpec.scala
build.sbt contains
name := "QuickStartSpec"
version := "1.0"
scalaVersion := "2.11.4"
libraryDependencies ++= Seq("org.specs2" %% "specs2-core" % "3.6.5" % "test")
scalacOptions in Test ++= Seq("-Yrangepos")
and QuickStartSpec.scala contains
package main.specs
import org.specs2._
class QuickStartSpec extends Specification {
def is = s2"""
This is my first specification
it is working $ok
really working! $ok
"""
}
here is the sbt output I get
sbt
[info] Set current project to QuickStartSpec (in build file:/tmp/stack/)
> test:compile
[info] Updating {file:/tmp/stack/}stack...
[info] Resolving jline#jline;2.12 ...
[info] Done updating.
[info] Compiling 1 Scala source to /tmp/stack/target/scala-2.11/test-classes...
[info] 'compiler-interface' not yet compiled for Scala 2.11.4. Compiling...
[info] Compilation completed in 6.372 s
[success] Total time: 9 s, completed 27 nov. 2015 06:38:26
> test
[info] QuickStartSpec
[info] + This is my first specification
[info] it is working
[info] + really working!
[info]
[info] Total for specification QuickStartSpec
[info] Finished in 17 ms
[info] 2 examples, 0 failure, 0 error
[info]
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[success] Total time: 1 s, completed 27 nov. 2015 06:38:31
>

Why is crossScalaVersion not scalaVersion?

build.sbt
scalaVersion := "2.11.4"
project/build.properties
sbt.version=0.13.7
Then
> show scalaVersion
[info] 2.11.4
> show crossScalaVersions
[info] List(2.10.4)
> inspect crossScalaVersions
[info] Setting: scala.collection.Seq[java.lang.String] = List(2.10.4)
[info] Description:
[info] The versions of Scala used when cross-building.
[info] Provided by:
[info] */*:crossScalaVersions
[info] Defined at:
[info] (sbt.Defaults) Defaults.scala:237
[info] Delegates:
[info] *:crossScalaVersions
[info] {.}/*:crossScalaVersions
[info] */*:crossScalaVersions
[info] Related:
[info] */*:crossScalaVersions
It seems like crossScalaVersions should be List(2.11.4).
Look at SBT's source code, that's also what I would think.
crossScalaVersions := Seq(scalaVersion.value)
Why doesn't crossScalaVersions correspond to scalaVersion?
scalaVersion.value is context-dependent. So in Defaults.scala it's */*:scalaVersion from appConfiguration.value.provider.scalaProvider. It's the version used to compile your project's definition, including your build.sbt file (sbt 0.13.7 uses 2.10.4 scala-compiler to compile your project definitions). And that the only way as your project's definitions (including scalaVersion) isn't compiled yet when Defaults executed and crossScalaVersions defined. So, */*:crossScalaVersions depends on */*:scalaVersion not proj/*:scalaVersion.
Just compare Provided by with explicit scalaVersion := 2.11.4 inside build.sbt:
> inspect scalaVersion
[info] Setting: java.lang.String = 2.11.4
[info] Description:
[info] The version of Scala used for building.
[info] Provided by:
[info] {file:/Users/user/dev/proj/}proj/*:scalaVersion
[info] Defined at:
[info] /Users/user/dev/proj/build.sbt:1
[info] Reverse dependencies (D=derives):
[info] *:allDependencies
[info] D *:scalaBinaryVersion
[info] *:libraryDependencies
[info] *:scalaInstance
[info] *:crossScalaVersions
[info] *:update
[info] Delegates:
[info] *:scalaVersion
[info] {.}/*:scalaVersion
[info] */*:scalaVersion
[info] Related:
[info] */*:scalaVersion
And without one (just empty project):
> inspect scalaVersion
[info] Setting: java.lang.String = 2.10.4
[info] Description:
[info] The version of Scala used for building.
[info] Provided by:
[info] */*:scalaVersion
[info] Defined at:
[info] (sbt.Defaults) Defaults.scala:232
[info] Reverse dependencies:
[info] *:allDependencies
[info] *:libraryDependencies
[info] *:update
[info] *:scalaInstance
[info] Delegates:
[info] *:scalaVersion
[info] {.}/*:scalaVersion
[info] */*:scalaVersion
[info] Related:
[info] */*:scalaVersion
So, you just need to redefine */*:scalaVersion in your build.sbt:
scalaVersion in GlobalScope := "2.11.2"

Changing scala version of play from console

I should revert my project to scala 2.10.0, but it looks like I cannot from the console. I've tried to clean and rebuild with scalaVersion := "2.10.0" in the build.sbt, but it keeps using the 2.10.2.
How can I do something like "play scala-version 2.10.0" ? (which doesn't seem to be correct)
I know it uses the 2.10.2 because it is using scala-compiler and reflect 2.10.2
jacek:~/sandbox/play-ground/xApp
$ play
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Updating {file:/Users/jacek/.sbt/0.13/plugins/}global-plugins...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Loading project definition from /Users/jacek/sandbox/play-ground/xApp/project
[info] Set current project to xApp (in build file:/Users/jacek/sandbox/play-ground/xApp/)
_
_ __ | | __ _ _ _
| '_ \| |/ _' | || |
| __/|_|\____|\__ /
|_| |__/
play 2.2.2 built with Scala 2.10.3 (running Java 1.7.0_51), http://www.playframework.com
> Type "help play" or "license" for more information.
> Type "exit" or use Ctrl+D to leave this console.
[xApp] $ show scalaVersion
[info] 2.10.3
[xApp] $ set scalaVersion := "2.10.0"
[info] Defining *:scalaVersion
[info] The new value will be used by *:allDependencies, *:dependencyUpdatesData and 11 others.
[info] Run `last` for details.
[info] Reapplying settings...
[info] Set current project to xApp (in build file:/Users/jacek/sandbox/play-ground/xApp/)
[xApp] $ show scalaVersion
[info] 2.10.0
[xApp] $ session save
[info] Reapplying settings...
[info] Set current project to xApp (in build file:/Users/jacek/sandbox/play-ground/xApp/)
[xApp] $ show scalaVersion
[info] 2.10.0
[xApp] $ about
[info] This is sbt 0.13.0
[info] The current project is {file:/Users/jacek/sandbox/play-ground/xApp/}xapp 1.0-SNAPSHOT
[info] The current project is built against Scala 2.10.0
[info] Available Plugins: com.typesafe.sbt.SbtGit, com.typesafe.sbt.SbtProguard, growl.GrowlingTests, org.sbtidea.SbtIdeaPlugin, sbtman.Plugin, np.Plugin, com.timushev.sbt.updates.UpdatesPlugin, play.Project, com.typesafe.sbteclipse.plugin.EclipsePlugin, com.typesafe.sbt.SbtNativePackager
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.3
You should see the version in build.sbt in the project afterwards.
jacek:~/sandbox/play-ground/xApp
$ cat build.sbt
name := "xApp"
version := "1.0-SNAPSHOT"
libraryDependencies ++= Seq(
jdbc,
anorm,
cache
)
scalaVersion := "2.10.0"

Prevent sbt from publishing an automatically aggregated root project

I have an sbt multi project build with two projects core and mac. I don't have a root project which aggregates them. Unfortunately sbt does create one automatically.
How can I prevent this dummy aggregate project from being published? I get something like "default-6a1ca6" apart from core and mac when I run sbt publish-local.
I am looking for something like
autoRoot := false
?
For sbt 1.x you can also use
lazy val root = (project in file(".")).
aggregate(core, mac).
settings(
skip in publish := true
)
See https://github.com/sbt/sbt/issues/3136
tl;dr Use packagedArtifacts in file(".") := Map.empty
With the latest SBT 0.13.1 and the following two files (and no other files inside the project):
build.sbt
lazy val core = project
lazy val mac = project
project/build.properties
sbt.version=0.13.1
...executing sbt publish-local gives:
$ sbt publish-local
...
[info] Set current project to root-0__multi (in build file:/Users/jacek/sandbox/so/0__multi/)
...
[info] published mac_2.10 to /Users/jacek/.ivy2/local/mac/mac_2.10/0.1-SNAPSHOT/poms/mac_2.10.pom
[info] published mac_2.10 to /Users/jacek/.ivy2/local/mac/mac_2.10/0.1-SNAPSHOT/jars/mac_2.10.jar
[info] published mac_2.10 to /Users/jacek/.ivy2/local/mac/mac_2.10/0.1-SNAPSHOT/srcs/mac_2.10-sources.jar
[info] published mac_2.10 to /Users/jacek/.ivy2/local/mac/mac_2.10/0.1-SNAPSHOT/docs/mac_2.10-javadoc.jar
[info] published ivy to /Users/jacek/.ivy2/local/mac/mac_2.10/0.1-SNAPSHOT/ivys/ivy.xml
[info] published root-0__multi_2.10 to /Users/jacek/.ivy2/local/default/root-0__multi_2.10/0.1-SNAPSHOT/poms/root-0__multi_2.10.pom
[info] published root-0__multi_2.10 to /Users/jacek/.ivy2/local/default/root-0__multi_2.10/0.1-SNAPSHOT/jars/root-0__multi_2.10.jar
[info] published root-0__multi_2.10 to /Users/jacek/.ivy2/local/default/root-0__multi_2.10/0.1-SNAPSHOT/srcs/root-0__multi_2.10-sources.jar
[info] published root-0__multi_2.10 to /Users/jacek/.ivy2/local/default/root-0__multi_2.10/0.1-SNAPSHOT/docs/root-0__multi_2.10-javadoc.jar
[info] published ivy to /Users/jacek/.ivy2/local/default/root-0__multi_2.10/0.1-SNAPSHOT/ivys/ivy.xml
[info] published core_2.10 to /Users/jacek/.ivy2/local/core/core_2.10/0.1-SNAPSHOT/poms/core_2.10.pom
[info] published core_2.10 to /Users/jacek/.ivy2/local/core/core_2.10/0.1-SNAPSHOT/jars/core_2.10.jar
[info] published core_2.10 to /Users/jacek/.ivy2/local/core/core_2.10/0.1-SNAPSHOT/srcs/core_2.10-sources.jar
[info] published core_2.10 to /Users/jacek/.ivy2/local/core/core_2.10/0.1-SNAPSHOT/docs/core_2.10-javadoc.jar
[info] published ivy to /Users/jacek/.ivy2/local/core/core_2.10/0.1-SNAPSHOT/ivys/ivy.xml
[success] Total time: 2 s, completed Feb 4, 2014 1:38:28 AM
It means that by default all there projects are published.
When you however add the setting packagedArtifacts in file(".") := Map.empty to set packagedArtifacts for the current (root) project:
build.sbt
lazy val core = project
lazy val mac = project
packagedArtifacts in file(".") := Map.empty
...executing sbt publish-local gives:
$ sbt publish-local
...
[info] Set current project to root-0__multi (in build file:/Users/jacek/sandbox/so/0__multi/)
...
[info] published ivy to /Users/jacek/.ivy2/local/default/root-0__multi_2.10/0.1-SNAPSHOT/ivys/ivy.xml
[info] published core_2.10 to /Users/jacek/.ivy2/local/core/core_2.10/0.1-SNAPSHOT/poms/core_2.10.pom
[info] published core_2.10 to /Users/jacek/.ivy2/local/core/core_2.10/0.1-SNAPSHOT/jars/core_2.10.jar
[info] published core_2.10 to /Users/jacek/.ivy2/local/core/core_2.10/0.1-SNAPSHOT/srcs/core_2.10-sources.jar
[info] published core_2.10 to /Users/jacek/.ivy2/local/core/core_2.10/0.1-SNAPSHOT/docs/core_2.10-javadoc.jar
[info] published ivy to /Users/jacek/.ivy2/local/core/core_2.10/0.1-SNAPSHOT/ivys/ivy.xml
[info] published mac_2.10 to /Users/jacek/.ivy2/local/mac/mac_2.10/0.1-SNAPSHOT/poms/mac_2.10.pom
[info] published mac_2.10 to /Users/jacek/.ivy2/local/mac/mac_2.10/0.1-SNAPSHOT/jars/mac_2.10.jar
[info] published mac_2.10 to /Users/jacek/.ivy2/local/mac/mac_2.10/0.1-SNAPSHOT/srcs/mac_2.10-sources.jar
[info] published mac_2.10 to /Users/jacek/.ivy2/local/mac/mac_2.10/0.1-SNAPSHOT/docs/mac_2.10-javadoc.jar
[info] published ivy to /Users/jacek/.ivy2/local/mac/mac_2.10/0.1-SNAPSHOT/ivys/ivy.xml
[success] Total time: 1 s, completed Feb 4, 2014 1:39:34 AM
No current (root) project is published.
This answer is a work around: Create an explicit root project and disable publishing for it. I wish there was a simpler way, though.