Scala 2.12 logging compilation too verbosely in SBT 0.13.16 - scala

Since updating to Scala 2.12, sbt logs immense amounts at info level on compilation, e.g.:
[info] /home/zoltan/workspace/reboot/juniqe/libs/db/src/main/scala/com/juniqe/db/slick/CmsBlockDao.scala:548: isomorphicType is not a valid implicit value for slick.ast.TypedType[slick.lifted.Rep[Short]] because:
[info] hasMatchingSymbol reported error: could not find implicit value for parameter iso: slick.lifted.Isomorphism[slick.lifted.Rep[Short],B]
[info] block <- CmsBlock if block.blockId === blockId
[info] ^
This looks like an error, but there is no compilation error, so I would like to silence these messages, because sometimes there's so many of them, my terminal overflows and I can't see the actual compilation errors.
How can I lower the logging level just for compilation (including test and integration test compilation)?
I've tried setting logLevel in Compile := Level.Warn, and logLevel in Compile := Level.Warn, but the messages are still there.
Setting logLevel in Global := Level.Warn does the trick, but I don't want to set it for the Global scope.
Note: This is a multi-project build, and I'm running compile from the root project.

Well, turns out that all these errors appeared because a colleague had enabled the SBT flag -Xlog-implicits, which, according to SBT "Show[s] more info on why some implicits are not applicable". After removing this flag, the errors were gone.
Source: https://paulbutcher.com/2010/04/26/scala-compiler-advanced-options/

Related

Scala sbt: How to turn off [info] messages for `~run`?

When using ~run I don't want to see [info] messages.
I have tried sbt -error and set logLevel := Level.Error but the [info] messages are still emitted.
This question is similar to How to suppress info and success messages in sbt?. However the solution there works only for sbt run whereas this question is about ~run issued after starting sbt in interactive mode (sbt -error).

How to use Quasar with Scala under sbt?

I wish to use Quasar in my SBT project. Since Scala is not yet supported the only viable option left is to have SBT compile some java classes that use of Quasar.
I tried putting
javaOptions += "-javaagent:PATH_TO_JAR/quasar-core-0.5.0.jar"
and
fork := true
as I read that for using e.g. JRebel one must insert both these statements into build.sbt
But it does not seem to work either as using a Quasarish class (QuasarExample) yields:
[error] IllegalArgumentException: : Fiber class HelloWorldSpec$$anonfun$1$$anonfun$apply$3$$anon$1 has not been instrumented. (Fiber.java:151)
[error] co.paralleluniverse.fibers.Fiber.<init>(Fiber.java:151)
[error] co.paralleluniverse.fibers.Fiber.<init>(Fiber.java:171)
[error] co.paralleluniverse.fibers.Fiber.<init>(Fiber.java:448)
A piece of code that's expected to be running without errors after successful instrumentation:
new Fiber<Integer>() {
#Override
protected Integer run() throws SuspendExecution, InterruptedException {
return 0;
}
}.start();
See also this repository for a starter.
As per the comment from #mjaskowski, Dou you plan to instrument bytecode produced by Scala compiler?, Scala is not a supported language yet.
Short answer is: absolutely. Longer answer is, yes, but not very soon.
Scala is a very (very, very, very, very) complex language (oh my god,
it's so incredibly complex!), and it would take a long time to test
Quasar with the many (many-many-many) Scala features. Given the
relatively small number of Scala developers, and the heavy integration
costs, this may take some time. We do, however support Clojure (much
simpler integration), and will soon probably (or maybe we already do)
support Kotlin (trivial integration).
Follow along to see the possible ways to have the javaagent set up in sbt.
This is my first encounter with Quasar so the steps are really basic however they should give you a head start.
Running Quasar's javaagent in JVM alone
It's only with the following command to be able to run Quasar's javaagent without any Scala/sbt's jars.
java -cp
/Users/jacek/.ivy2/cache/org.ow2.asm/asm-util/jars/asm-util-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm-commons/jars/asm-commons-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm/jars/asm-5.0.1.jar -javaagent:/Users/jacek/.ivy2/cache/co.paralleluniverse/quasar-core/jars/quasar-core-0.5.0.jar
-help
It appears it's not self-contained and needs additional jars on the CLASSPATH.
Running Quasar's javaagent with scala
The following command makes scala and Quasar's javaagent happy.
scala -debug -usebootcp -toolcp
/Users/jacek/.ivy2/cache/org.ow2.asm/asm-tree/jars/asm-tree-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm-util/jars/asm-util-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm-commons/jars/asm-commons-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm/jars/asm-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm-analysis/jars/asm-analysis-5.0.1.jar
-J-javaagent:/Users/jacek/.ivy2/cache/co.paralleluniverse/quasar-core/jars/quasar-core-0.5.0.jar
Initial attempts to run Quasar with sbt
Add the necessary dependencies of Quasar in build.sbt:
val quasarDeps = Seq(
"quasar-core",
"quasar-actors",
"quasar-galaxy"
)
libraryDependencies := quasarDeps.map("co.paralleluniverse" % _ % "0.5.0")
It boils down to augmenting libraryDependencies with necessary jars. I chose all available.
I checked in Scala console that the libraries are available.
➜ quasar-sbt xsbt
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Set current project to quasar-sbt (in build file:/Users/jacek/sandbox/quasar-sbt/)
> console
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_60).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import co.paralleluniverse.fibers._
import co.paralleluniverse.fibers._
scala> Fiber.DEFAULT_STACK_SIZE
res0: Int = 32
You will also have to add the java agent. Add the following to build.sbt:
// FIXME the path to quasar-core should be simpler
javaOptions in Test += "-javaagent:/Users/jacek/.ivy2/cache/co.paralleluniverse/quasar-core/jars/quasar-core-0.5.0.jar"
fork in Test := true
// only needed for Specs2 so I could test the test setup
libraryDependencies += "org.specs2" %% "specs2" % "2.3.13" % Test
scalacOptions in Test ++= Seq("-Yrangepos")
reload the build changes.
> reload
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Set current project to quasar-sbt (in build file:/Users/jacek/sandbox/quasar-sbt/)
Write a test to make sure all's set up properly. I used the HelloWorldSpec from [Specs2][2] with some changes:
import org.specs2.mutable._
import co.paralleluniverse.fibers._
class HelloWorldSpec extends Specification {
"Quasar" should {
"Fiber.DEFAULT_STACK_SIZE defaults to 32" in {
Fiber.DEFAULT_STACK_SIZE === 32
}
}
}
It's not a very extensive test, so tweak it for your needs. Save the file under src/test/scala.
Execute test.
> test
objc[27427]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.7.0_60.jdk/Contents/Home/jre/bin/java and /Library/Java/JavaVirtualMachines/jdk1.7.0_60.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
[info] HelloWorldSpec
[info]
[info] Quasar should
[info] + Fiber.DEFAULT_STACK_SIZE defaults to 32
[info]
[info] Total for specification HelloWorldSpec
[info] Finished in 40 ms
[info] 1 example, 0 failure, 0 error
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 4 s, completed Jul 13, 2014 2:04:13 PM
It works!

Make one sbt config depend on another

The sbt documentation shows example of how to declare dependency only between projects. But I'm positive that there are ways to declare one config be dependent on another, just like the Test configuration uses classpath from the Compile configuration.
How can I declare my own configuration so that it would depend on the Compile config generated classpath?
I take a more close look to suggested solution and bunch of question arose again. So I reopen the question
I can not deduce sbt behavior solely from the delegate relation between Test and Compile config.
The source directories turn out to be completely different for Test and Compile config despite being delegated.
> show test:unmanagedSourceDirectories
[info] List(./src/test/scala, ./src/test/java)
> show test:scalaSource
[info] ./src/test/scala
> show test:javaSource
[info] ./src/test/java
> show compile:unmanagedSourceDirectories
[info] List(./src/main/scala, ./src/main/java)
> show compile:scalaSource
[info] ./src/main/scala
> show compile:javaSource
[info] ./src/main/java
And other significant keys such as unmanagementClasspath and fullClasspath are not SettingsKeys that may be naturally stacked with delegating. They are full-fledged TaskKeys that stores complex procedure for generating class-paths behind them.
So, the question is still actual: How can I mimic exporting classes from Compile to Test config for my custom defined config? And there is closely related optional question: how this is actually done for aforementioned pre-defined configs?
You can make one configuration extend another. You do that by using extend method.
lazy val MyConfig = config("myConfig") extend(Compile)
lazy val root = project.in(file(".")).
configs(MyConfig).
settings(inConfig(MyConfig)(Defaults.compileSettings ++ Defaults.compileInputsSettings): _*)
Extend will delegate to Compile in this case, for settings which are undefined in the MyConfig configuration.
You can check it by running SBT and executing for example show myConfig:managedClasspath, the output should be exactly the same as for show compile:managedClasspath.
If you inspect your new configuration's managedClasspath you'll see that it delegates to the compile.
[info] Delegates:
[info] myConfig:managedClasspath
[info] compile:managedClasspath
[info] *:managedClasspath
[info] {.}/myConfig:managedClasspath
[info] {.}/compile:managedClasspath
[info] {.}/*:managedClasspath
[info] */myConfig:managedClasspath
[info] */compile:managedClasspath
[info] */*:managedClasspath
As I've stated above, SBT will only delegate to the setting if it's not defined in the given configuration.
For example, if you do not define any specific compiler options for myConfig the settings will be taken from compile.
> show compile:scalacOptions
[info] List()
> show myConfig:scalacOptions
[info] List()
Changing setting in compile configuration will have an effect on myConfig:
> set scalacOptions in Compile += "-Xexperimental"
> show compile:scalacOptions
[info] List(-Xexperimental)
> show myConfig:scalacOptions
[info] List(-Xexperimental)
Overriding the setting in myConfig will make SBT to use the setting defined in that configuration, while Compile will have its own value:
> set scalacOptions in MyConfig := Seq("-Xcheck-null")
> show compile:scalacOptions
[info] List(-Xexperimental)
> show myConfig:scalacOptions
[info] List(-Xcheck-null)
Note the delegation is one way. Change to the MyConfig has no influence on the Compile configuration.
You can check the documentation for details.

how to set main class in SBT 0.13 project

Could you guys please explain to me how to set main class in SBT project ? I'm trying to use version 0.13.
My directory structure is very simple (unlike SBT's documentation). In the root folder I have build.sbt with following content
name := "sbt_test"
version := "1.0"
scalaVersion := "2.10.1-local"
autoScalaLibrary := false
scalaHome := Some(file("/Program Files (x86)/scala/"))
mainClass := Some("Hi")
libraryDependencies ++= Seq(
"org.scalatest" % "scalatest_2.10" % "2.0.M5b" % "test"
)
EclipseKeys.withSource := true
And I have subfolder project with single file Hi.scala which contains following code
object Hi {
def main(args: Array[String]) = println("Hi!")
}
I'm able to compile it by calling sbt compile but sbt run returns
The system cannot find the file C:\work\externals\sbt\bin\sbtconfig.txt.
[info] Loading project definition from C:\work\test_projects\sbt_test\project
[info] Set current project to sbt_test (in build file:/C:/work/test_projects/sbt_test/)
java.lang.RuntimeException: No main class detected.
at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last compile:run for the full output.
[error] (compile:run) No main class detected.
[error] Total time: 0 s, completed Apr 8, 2013 6:14:41 PM
You need to put your application's source in src/main/scala/, project/ is for build definition code.
Try to use an object and extend it from App instead of using class
object Main extends App {
println("Hello from main scala object")
}
Here is how to specify main class
mainClass in (Compile,run) := Some("my.fully.qualified.MainClassName")
For custom modules in SBT (0.13), just enter on the SBT console:
project moduleX
[info] Set current project to moduleX (in build file:/path/to/Projects/)
> run
[info] Running main
to switch scope to moduleX, as define in Built.scala. All main classes within that scope will be detected automatically. Otherwise you get the same error of no main class detected.
For God's sake, SBT does not tell you that the default scope is not set. It has nothing to do with default versus non default source folders but only with SBT not telling anything that it doesn't know which module to use by default.
Big Hint to typesafe: PLEASE add a default output like:
[info] Project module is not set. Please use ''project moduleX'' set scope
or set in Built file (LinkToDocu)
at the end of SBT start to lower the level of frustration while using SBT on multi module projects.....
I had the same issue: was mode following the tutorial at http://www.scala-sbt.org/0.13/docs/Hello.html, and in my opinion, as a build tool sbt's interaction and error messages can be quite misleading to a newcomer.
It turned out, hours of head scratching later, that I missed the critical cd hello line in the example each time. :-(
If you have multiple main methods in your project you can add the following line to your build.sbt file:
val projectMainClass = "com.saeed.ApplicationMain"
mainClass in (Compile, run) := Some(projectMainClass)
If you want to specify the class that will be added to the manifest when your application is packaged as a JAR file, add this line to your build.sbt file:
mainClass in (Compile, packageBin) := Some(projectMainClass)
You can also specify main class using run-main command in sbt and activator to run:
sbt "run-main com.saeed.ApplicationMain"
or
activator "run-main com.saeed.ApplicationMain"
There are 4 options
you have 1 main class
sbt run and sbt will find main for you
you have 2 or more main classes
sbt run and sbt will propose to select which one you want to run.
Multiple main classes detected, select one to run:
[1] a.b.DummyMain1
[2] a.b.DummyMain2
Enter number:
You want to set main class manually.
mainClass in run := Some("a.b.DummyMain1")
You could run with main class as parameter
sbt runMain a.b.DummyMain1
If the Main class is in a different project then by setting the below command in build.sbt would work:
addCommandAlias("run", "; project_folder/run")
I had the same issue. Resolved it after adding PlayMinimalJava plugin in build.sbt.
Not sure how it got fixed, if someone can highlight how PlayMinimalJava solves it, would be great.
enablePlugins(PlayMinimalJava)
My build.sbt looks like this
organization := "org"
version := "1.0-SNAPSHOT"
scalaVersion := "2.13.1"
libraryDependencies += guice
enablePlugins(PlayMinimalJava)
Log
C:\Users\KulwantSingh\repository\pdfdemo>sbt run
Java HotSpot(TM) Client VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[info] Loading settings for project pdfdemo-build from plugins.sbt ...
[info] Loading project definition from C:\Users\KulwantSingh\repository\pdfdemo\project
[info] Loading settings for project pdfdemo from build.sbt ...
[info] Set current project to pdfdemo (in build file:/C:/Users/KulwantSingh/repository/pdfdemo/)
[warn] There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings.
--- (Running the application, auto-reloading is enabled) ---
[info] p.c.s.AkkaHttpServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
(Server started, use Enter to stop and go back to the console...)
[info] Compiling 6 Scala sources and 2 Java sources to C:\Users\KulwantSingh\repository\pdfdemo\target\scala-2.13\classes ...
[info] p.a.h.EnabledFilters - Enabled Filters (see <https://www.playframework.com/documentation/latest/Filters>):
play.filters.csrf.CSRFFilter
play.filters.headers.SecurityHeadersFilter
play.filters.hosts.AllowedHostsFilter
[info] play.api.Play - Application started (Dev) (no global state)
Incase if someone made a silly mistake like I did.
Check if your project is sbt-multi project.
If it is make sure to provide sbt moduleName/run instead sbt run
I keep making this mistaken when I switch between multi and single projects.

How to change Scala version for build definition?

I'm developing a simple SBT project that includes InputTasks for benchmarking Scala Parallel collections.
I have defined the InputKeys and started writing the tasks when I encountered a problem.
Since my benchmarks require Scala 2.10.0-M5, I tried doing this in my build.sbt:
name := "scala-parallel-collection-benchmark"
version := "1.0.0"
organization := "com.google.summer"
scalaVersion := "2.10.0-M5"
However, at compilation I get the following error:
[info] Loading project definition from C:\Users\Administrator\scala-parallel-collection-benchmark\project
[info] Compiling 1 Scala source to C:\Users\Administrator\scala-parallel-collection-benchmark\project\target\scala-2.9.1\sbt-0.11.3\classes...
[error] C:\Users\Administrator\scala-parallel-collection-benchmark\project\Build.scala:47: value tasksupport is not a member of scala.collection.parallel.mutable.ParArray[Int]
[error] collection.tasksupport = new ForkJoinTaskSupport(new ForkJoinPool(par))
[error] ^
[error] one error found
[error] {file:/C:/Users/Administrator/scala-parallel-collection-benchmark/project/}default-e0b2a2/compile:compile: Compilation failed
It appears that it still uses Scala 2.9.1 to compile it.
How can I set up SBT so it compiles my code using Scala 2.10.0-M5?
scalaVersion only impacts the version of Scala used to compile the "actual" source code (usually located in src/...). Your error comes from a part of the build definition (under project/), which is always compiled with the Scala version that sbt was built with.
You can't modify the version of Scala that is used to to compile the project definition, because it must be a version binary compatible with the version used to compile SBT itself. There's some flexibility being studied in this regard, but, right now, it's fixed.
The setting scalaVersion will change the version of Scala used to compile the project itself. The project can be compiled with completely different versions and, in fact, you can even have SBT compile your project with multiple Scala versions.
you can change the scala version in file "project/build.properties"
e.g. sbt.version=0.11.2