exewrap を使う

実行可能 JAR ファイルから EXE ファイルを作成してくれるとても有り難いツール、それが exewrap。

http://www.ne.jp/asahi/web/ryo/exewrap/

SBT(Simple Build Tool)から exewrap を使ってみたいと思います。折角なのでプラグイン風にしてみます。

まずは exewrap を先程のサイトからダウンロードし、exewrap.exe をパスが通っているディレクトリに置きます。

次に、下記のように project/build/ExewrapPlugin.scala を作成します。

import sbt._
import Process._

trait ExewrapPlugin extends MavenStyleScalaPaths {
  // description
  val exewrapDescription = "Native executable java application wrapper."
  // command
  lazy val exewrap = exewrapAction
  // action
  protected def exewrapAction =
    task(exewrapTask) describedAs (exewrapDescription)
  // task executor
  private def exewrapTask = {
    val opts: List[String] = List(
      if (isGuiApplication) Some("-g") else None,
      if (isServiceApplication) Some("-s") else None,
      targetVersion.map("-t " + _),
      if (!extFlags.isEmpty) Some(extFlags.mkString("-e ", ";", "")) else None,
      vmArgs.map("-a " + _),
      iconFile.map("-i " + _),
      Some("-v " + version),
      description.map("-d " + _),
      copyright.map("-c " + _),
      Some("-j " + jarFile),
      exeFile.map("-o " + _)).flatten
    val command = ("exewrap.exe" :: opts).mkString(" ")
    command ! log
    None
  }

  /**
   * User configurable options
   */
  def isGuiApplication: Boolean = false
  def isServiceApplication: Boolean = false
  def targetVersion: Option[String] = None
  def extFlags: List[String] = List()
  def vmArgs: Option[String] = None
  def iconFile: Option[Path] = None
  def description: Option[String] = None
  def copyright: Option[String] = None
  def jarFile: Path = jarPath
  def exeFile: Option[Path] = None
}

さらに、project/build/MyProject.scala を編集します。

import sbt._

class MyProject(info: ProjectInfo) extends DefaultProject(info) with ExewrapPlugin {
  override def mainClass = Some("xx.inosix.Main")

  // for ExewrapPlugin
  override def isGuiApplication: Boolean = true
  override def targetVersion: Option[String] = Some("1.6")
  override def extFlags: List[String] = List("SINGLE")
  override def iconFile: Option[Path] = Some(mainResourcesPath / "xx" / "inosix" / "logo.ico")
  override def exeFile: Option[Path] = Some(outputPath / "inosix.exe")
  override def exewrapAction = super.exewrapAction dependsOn (`package`)
}

exewrap で指定する JAR ファイルは実行可能である必要があるので mainClass メソッドをオーバライドする必要があります。exewrap コマンドを実行するときは package コマンドを実行しておいて欲しいので、exewrapAction メソッドをオーバライドして dependsOn を追加しています。

以上のことを行って SBT から reload コマンドを実行して、ExewrapPlugin と MyProject をビルドします。そうすると exewrap コマンドが実行可能になるので SBT で exewrap コマンドを実行すると EXE ファイルが作成されます。

Version Info

  • Scala 2.8.1
  • SBT 0.7.4
  • exewrap 0.9.6