SBT test:compile is not satisfied by libraryDependencies in Test - scala

I have the snippet of test case below under src/test/scala:
package example.module
import utest._
object ModuleSpec extends TestSuite { ... }
... which compiles just fine with this snippet of build.sbt below:
val testDependencies: Seq[ModuleID] =
Seq(
"com.lihaoyi" %% "utest" % "0.6.5" % "test",
)
def testSettings: Seq[Setting[_]] =
Seq(
libraryDependencies ++= testDependencies)
lazy val root =
(project in file("."))
.aggregate(subproject)
lazy val subproject =
(project in file("subproject"))
.settings(testSettings: _*)
My question is:
Why the test code does not compile anymore if I add Test axis to libraryDependencies, like shown below?
def testSettings: Seq[Setting[_]] =
Seq(
libraryDependencies in Test ++= testDependencies)
In more detail:
The line containing import utest._ fails to compile, meaning that the dependency which is now declared as part of libraryDependencies in Test was ignored.
Argumentation:
Since I'm compiling a class under src/main/test, I would expect that libraryDependencies in Test would be the necessary and the sufficient piece of information in this case. In order words: I would not expect that a wider scope would be needed.

Related

sbt cross project, shared dependencies for test example

I have a small project.
Where I have the following problem:
scalaTest needs to be added to all three dependency project (client, server, shared), otherwise the scalatest library is not accessible from all projects.
In other words, if I write
val jvmDependencies = Def.setting(Seq(
"org.scalaz" %% "scalaz-core" % "7.2.8"
)++scalaTest)
then things work fine.
But if I don't write ++scalaTest into each three dependencies then it fails like this:
> test
[info] Compiling 1 Scala source to /Users/joco/tmp3/server/target/scala-2.11/test-classes...
[error] /Users/joco/tmp3/server/src/test/scala/Test.scala:1: object specs2 is not a member of package org
[error] import org.specs2.mutable.Specification
[error] ^
[error] /Users/joco/tmp3/server/src/test/scala/Test.scala:3: not found: type Specification
[error] class Test extends Specification {
[error] ^
[error] /Users/joco/tmp3/server/src/test/scala/Test.scala:5: value should is not a member of String
[error] "Test" should {
[error] ^
[error] /Users/joco/tmp3/server/src/test/scala/Test.scala:6: value in is not a member of String
[error] "one is one" in {
[error] ^
[error] /Users/joco/tmp3/server/src/test/scala/Test.scala:8: value === is not a member of Int
[error] 1===one
[error] ^
[error] 5 errors found
[error] (server/test:compileIncremental) Compilation failed
[error] Total time: 4 s, completed Mar 18, 2017 1:56:54 PM
However for production(not test) code everything works just fine: I don't have to add 3 times the same dependencies (in this example autowire) to all three projects if I want to use a library in all three projects, it is enough to add it to only the shared project and then I can use that library from all three projects.
For test code, however, as I mentioned above, currently I have to add the same library dependency (scalaTest - below) to all three projects.
Question: Is there a way to avoid this ?
Settings.scala:
import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._
import sbt.Keys._
import sbt._
object Settings {
val scalacOptions = Seq(
"-Xlint",
"-unchecked",
"-deprecation",
"-feature",
"-Yrangepos"
)
object versions {
val scala = "2.11.8"
}
val scalaTest=Seq(
"org.scalatest" %% "scalatest" % "3.0.1" % "test",
"org.specs2" %% "specs2" % "3.7" % "test")
val sharedDependencies = Def.setting(Seq(
"com.lihaoyi" %%% "autowire" % "0.2.6"
)++scalaTest)
val jvmDependencies = Def.setting(Seq(
"org.scalaz" %% "scalaz-core" % "7.2.8"
))
/** Dependencies only used by the JS project (note the use of %%% instead of %%) */
val scalajsDependencies = Def.setting(Seq(
"org.scala-js" %%% "scalajs-dom" % "0.9.1"
)++scalaTest)
}
build.sbt:
import sbt.Keys._
import sbt.Project.projectToRef
import webscalajs.SourceMappings
lazy val shared = (crossProject.crossType(CrossType.Pure) in file("shared")) .settings(
scalaVersion := Settings.versions.scala,
libraryDependencies ++= Settings.sharedDependencies.value,
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)
) .jsConfigure(_ enablePlugins ScalaJSWeb)
lazy val sharedJVM = shared.jvm.settings(name := "sharedJVM")
lazy val sharedJS = shared.js.settings(name := "sharedJS")
lazy val elideOptions = settingKey[Seq[String]]("Set limit for elidable functions")
lazy val client: Project = (project in file("client"))
.settings(
scalaVersion := Settings.versions.scala,
scalacOptions ++= Settings.scalacOptions,
libraryDependencies ++= Settings.scalajsDependencies.value,
testFrameworks += new TestFramework("utest.runner.Framework")
)
.enablePlugins(ScalaJSPlugin)
.disablePlugins(RevolverPlugin)
.dependsOn(sharedJS)
lazy val clients = Seq(client)
lazy val server = (project in file("server")) .settings(
scalaVersion := Settings.versions.scala,
scalacOptions ++= Settings.scalacOptions,
libraryDependencies ++= Settings.jvmDependencies.value
)
.enablePlugins(SbtLess,SbtWeb)
.aggregate(clients.map(projectToRef): _*)
.dependsOn(sharedJVM)
onLoad in Global := (Command.process("project server", _: State)) compose (onLoad in Global).value
fork in run := true
cancelable in Global := true
For test code, however, as I mentioned above, currently I have to add the same library dependency (scalaTest - below) to all three projects.
That is expected. test dependencies are not inherited along dependency chains. That makes sense, because you don't want to depend on JUnit just because you depend on a library that happens to be tested using JUnit.
Although yes, that calls for a bit of duplication when you have several projects in the same build, all using the same testing framework. This is why we often find some commonSettings that are added to all projects of an sbt build. This is also where we typically put things like organization, scalaVersion, and many other settings that usually apply to all projects inside one build.

SBT published jar corrupt

I am having a really strange problem:
I have a multi-module sbt project containing libraries that I publish locally.
Every once in a while the published jar is really a POM file!
Meaning I can open it with a text editor and see the POM for the library in question instead of the class files.
cleaning and rebuilding/republishing sometimes fixes it temporarily.
Also note that the jar in 'target/scala-2.11' is also a POM file.
Here is the Build.scala and sbt file for the libraries. (names are changed to protect the guilty :) due to company policies)
//////////////////Build.scala
import java.io._
import java.nio.file.{Paths, Files}
import sbt._
import xerial.sbt.Pack._
object Library extends Build {
lazy val rootProj = Project(id = "library", base = file(".")) aggregate(
projA,
projB,
projC,
projD
)
lazy val projA = Project(id = "projectA", base = file("ProjectA"))
lazy val projB = Project(id = "projectB", base = file("ProjectB"))
lazy val projC = Project(id = "projectC", base = file("ProjectC"))
.dependsOn(spatialMathProj)
lazy val projD = Project(id = "projectD", base = file("ProjectD"))
}
//////////////////build.sbt for projectD
name := "ProjectD"
version := "2.0-SNAPSHOT"
scalaVersion := "2.11.8"
publishArtifact in (Compile, packageDoc) := false
publishArtifact in (Compile, packageSrc) := false
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.4.2"
libraryDependencies += "com.typesafe.akka" %% "akka-remote" % "2.4.2"
libraryDependencies += "net.sf.jung" % "jung2" % "2.0.1"
libraryDependencies += "net.sf.jung" % "jung-graph-impl" % "2.0.1"
libraryDependencies += "net.sf.jung" % "jung-visualization" % "2.0.1"
libraryDependencies += "com.plexsys" % "api_2.11" % "2.0-SNAPSHOT"
Has anyone else seen this?
Why is this happening?
I am using sbt version 0.13.7.
Thanks for any help you can offer.

Confused how to set up a multi-project sbt project

I'm using sbt .13 here.
I have this so far:
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val appVersion = "1.0"
resolvers += "local maven" at "/Users/blankman/.m2/repository/"
val commonDependencies = Seq()
val modelDependencies = Seq(
"com.typesafe.slick" %% "slick" % "2.0.1",
"org.slf4j" % "slf4j-nop" % "1.6.4"
)
val serviceDependencies = Seq(
"com.typesafe.slick" %% "slick" % "2.0.1",
"org.slf4j" % "slf4j-nop" % "1.6.4"
)
val webDependencies = Seq(
//"org.apache.tomcat" % "tomcat-jdbc" % "8.0.3",
"mysql" % "mysql-connector-java" % "5.1.30",
"com.typesafe.slick" %% "slick" % "2.0.1"
)
lazy val common = Project(
id = "app-common",
base = file("app-common"),
dependencies = commonDependencies
)
lazy val models = Project(
id = "app-models",
base = file("app-models"),
settings(modelDependencies: _*)
)
).dependsOn(common)
lazy val services = Project(
id = "app-services",
base = file("app-services"),
settings = Seq(
libraryDependencies ++= serviceDependencies
)
).dependsOn(models, common)
lazy val web = play.Project("app-web", appVersion, webDependencies,
path = file("app-web"))
.settings(playScalaSettings: _*)
.dependsOn(services)
}
This doesn't work. For example, if I go into:
project app-models
and try and compile, it says compile isn't valid or something.
I'm really confused how to set up a project. What is the correct way?
Looking at this slide #10 here http://jsuereth.com/scala/2013/06/11/effective-sbt.html it says I can do:
lazy val web = (
Project("app-models", file("app-models"))
settings(
libraryDependencies += modelDependencies
)
)
But when I do this I get an error also.
I basically have a few projects inside of sbt:
common
models
services
web (which is play)
models depends on commons
services depends on commons + models
web depends on services
Can someone help me get this to work?
There are a few issues I found in your build definition, but since you bought up Josh's Effective sbt talk, I think we should go whole hog on the style.
Effective sbt
Here are the files.
project/build.properties
sbt.version=0.13.2
project/play.sbt
val playVersion = "2.2.2"
resolvers += Resolver.typesafeRepo("releases")
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % playVersion)
project/commons.scala
import sbt._
import Keys._
object Commons {
val appVersion = "1.0"
val settings: Seq[Def.Setting[_]] = Seq(
version := appVersion,
resolvers += Opts.resolver.mavenLocalFile
)
}
project/dependencies.scala
import sbt._
import Keys._
object Dependencies {
val slickVersion = "2.0.1"
val slick = "com.typesafe.slick" %% "slick" % slickVersion
val slf4jVersion = "1.6.4"
val slf4jNop = "org.slf4j" % "slf4j-nop" % slf4jVersion
val mysqlConnectorVersion = "5.1.30"
val mysqlConnector = "mysql" % "mysql-connector-java" % mysqlConnectorVersion
val commonDependencies: Seq[ModuleID] = Seq(
slick,
slf4jNop
)
val modelDependencies: Seq[ModuleID] = Seq()
val serviceDependencies: Seq[ModuleID] = Seq()
val webDependencies: Seq[ModuleID] = Seq(
mysqlConnector
)
}
build.sbt
import play.Project._
import Dependencies._
lazy val appCommon = (project in file("app-common")).
settings(Commons.settings: _*).
settings(
libraryDependencies ++= commonDependencies
)
lazy val appModels = (project in file("app-models")).
settings(Commons.settings: _*).
settings(
libraryDependencies ++= modelDependencies
).
dependsOn(appCommon)
lazy val appServices = (project in file("app-services")).
settings(Commons.settings: _*).
settings(
libraryDependencies ++= serviceDependencies
).
dependsOn(appModels, appCommon)
lazy val appWeb = (project in file("app-web")).
settings(Commons.settings: _*).
settings(playScalaSettings: _*).
dependsOn(appServices)
notes
settings parameter vs settings method
For models and services, you're passing in settings sequence into Project(...) constructor, so the default settings are likely not loaded. You can pass in the default settings manually, or use settings(...) method on Project, which I would recommend.
lazy val appModels = (project in file("app-models")).
settings(
libraryDependencies ++= modelDependencies
).
dependsOn(appCommon)
Josh uses postfix notation using parenthesis, but I prefer using dot notation for this, so that's a slight deviation from the talk.
libraryDependencies ++=
As the above example, you have to pass modelDependencies to libraryDependencies. You had it calling directly into settings.
resolvers
The resolvers setting is not passed into anything, which likely is not correct.

Shapeless example with map won't compile (scala)

I'm trying to map over an HList in shapeless. The following example is derived from here:
import shapeless._
import poly._
object Main {
def main(args: Array[String]) = {
object choose extends (Set ~> Option) {
def apply[T](s : Set[T]) = s.headOption
}
val sets = Set(1) :: Set("foo") :: HNil
val opts = sets map choose // map selects cases of choose for each HList element
}
}
Unfortunately I am unable to compile the example. The compiler says "value map is not a member of HCons[scala.collection.immutable.Set[Int],HCons[scala.collection.immutable.Set[String],HNil]]". I suspect there is a missing import of an implicit that defines the map operation on HLists, but I don't know what that import should be. I'm using sbt with the following build.sbt file:
name := "scala-polymorphism-experiments"
version := "0.1.0"
scalaVersion := "2.10.3"
resolvers ++= Seq(
"Sonatype OSS Releases" at "http://oss.sonatype.org/content/repositories/releases/",
"Sonatype OSS Snapshots" at "http://oss.sonatype.org/content/repositories/snapshots/"
)
libraryDependencies ++= Seq("org.scalatest" % "scalatest_2.10" % "2.0" % "test",
"com.chuusai" % "shapeless" % "2.0.0-SNAPSHOT" cross CrossVersion.full changing())
I also have this problem if I use the M1 release of 2.0.0. What should I change to make this example compile and run?
The problem was never determined. The solution was to comment out all code in all other scala files in the project, recompile, then uncomment and compile again. No doubt an
sbt clean
would have done just as well.

libraryDependencies on sbt Build.scala Full Configuration with sub-projects

I have a project foo with two children foo-core and foo-cli, foo-cli depends on foo-core
(I come from Java/Maven and tried to transpose the parent module with 2 submodules architecture).
Following https://github.com/harrah/xsbt/wiki/Full-Configuration, I wrote my project/Build.scala this way:
import sbt._
import Keys._
object MyBuild extends Build {
//Dependencies
val slf4s = "com.weiglewilczek.slf4s" %% "slf4s" % "1.0.6"
val slf4j = "org.slf4j" %% "slf4j-simple" % "1.5.6"
val grizzled = "org.clapper" %% "grizzled-slf4j" % "0.5"
val junit = "junit" % "junit" % "4.8" % "test"
//End dependencies
lazy val root : Project = Project("root", file(".")) aggregate(cli) settings(
mainClass:= Some("Main")
)
lazy val core : Project = Project("core", file("core"), delegates = root :: Nil) settings(
name := "foo-core",
libraryDependencies ++= Seq(grizzled)
)
lazy val cli: Project = Project("cli", file("cli")) dependsOn(core) settings(
name := "foo-cli",
libraryDependencies ++= Seq(grizzled)
)
}
This configuration does not work: grizzled library is not dowloaded when I run sbt reload;sbt +update (as indicated in http://software.clapper.org/grizzled-slf4j/) and thus the "import grizzli._" fail in my core and cli projects when I sbt compile.
Since I'm new to scala/sbt I imagine I'm doing something awful but can't figure why since I'm confused with all sbt 0.7/sbt0.10 conflicting configurations that were suggested
(like Subproject dependencies in SBT).
Any idea? Hint that could help me?
Thanks in advance
That's grizzled, not grizzli you are using as dependency. The import is:
import grizzled._
This works here from console on project cli and project core, with nothing more than the configuration file above.
Are you using SBT 0.10?