Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exit code for sbt project

Tags:

scala

akka

sbt

I have a project, build with sbt and using akka actors. I run it with "sbt 'run $args'" command and I want this program to return different exit codes depending on some condition. I use System.exit(code) from my main actor for this purposes.
Problem, I can`t solve is that sbt exit code depends on program arguments: sometimes it exits with error

java.lang.RuntimeException: Nonzero exit code returned from runner: 3        at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last compile:runMain for the full output.
[error] (compile:runMain) Nonzero exit code returned from runner: 3
[error] Total time: 5 s, completed Dec 4, 2014 6:50:50 PM

that is not beauty, but that's ok.
But in some conditions I run System.exit(3), but sbt exits with 0 exit code and [success] message.
It there a way to force sbt to exit with the same code as my program?
P.S. I`m not sure, but looks like main difference between arguments is that in first case program is executed in one thread and in the second case it executed in more then 1 thread

like image 717
Dmitry Meshkov Avatar asked Mar 08 '26 09:03

Dmitry Meshkov


1 Answers

System.exit (or better: sys.exit) quits the current runtime. If sbt forks the runtime, then calling sys.exit does not quit sbt itself but just the forked process. For example, if you have fork in Run := true, then calling sbt run will make sbt spawn a second independent JVM (the purpose being that you don't want to mess around in the same JVM obviously).

In such cases, you could define a custom run task that repeats the sys.exit for the actual sbt instance.


Edit: Here is a minimal example:

// project/build.properties
sbt.version = 0.13.6

// build.sbt
scalaVersion := "2.11.4"

lazy val myRun = taskKey[Unit]("A custom run task.")

fork in myRun := true

myRun := {
  val r   = (runner in Compile).value
  val cp  = (fullClasspath in Compile).value
  val res = r.run("foo.Bar", cp.map(_.data), Nil, streams.value.log)
  val ExitCode = "Nonzero exit code: (-?\\d+)".r
  val code = res match {
    case Some(ExitCode(c)) => c.toInt
    case _ => 0
  }
  println(s"myRun returned with $code")
  if (code != 0) sys.exit(code)
}

// src/main/scala/foo/Bar.scala 
package foo

object Bar extends App {
  println("Hello.")
  sys.exit(3)
}

To test: sbt myRun. Don't ask me why run returns an Option[String] instead of a straight Int.

like image 106
0__ Avatar answered Mar 10 '26 02:03

0__



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!