1

I'm trying to set up a Scala project, built using SBT, that will consist of a library and several command-line tools to do various things using that library. The library and tools are going to depend on another Scala project which I've installed into my local Ivy cache with sbt publish-local.

I've never used SBT before, so I'm a bit lost as to how to set this up. I would like several Linux executables or shell scripts in my top-level project directory, each of which executes a main() methods defined in a Scala file, and all of which depend on a single library. How do I get that sort of setup with an SBT project?

The way I'm thinking this will have to work is as an SBT configuration with multiple projects, and a bunch of wrapper shell scripts that execute sbt run in the appropriate project. However, when I run sbt run in my current single-project setup, I get, in addition to my program's intended output, a bunch of SBT noise:

Loading /pod/home/anovak/build/sbt/bin/sbt-launch-lib.bash
[info] Loading project definition from /pod/home/anovak/sequence-graphs/project
[info] Set current project to Sequence Graph API (in build file:/pod/home/anovak/sequence-graphs/)
[info] Running SequenceGraphs 
Sequence Graphs are great!
[success] Total time: 2 s, completed Jan 6, 2014 6:01:17 PM

I would like my wrapper scripts to be able to run my command-line tools without seeing anything from SBT on screen at all. I think the [info] and [success] messages can be suppressed by messing about with the project's log level settings, but would that eliminate the "Loading..." line as well? If not, is there some other way to run an SBT project "on its own", without much/any interference from SBT?

interfect
  • 2,665
  • 1
  • 20
  • 35

1 Answers1

1

I think what you need is one root project - sequence-graphs - with two submodules - library and cmd-tools.

project/build.properties would be as follows:

sbt.version=0.13.1

build.sbt for the root project would be as follows:

lazy val root = project in file(".") aggregate (library, `cmd-tools`)

lazy val library = project

lazy val `cmd-tools` = project dependsOn library

With only these two files you can run sbt and do projects to see the projects available.

[root]> projects
[info] In file:/Users/jacek/sandbox/so/sequence-graphs/
[info]     cmd-tools
[info]     library
[info]   * root

At the same time SBT will create necessary subdirectories for the submodules.

With the project layout you start developing your own command-line tools in cmd-tools submodule.

To make things simple, I assume that a simple App-extending applications are enough.

cmd-tools/Hello1.scala

object Hello1 extends App {
  println("Hello1")
}

cmd-tools/Hello2.scala

object Hello2 extends App {
  println("Hello2")
}

With these two Hellos you can run cmd-tools/run from SBT shell in the root project.

[root]> cmd-tools/run
[info] Compiling 2 Scala sources to /Users/jacek/sandbox/so/sequence-graphs/cmd-tools/target/scala-2.10/classes...

Multiple main classes detected, select one to run:

 [1] Hello2
 [2] Hello1

Enter number:

The same could be run from the command line as sbt cmd-tools/run:

jacek:~/sandbox/so/sequence-graphs
$ sbt cmd-tools/run
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Loading project definition from /Users/jacek/sandbox/so/sequence-graphs/project
[info] Set current project to root (in build file:/Users/jacek/sandbox/so/sequence-graphs/)

Multiple main classes detected, select one to run:

 [1] Hello1
 [2] Hello2

Enter number: 1

[info] Running Hello1
Hello1
[success] Total time: 4 s, completed Jan 9, 2014 9:44:39 PM

Let's start it over as well as disable infos and [success]es messages.

jacek:~/sandbox/so/sequence-graphs
$ sbt --error 'set showSuccess := false' cmd-tools/run

Multiple main classes detected, select one to run:

 [1] Hello1
 [2] Hello2

Enter number: 1

Hello1

There's also the runMain command that Runs the main class selected by the first argument, passing the remaining arguments to the main method.

With that and the other examples you could have a sample command-line script to execute Hello1 as follows:

sbt --error 'set showSuccess := false' 'cmd-tools/runMain Hello1'

It could be even simpler when you use the sbt-onejar plugin that can Package your project using One-JAR™ With the plugin you don't have to use SBT after you distribute your command-line tools.

Quoting the plugin's documentation:

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

Please note that the Officially supported packages of SBT add some additional checks and printouts, i.e. tgz comes with bin/sbt script that does the following (amongst the other things):

echo "Loading $(dirname "$(realpath "$0")")/sbt-launch-lib.bash"

It's not an integral part of SBT itself, but the script itself that wants to do as much as possible so an end user is, say, happy. In your case, you are not necessarily happy, so either remove the line from the script or follow the steps as described in Manual Installation.

Jacek Laskowski
  • 72,696
  • 27
  • 242
  • 420
  • `sbt --error 'set showSuccess := false' 'cmd-tools/runMain Hello1'` takes care of the [Success] and [info] lines, but does nothing about the `Loading /pod/home/anovak/build/sbt/bin/sbt-launch-lib.bash`, which is printed first thing on any invocation of the sbt command (even as the first line of output from `sbt --help`). The `sbt-onejar` plugin looks promising, but that still leaves me running a `java -jar whatever.jar` command to launch my tools, and (when I originally tried using OneJar) spat out a bunch of warnings about different versions of dependencies masking each other. – interfect Jan 14 '14 at 21:55
  • How did you install SBT? What's the version? I've seen `Loading...bash` message, but guess it's from the shell script itself rather than SBT. I found no place in the source code of SBT with `Loading` word other than for loading a project (not `.bash` file). – Jacek Laskowski Jan 14 '14 at 22:50
  • I installed SBT by downloading the official tgz package linked from http://www.scala-sbt.org/release/docs/Getting-Started/Setup.html, unzipping it, and adding the resulting bin directory to my PATH. – interfect Jan 14 '14 at 23:06
  • Added a note about the Officially supported packages of SBT that exhibit the behaviour you want to avoid. The answer should be complete now. Hint, hint: accept it if it really is :) – Jacek Laskowski Jan 16 '14 at 20:45