How to suppress info and success messages in sbt? - scala

When I do sbt run I see some header and footer info which I would like to get rid of:
$ sbt run
[info] Set current project to XXX (in build file:/path/to/dir/)
<actual program output goes here; stuff I care about>
[success] Total time: 68 s, completed Apr 1, 2012 7:30:45 PM
$
How can I get rid of those 2 additional lines (i.e., the [info] and [success] lines)? Are there some build.sbt configuration settings available to do that? Ideally, I don't want to have another tool/dependency just to get rid of those 2 lines.
Following is a list of things I have tried:
Set run logLevel to Warn
Set Global logLevel to Warn
Set -Dsbt.log.noformat=true
The workaround that I am currently using:
Copy the java invocation that sbt generates (by doing ps or top) as a result of doing fork in run := true and manually run that java command directly on the command line.
It would be much cleaner if sbt could be told not to print those lines.
Scala version: 2.9.1
SBT version: 0.11.1

sbt 1.x, sbt 0.13.13+
Use -warn or -error. See Fixes with compatibility implications for sbt 0.13.13 release:
it is strongly encouraged to migrate to the single hyphen options: -error, -warn, -info, and -debug
sbt 0.13.1
To disable info messages run SBT with --warn or --error command line options.
To disable [success] messages set showSuccess to false.
Bringing it all together, it gives you the following options:
On command line use the following:
$ sbt --error 'set showSuccess := false' run
In build.sbt add showSuccess := false
$ cat build.sbt
showSuccess := false
and execute sbt --error run.

As Jacek mentioned in his response, in build.sbt you can add showSuccess := false to suppress the [success] message. To suppress the [info] message, I'd set the logLevel to Level.Warn for the run configuration only. Putting it together, you want to add these lines to build.sbt:
showSuccess := false
logLevel in run := Level.Warn

You should be able to get rid of the "Set current project" line by adding this to your build.sbt file:
onLoadMessage := ""

This is an old question that comes up at top of web searches, but gives the wrong answer. After this change was recently merged, the prescribed way to suppress interactive noise is by passing two flags to sbt:
sbt -batch -error ...
Works for me in sbt 1.8.0

Related

Scala: Sbt can run project, but calling the jar results in ClassNotFoundError

I have a project that will compile/package/run with SBT, but when I call the jar from the command line with Scala, I get a 'java.lang.ClassNotFoundException'.
build.sbt:
name := "coloring"
version := "0.1"
scalaVersion := "2.12.5"
libraryDependencies ++= Seq("org.scala-graph" %% "graph-core" % "1.12.5")
running sbt run results in:
[info] Compiling 1 Scala source to /path/to/dir/coloring/target/scala-2.12/classes ...
[warn] there was one feature warning; re-run with -feature for details
[warn] one warning found
[info] Done compiling.
[info] Packaging /path/to/dir/coloring/target/scala-2.12/coloring_2.12-0.1.jar ...
[info] Done packaging.
[info] Running Main
[success] Total time: 6 s, completed May 21, 2018 12:55:19 PM
However running scala target/scala-2.12/coloring_2.12-0.1.jar results in
java.lang.ClassNotFoundException: scalax.collection.GraphBase$InnerNode
What could be going wrong here? How is it possible that sbt run works, but when you call the jar directly, it fails?
EDIT: I solved the problem using sbt-assembly, but (1) I don't think this should be necessary, and (2) in similar projects in the past, I have used the exact same build.sbt and library/imports/etc and the project works when called from the command line.
If you don't want to assemble an uber-jar or similar, you'll need to have the dependencies on the classpath.
From the command line, that looks like:
scala -classpath my_1st.jar:my_2nd.jar:my_3rd.jar <whatever command>
So in your case, I imagine that looks like:
scala -classpath path/to/scala-graph.jar target/scala-2.12/coloring_2.12-0.1.jar
You can shorten -classpath to -cp
Here are quite a few other options: Include jar file in Scala interpreter
Libraries that you use need to be in the Java classpath. If you don't want to use assembly to include dependent libraries into a fat jar, you need to add them to the classpath some other way. For example via command line:
java -cp yourApp.jar:somelib.jar:someotherlibjar your.main.Class
java -cp yourApp.jar:libs/* your.main.Class

Running application using sbt run and some flags

I am currently running a akka application with the below command after I run
sbt assembly
java -Dconfig.resource=/application.test.conf -cp /path/to/folder:./target/scala-2.11/app-name.jar ca.path.to.main
Is there a way I can pass this information using sbt and some flags so I don't have to run the sbt assembly task everytime just to run the application?
sbt run config=/application.test.conf cp=/path/to/folder:
(something like the above)
Options that are passed to JVM are read by sbt from the javaOptions setting. So you can configure this setting to have the options you want and then tell sbt to fork new JVM process everytime you run your app from sbt so these options are applied. You can do this from sbt console:
set javaOptions += "-Dconfig.resource=/application.test.conf"
set fork := true
run
Or in your build.sbt file:
javaOptions += "-Dconfig.resource=/application.test.conf"
fork := true
However this might not be the most idiomatic approach to reach your underlying end goal.

How do I run sbt quietly? [duplicate]

When I do sbt run I see some header and footer info which I would like to get rid of:
$ sbt run
[info] Set current project to XXX (in build file:/path/to/dir/)
<actual program output goes here; stuff I care about>
[success] Total time: 68 s, completed Apr 1, 2012 7:30:45 PM
$
How can I get rid of those 2 additional lines (i.e., the [info] and [success] lines)? Are there some build.sbt configuration settings available to do that? Ideally, I don't want to have another tool/dependency just to get rid of those 2 lines.
Following is a list of things I have tried:
Set run logLevel to Warn
Set Global logLevel to Warn
Set -Dsbt.log.noformat=true
The workaround that I am currently using:
Copy the java invocation that sbt generates (by doing ps or top) as a result of doing fork in run := true and manually run that java command directly on the command line.
It would be much cleaner if sbt could be told not to print those lines.
Scala version: 2.9.1
SBT version: 0.11.1
sbt 1.x, sbt 0.13.13+
Use -warn or -error. See Fixes with compatibility implications for sbt 0.13.13 release:
it is strongly encouraged to migrate to the single hyphen options: -error, -warn, -info, and -debug
sbt 0.13.1
To disable info messages run SBT with --warn or --error command line options.
To disable [success] messages set showSuccess to false.
Bringing it all together, it gives you the following options:
On command line use the following:
$ sbt --error 'set showSuccess := false' run
In build.sbt add showSuccess := false
$ cat build.sbt
showSuccess := false
and execute sbt --error run.
As Jacek mentioned in his response, in build.sbt you can add showSuccess := false to suppress the [success] message. To suppress the [info] message, I'd set the logLevel to Level.Warn for the run configuration only. Putting it together, you want to add these lines to build.sbt:
showSuccess := false
logLevel in run := Level.Warn
You should be able to get rid of the "Set current project" line by adding this to your build.sbt file:
onLoadMessage := ""
This is an old question that comes up at top of web searches, but gives the wrong answer. After this change was recently merged, the prescribed way to suppress interactive noise is by passing two flags to sbt:
sbt -batch -error ...
Works for me in sbt 1.8.0

Running tests from jar with "sbt testOnly" in SBT?

As part of a CI setup the very first step is to create a package/jar using SBT dist. The following steps are to run unit, integration and functional tests with the dist-created jar.
Is it possible to do that with SBT?
Normally I use sbt testOnly "Unit.*", but that works in the context of a project. I can't find any documentation showing how to do this when there is already a jar.
I'm using ScalaTest and I know there is a runner for it I could use http://www.scalatest.org/user_guide/using_the_runner. But using SBT would be simpler, if that is possible.
As an example, something like this is what I am looking for:
sbt testOnly "Unit.* -jar myjar.jar"
Will my tests even be included in the jar when I use the following:
sbt dist
?
EDIT
I created a new folder
I added build.sbt with the following content:
name := "abc"
version := "1.0-SNAPSHOT"
scalaVersion := "2.10.0"
I added the lib folder and copied my tests jar into it
I ran sbt testOnly Unit.*
It could not find any tests
EDIT 2
I tried with the following "proper" SBT file:
name := "ihs2tests"
version := "1.0-SNAPSHOT"
scalaVersion := "2.10.0"
unmanagedBase in Test := new java.io.File(".")
and moved test.jar into the root of the project. Again, no tests found.
Normally I use sbt testOnly "Unit.*", but that works in the context of a project. I can't find any documentation showing how to do this when there is already a jar.
The test-family tasks in SBT (with testOnly as an example) work with compile task that returns a list of compiled files through an sbt.inc.Analysis instance. I couldn't figure out how to amend it and inject the changed Analysis instance to testOnly so it knows the test I'm going to run exists.
I'm proposing another solution - a trick.
Package the tests classes to a jar with test:package task as follows:
[test-lib]> test:package
[info] Updating {file:/Users/jacek/sandbox/so/test-lib/}test-lib...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 1 Scala source to /Users/jacek/sandbox/so/test-lib/target/scala-2.10/test-classes...
[info] Packaging /Users/jacek/sandbox/so/test-lib/target/scala-2.10/test-lib_2.10-0.1-SNAPSHOT-tests.jar ...
[info] Done packaging.
[success] Total time: 9 s, completed Mar 4, 2014 11:34:13 PM
When you have the test jar, you can execute the test framework on the command line without SBT (I assume you use ScalaTest given the scalatest tag, but I'll use Specs2). Read the documentation of the test framework on how to do it and for Specs2 it's specs2.run as described in Console output.
Executing tests from the test jar requires defining a proper CLASSPATH that may or may not be easy to get right. That's where SBT can be of great help - to manage dependencies and hence the CLASSPATH.
Create another SBT project and save the test jar in lib subdirectory to have it on CLASSPATH (as described in Unmanaged dependencies).
Dependencies in lib go on all the classpaths (for compile, test, run, and console).
Add a sample build.sbt where you define your test framework as a dependency of the project. For Specs2 it's as follows (I used the default configuration as described in the Specs2 home page):
libraryDependencies += "org.specs2" %% "specs2" % "2.3.8" % "test"
scalacOptions in Test ++= Seq("-Yrangepos")
The trick is to execute the main class of the test framework, e.g. specs2.run for Specs2, as if the class were executed on the command line. SBT helps with test:runMain.
[my-another-project]> test:runMain specs2.run HelloWorldSpec
[info] Running specs2.run HelloWorldSpec
HelloWorldSpec
The 'Hello world' string should
+ contain 11 characters
+ start with 'Hello'
+ end with 'world'
Total for specification HelloWorldSpec
Finished in 62 ms
3 examples, 0 failure, 0 error
Exception: sbt.TrapExitSecurityException thrown from the UncaughtExceptionHandler in thread "run-main-0"
[success] Total time: 5 s, completed Mar 4, 2014 11:15:14 PM
Don't worry about this Exception as it comes from SBT that catches exit from Specs2 (after test execution) so SBT remains up.
It seems that SBT can't read jar file without any additional/manual setup - I might be wrong but I didn't find anything in the docs. So I tried something like this to make the task simpler:
unzip some-test.jar
java -jar sbt-launch.jar \
'set scalaSource in Test := new java.io.File(".")' \
'set fullClasspath in Test += Attributed.blank(file("."))' \
'test'
This runs without errors but does not find tests.
If I add 'set includeFilter in (Test, unmanagedSources) := "*Suite*.class"' to force it to find tests it obviously fails because it expects *.scala files, not the compiled *.class files.
I'm not an SBT expert, but I think this must be close to a solution. There must be a way to read all files from a jar path programmatically and then tell test framework to use *.class files.
At this point is seems more reasonable to run tests using a Scalatest test runner or from sbt using the project.
If you wish to dig deeper take a look at SBT source code and the default sbt shell script that does lots of setup before it runs the sbt launcher jar.

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.