sbtでjavaコマンドから実行できるJAR作成

要はsbtで作ったjarファイルでこういうことがしたい

$ java -cp ./hoge/fuga.jar org.example.HelloScala
Hello,Scala!

いろいろ試した結果、sbt-proguard-pluginを使用すれば可能だとわかった。

sbt-proguard-pluginの使用方法は以下のページが詳しい。
sbtのproguardプラグインを使う


このページから変更が必要だったのはバージョン0.0.2がすでに存在していないので0.0.4を使ったのと、Projectのクラス定義を少し変えないと動かなかったことくらい。

class HelloScalaProject(info:ProjectInfo) extends DefaultProject(info) with ProguardProject
{
  def keepMainClass = """
  -keepclasseswithmembers public class *{ public static void main(java.lang.String[]);}"""
  
  override def proguardDefaultArgs = "-dontwarn" :: "-dontoptimize" :: "-dontobfuscate" :: keepMainClass :: proguardOptions
}


あとjar内部にScala実行環境を埋め込むためにscala-library.jarをプロジェクト直下のlibディレクトリにコピー。
これをしないとjavaコマンドでは実行できないので注意。


ここまで準備すれば残りはコードを普通に書くだけ。
例えばこんな感じでmainを書いて

package org.papamitra

object HelloScala extends Application{
  println("Hello,Scala!")
}

以下のコマンドを実行。

$ sbt
> update
> proguard

するとtarget/scala_/に

hoge_2.8.0_1.0.0.jar
hoge_2.8.0_1.0.0.min.jar

こんな感じの名前のファイルができる。
min.jarのほうはscala-libliry.jarが埋め込まれているので単独で実行できる。

$ java -cp hoge_2.8.0_1.0.0.min.jar org.papamitra.HelloScala
Hello,Scala!

できた。

追記:これでも実行できるみたいだ

$ java -jar hoge_2.8.0_1.0.0.min.jar
Hello,Scala!

こっちのほうがスマート。