5
votes

I'm currently using sbt-native-packager to generate a start script for my scala application. I'm using packageArchetype.java_application. I create the script in sbt:

sbt clean myproject/stage

and then "install" the application by copying the created lib and bin directories to the installation directory. I'm not distributing it to anyone, so I'm not creating an executable jar or tarball or anything like that. I'm just compiling my classes, and putting my jar and all the library dependency jars in one place so the start script can execute.

Now I want to add a second main class to my application, so I want a second start script to appear in target/universal/stage/bin when I run sbt stage. I expect it will be the same script but with a different name and app_mainclass set to the different class. How would I do this?

3

3 Answers

3
votes

The sbt-native-packager generated script allows you to pass in a -main argument to specify the main class you want to run. Here's what I do for a project named foo:

Create a run.sh script with whatever common options you want that calls the sbt-native-packager generated script:

#!/bin/bash

./target/universal/stage/bin/foo -main "$@"

Then I create a separate script for each main class I want to run. For example first.sh:

#!/bin/bash

export JAVA_OPTS="-Xms512m -Xmx512m"

./run.sh com.example.FirstApp -- "$@"

and second.sh:

#!/bin/bash

export JAVA_OPTS="-Xms2048m -Xmx2048m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC"

./run.sh com.example.SecondApp -- "$@"
3
votes

Having multiple main classes is... supported now (Q4 2016, native package 1.2.0)

See "SBT Native Packager 1.2.0" by Muki Seiler

Single Project — Multiple Apps

A major pain point for beginners is the start script creation. The bash and bat start scripts are only generated when there is a either

  • Exactly one main class
  • Explicitly set main class with
     mainClass in Compile := Some(“com.example.MainClass”)

For 1.2.x we will extends the implementation and support multiple main classes by default.

Native packager will generate a start script for each main class found on the classpath.
SBT provides them via the discoveredMainClasses in Compile task.
If there is only one main class, SBT will assign it to the mainClass in Compile setting. This leads to three cases:

  • Exactly one main class.
    In this case native-packager will behave like previous versions and just generate a single start script, using the executableScriptName setting for the script name.

  • Multiple main classes and mainClass in Compile := None.
    This is the default behaviour defined by SBT. In this case native-packager will generate the same start script for each main class.

  • Multiple main classes and mainClass in Compile := Some(…).
    The user has set a specific main class, which will lead to a main start script being generated using the executableScriptName setting. For all other main classes native-packager generates forwarder scripts.

2
votes

Having multiple main classes not supported now. As a workaround you could use single main class and check command line args. Starting your app:

myApp prog1

In your main class:

def main(args: Array[String]): Unit = {
  if(args[0] == "prog1")
    Programm1.start()
  else 
    Programm2.start()
}