TODESKING
技術ブログ

Scalaで作ったコンソールアプリケーションをConscriptで配布する

Conscriptの概要はREADME日本語訳などを参照

ざっくり説明すると、ConscriptというのはGitHub上のコンソールアプリプロジェクトを自動でビルド+インストールしてくれるツール。 何かツールを配布したいときは、自分のプロジェクトにConscriptの設定ファイルを含めておけばcsコマンド一発でインストール可能になって便利というやつです。

Giter8というプロジェクトテンプレート管理システム用にConscriptプロジェクトのテンプレートが提供されてるので、新規プロジェクトの時はこれ使うと良さそう。

Conscriptは何をしているのか

  • GitHub上のlaunchconfigを元に、sbt-launcherのラッパーコマンドを作成する
  • sbt-launcherは、launchconfigの内容に応じて依存ライブラリの解決とアプリケーションの起動を行う

最初勘違いしてたんだけど、GitHubからソース一式落としてきてビルドしてるわけじゃないです。launchconfig以外はmvnリポジトリ経由で取得しているので、ビルド済みのjarを公開しておかないとインストールできない。

launchconfigの書き方などが知りたいときはsbt-launcherのドキュメント読むと書いてあります。

既存プロジェクトに導入する場合

launchconfig

まずsrc/main/conscript/(実行ファイル名)/launchconfig に設定を書く

1
2
3
4
5
6
7
8
9
10
11
12
[app]
  version: 1.0.0
  org: com.todesking
  name: example
  class: com.todesking.example.Main
[scala]
  version: 2.11.4
[repositories]
  local
  scala-tools-releases
  maven-central
  todesking: http://todesking.github.io/mvn/

インストール時は[repositories]の定義を元に依存ライブラリ(アプリ本体含む)を探すので、必要な物を書いておく。 [app] class:には起動用のクラスを指定する。xsbti.AppMainを継承している必要がある。

sbtと定義内容がかぶってるので、自動生成するようにしてみた。versionは「現在mvnリポジトリから入手可能なバージョン」である必要があるので微妙なことをしている……。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// build.sbt
compile <<= (compile in Compile) dependsOn Def.task {
    val content = s"""[app]
      |  version: ${version.value.replaceAll("\\+$", "")}
      |  org: ${organization.value}
      |  name: ${name.value}
      |  class: com.todesking.nyandoc.Main
      |[scala]
      |  version: ${scalaVersion.value}
      |[repositories]
      |  local
      |  scala-tools-releases
      |  maven-central
      |  todesking: http://todesking.github.io/mvn/""".stripMargin
    val dir = (sourceDirectory in Compile).value / "conscript" / "nyandoc"
    dir.mkdirs()
    val launchconfig = dir / "launchconfig"
    IO.write(launchconfig, content)
  }

AppMain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.todesking.example

case class Exit(val code: Int) extends xsbti.Exit
class Main extends xsbti.AppMain {
  def run(config: xsbti.AppConfiguration) = {
    Exit(Main.run(config.arguments))
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    System.exit(run(args))
  }

  def run(args: Array[String]): Int = {
    // ここに実際の処理を書く

    0 // exit code
  }
}

sbt plugin

Conscript sbt plugin を指定することで、依存関係とか設定してくれるっぽい。

1
2
// project/plugins.sbt
addSbtPlugin("net.databinder" % "conscript-plugin" % "0.3.5")
1
2
// build.sbt
seq(conscriptSettings :_*)

publish設定

自前のリポジトリでjarをホスティングするためのpublish設定の例。 この設定でsbt publishすると./repo/以下に必要なファイル一式が出力されるので、適当なサーバに公開するとよい。

1
2
// build.sbt
publishTo := Some(Resolver.file("com.todesking", file("./repo/"))(Patterns(true, Resolver.mavenStyleBasePattern)))

Comments