This is an excerpt from the 1st Edition of the Scala Cookbook. This is Recipe 18.9, “How to Specify a Main Class to Run with SBT.”
Problem
In a Scala SBT project, you have multiple main
methods in objects in your project, and you want to specify which main
method should be run when you type sbt run
, or specify the main
method that should be invoked when your project is packaged as a JAR file.
Solution
If you have multiple main
methods in your project and want to specify which main
method to run when typing sbt run
, add a line like this to your build.sbt file:
// set the main class for 'sbt run'
mainClass in (Compile, run) := Some("com.alvinalexander.Foo")
This class can either contain a main
method, or extend the App
trait.
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:
// set the main class for packaging the main jar
mainClass in (Compile, packageBin) := Some("com.alvinalexander.Foo")
That setting tells SBT to add the following line to the META-INF/MANIFEST.MF file in your JAR when you run sbt package
:
Main-Class: com.alvinalexander.Foo
Update!
The examples in this article show the syntax that used to be used in SBT. The newer syntax now looks like this:
Compile / mainClass := Some("com.alvinalexander.Foo"
)
Similarly, I believe this is the correct syntax to specify a main method when you’re creating an all-in-one JAR file using sbt-assembly:
assembly / mainClass := Some("com.alvinalexander.Foo")
Using run-main (or the newer 'runMain')
When running your application with SBT, you can also use SBT’s run-main
(runMain
) command to specify the class to run. Invoke it like this from your operating system command line:
$ sbt "run-main com.alvinalexander.Foo"
[info] Loading global plugins from /Users/Al/.sbt/plugins
[info] Running com.alvinalexander.Foo
hello
[success] Total time: 1 s
Invoke it like this from inside the SBT shell:
$ sbt
> run-main com.alvinalexander.Foo
[info] Running com.alvinalexander.Foo
hello
[success] Total time: 1 s
UPDATE:
run-main
has been changed torunMain
in sbt.
Discussion
If you have only one main
method in an object in your project (or one object that extends the App
trait), SBT can automatically determine the location of that main
method. In that case, these configuration lines aren’t necessary.
If you have multiple main
methods in your project, and don’t use any of the approaches shown in the Solution, SBT will prompt you with a list of objects it finds that have a main
method or extend the App
trait when you execute sbt run
:
Multiple main classes detected, select one to run:
[1] com.alvinalexander.testproject.Foo
[2] com.alvinalexander.testproject.Bar
The following code shows what a build.sbt file with both of the mainClass
settings looks like:
name := "Simple Test Project"
version := "1.0"
scalaVersion := "2.10.0"
// set the main class for packaging the main jar
mainClass in (Compile, packageBin) := Some("com.alvinalexander.testproject.Foo")
// set the main class for the main 'sbt run' task
mainClass in (Compile, run) := Some("com.alvinalexander.testproject.Foo")
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
When your sbt mainClass has command-line parameters
When your main class (mainClass
) requires command-line parameters, do the initial configuration in the build.sbt file as shown above, and then when you run your main method/class from inside sbt, supply the parameters there:
sbt> run hello world
For instance, the code that generates this website is written in Scala, and my build.sbt mainClass
setting looks like this:
mainClass in (Compile, run) := Some("static_drupal.GenAllNodes")
Then when I want to regenerate all of the web pages that have been updated in the last ten days, I use this sbt run
command:
sbt> run 10
If you need to use sbt and run a main class that has command line arguments, I hope this example is helpful.
See Also
- The SBT Quick Configuration documentation shows dozens of build.sbt examples