Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom 'run' like task for for a project

Tags:

scala

build

sbt

By default, the run task for my SBT build executes my main class found (automatically) in src/main/scala/.

How can I add a new task for a project that behaves just like the run task but finds a main class in src/util/scala? The task should run the util main method with src/main/scala on the classpath.

I am using SBT 0.12.4 with a full multi project configuration.

like image 648
Andy Avatar asked Nov 02 '22 06:11

Andy


2 Answers

The following defines a new configuration that compiles sources from src/util/scala and defines util:run and util:run-main to run main classes from the new configuration. The compiled sources from src/main/scala are available on the classpath when compiling and running.

import sbt._
import Keys._

object MyBuild extends Build
{
   // Define a new configuration named `util`.
   //   Extending `Compile` means the main classpath is available to `util`
   lazy val Util = config("util").extend(Compile)

   // Add the new configuration to the project.
   // Add the new settings.
   lazy val root = Project("root", file(".")).configs(Util).settings( utilSettings : _*)

   // Add the basic source, compilation, and packaging settings
   //   as well as custom run methods.
   lazy val utilSettings = inConfig(Util)( Defaults.configSettings ++ utilRunSettings )

   // Settings that define `run` and `run-main` to use the
   // classpath from the enclosing configuration.
   // (The standard `run` methods use the `Runtime` configuration.
   lazy val utilRunSettings = Seq(
        run <<= Defaults.runTask(fullClasspath, mainClass in run, runner in run),
        runMain <<= Defaults.runMainTask(fullClasspath, runner in run)
   )
}

(Was tested on 0.13, but should work on 0.12.)

like image 114
Mark Harrah Avatar answered Nov 15 '22 07:11

Mark Harrah


I don't think sbt will find code that you put in src/util/... it should go in src/main/scala, src/test/scala, etc. You might want to add utility classes to some kind of "util" package, maybe in src/main/com/example/util, or put them in a sub project or dependent project, but sbt isn't really designed (afaik) to be able to handle arbitrary directory structures.

As far as setting up multiple main methods, sbt run, if it finds multiple main methods in src/main/scala, will let you choose which one to call.

If it's in an external jar you may need to: Configuring sbt project to include external Main methods in "sbt run"

What I usually do is run sbt console and then just import and call the main method directly from there. For example:

sbt console
import com.example.Main
Main(new String[])

Since you have sub-projects, if one of your projects is "util," you should be able to use something like sbt util/run to run a main method in util/src/main/scala.

You should also be able to use sbt "util/run-main com.example.MainClass" if you have multiple main methods in one project.

You might also consider the sbt start-script plugin: https://github.com/sbt/sbt-start-script

like image 40
nairbv Avatar answered Nov 15 '22 06:11

nairbv