开发者

How do I run an sbt main class from the shell as normal command-line program?

How can I run an sbt app from the shell, so that I can run my app as a normal command-line program (as if run directly via scala but without having to set up an enormous classpath)?

I know I can do:

echo hello | sbt 'run-main com.foo.MyMain3 arg1 arg2' > out.txt

But this (1) takes forever to start because it starts sbt, (2) causes all stdout and stderr to go to stdout, and (3) causes all output to be decorated with a logger [info] or [error].

I looked at https://github.com/harrah/xsbt/wiki/Launcher but it seems too heavyweight, since it downloads dependencies and sets up a new environment and whatnot. I just want to run this app within my existing development environment.

Thus far I've cobbled together my own script to build up a classpath, and you can also do some other things like modify your project file to get sbt to print the raw classpath,开发者_开发技巧 but I feel like there must be a better way.


Here's what I have in my SBT (version 0.10) project definition,

  val Mklauncher = config("mklauncher") extend(Compile)
  val mklauncher = TaskKey[Unit]("mklauncher")
  val mklauncherTask = mklauncher <<= (target, fullClasspath in Runtime) map { (target, cp) =>
    def writeFile(file: File, str: String) {
      val writer = new PrintWriter(file)
      writer.println(str)
      writer.close()
    }
    val cpString = cp.map(_.data).mkString(":")
    val launchString = """
CLASSPATH="%s"
scala -usejavacp -Djava.class.path="${CLASSPATH}" "$@"
""".format(cpString)
    val targetFile = (target / "scala-sbt").asFile
    writeFile(targetFile, launchString)
    targetFile.setExecutable(true)
  }

  ... // remember to add mklauncherTask to Project Settings

The mklauncher task creates a script target/scala-sbt that executes scala with the project classpath already set. It would be nice to have mklauncher executed automatically whenever the classpath changes, but I haven't looked into doing this yet.

(I use the Java classpath, rather than Scala's, for ease of creating embedded interpreters.)


The start-script SBT plugin is now at:

https://github.com/sbt/sbt-start-script

It requires a few steps to set up and generates scripts that do not work on OS X, but that can be easily fixed if you're on that platform (see below).

Setup

  1. Install greadlink (OS X only):

    a) brew install coreutils

    b) map readlink to the new function (greadlink) by adding these lines to ~/.bashrc:

    function readlink() { greadlink "$@"; }

    export -f readlink`

  2. Add start-script plugin to ~/.sbt/plugins/build.sbt:

    addSbtPlugin("com.typesafe.sbt" % "sbt-start-script" % "0.8.0")

  3. Add start-script task to current project:

    $ sbt add-start-script-tasks # execute from directory where build.sbt resides

  4. Add start-script support to current build.sbt:

    import com.typesafe.sbt.SbtStartScript

    seq(SbtStartScript.startScriptForClassesSettings: _*)

Note the blank line in between statements (de rigueur for SBT build files).

Generate Start Script

Then, whenever you want to create a script to start your app like sbt run-main, but without sbt, execute:

$ sbt start-script

Run

target/start mypackage.MyMainClass


Time flies by and a lot have changed since the other answers. It's currently SBT 0.13.6 time.

I think what you may need is the sbt-onejar plugin or the SBT Native Packager plugin.

sbt-onejar "is a simple-build-tool plugin for building a single executable JAR containing all your code and dependencies as nested JARs."

SBT Native Packager's "goal is to be able to bundle up Scala software built with SBT for native packaging systems, like deb, rpm, homebrew, msi."


Just discovered the sbt start script plugin: https://github.com/typesafehub/xsbt-start-script-plugin:

This plugin allows you to generate a script target/start for a project. The script will run the project "in-place" (without having to build a package first).

The target/start script is similar to sbt run but it doesn't rely on SBT. sbt run is not recommended for production use because it keeps SBT itself in-memory. target/start is intended to run an app in production.

The plugin adds a task start-script which generates target/start. It also adds a stage task, aliased to the start-script task.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜