読者です 読者をやめる 読者になる 読者になる

倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

Scala Build Tool じゃないのかよ SBT

Scala テスト

いや、知ってましたよ、「SBT」が Simple Build Tool の略だって。 とは言いつつ、sbt のサイトには何かの略だとは書いてないっぽいね。 まぁいいや。

最近ちょいと Scala をイジってみようと思い勃ったんですが、大したプロジェクトを作るわけでもないのにビルドツールを使わずにはいられない症候群を煩って、Scala プロジェクトを管理できるビルドツールを試行錯誤。 一応大雑把には使えるようになってきた Gradle では Scala もサポートしてる様なので最初はそちらを設定してたんですが、どうも普段使っている IDE の IntelliJ IDEA と併用しようとするといまいち上手くいかなかったので Gradle による管理は断念することに*1。 ま、Scala プロジェクト管理するのは Scala 用のビルドツールでいいんじゃね?ってことで、結局 SBT を使うことに決定!

SBT ってドキュメント(の一部)が日本語化されてるのね(始める sbt)。 いやー、英語のドキュメント読んでたよ。 まぁ、英語だろうが日本語だろうが文章読むの苦手なんでどっちでもいいけど。 それはともかく、ドキュメント読んでてよく分からないのが「典型的なビルド・ファイルって結局どんなの?」というところ。 SBT のコンセプトやら、Scala 言語によるビルド(プロジェクト)の設定方法とかは事細かにかいてあるんですが、どうも全体としてどんな感じのビルド・ファイルが典型的なのかよく分からんのだよね。 ちゃちいプロジェクトならほとんど設定なしに動くのも確かですが。

ということで、この記事では SBT のビルド・ファイルの自分用テンプレートを書いておきます。 ちなみに、試した SBT のバージョンは 0.12.1 です。

内容

  1. sbt のインストール
  2. sbt プロジェクトのディレクトリ構造
  3. ビルド・ファイル build.sbt

参考 URL

sbt のインストール

とりあえず sbt をインストールしないと始まりませんね。 各種 OS に対してインストーラが用意されてるので、インストールは難しくないと思います。 下記参照:

日本語のドキュメントには訳注として書いてありますが、Windows の場合はバッチファイル用意するより MSI インストーラを使う方が簡単。

プロジェクトのディレクトリ構造

sbt プロジェクトのディレクトリ構造は、デフォルトでは Maven2/3 や Gradle と同じです。 ってことで、既存の Maven2/3 プロジェクト、もしくは Gradle プロジェクトを sbt プロジェクトにするのも簡単そうですね。 また、独自のディレクトリ構造を設定することもそんなに難しくないようです(この記事では扱いませんが)。

sbt プロジェクトと Maven2/3, Gradle プロジェクトとの違いは

  • ビルド・ファイルは build.sbt
  • プロジェクトのルート下にある lib ディレクトリに Jar ファイルを配置しておくと、自動的にクラスパスに含めてくれる

という点です。

以上をまとめると、sbt プロジェクトの典型的なディレクトリ構造はこんな感じでしょう:

  • sbt-sample/
    • src/
      • main/
        • java/
        • scala/
        • resources/
      • test/
        • scala/
    • lib/
    • build.sbt

説明は不要かと思いますが

  • scala のソースコードは src/main/scala 下に配置
  • scala のテストコードは src/test/scala 下に配置

とします。 sbt は Java のソースコード、テストコードもコンパイルしてくれるので、必要なら src/main/java, src/test/java*2 に配置してください。

ビルド・ファイル build.sbt

さて、以上を踏まえて、本題のビルドファイル build.sbt を見ていきましょう。 sbt のドキュメントを最初から読んでると、なかなかどんなビルド・ファイルを書いたらいいのか分かんないところですが、下記に書かれてあるビルド・ファイルの例

に、普段よく使いそうな設定のやり方が大体書かれてました(日本語には訳されてないようですが)。 この例から、個人的によく設定している項目をピックアップして、自分用にビルド・ファイルの雛形を書いてみました:

name := "sbt-sample"
 
version := "0.1"
 
organization := "org.sample"
 
scalaVersion := "2.9.2"
 
//libraryDependencies += "org.apache.commons" % "commons-math3" % "3.0"
libraryDependencies ++= Seq(
  "org.apache.commons" % "commons-math3" % "3.0",
  "org.scala-lang" % "scala-swing" % "2.9.2",
  "junit" % "junit" % "4.10" % "test"
)
 
javacOptions ++= Seq("-source", "1.7", "-target", "1.7", "-encoding", "UTF-8")
 
scalacOptions ++= Seq("-deprecation", "-encoding", "UTF-8")
 
fork := true
 
initialCommands in console := """println("***** Console Start! *****")"""
//initialCommands in console := "import org.sample._"
 
mainClass in Compile := Some("org.sample.Main")
//mainClass in (Compile, packageBin) := Some("org.sample.Main")
//mainClass in (Compile, run) := Some("org.sample.Main")
 
crossPaths := false

半分くらいは説明不要な設定項目かと。 いくつかピックアップして簡単に解説していきます:

  • libraryDependencies は依存するライブラリを指定します。 プロジェクトのコンパイル時や実行時に必要になればダウンロードします。
    • Maven2/3 の groupId, artifactId, version (Ivy の group, module, revision だっけ?)に対応する文字列を「%」で区切って指定します(% メソッドを呼び出す)。
    • ライブラリを1つずつ指定するには「+=」、複数まとめて指定するには「++=」を使います。
    • テストにのみ使用するライブラリは 最後に「% "test"」を付ける
  • fork はプロジェクトコードやテストコードを実行する際に、別の JVM をフォークするかどうかを指定します。 Ant にもこんなのあったような。
  • initialCommands in console は sbt シェルで「console」を実行して REPL を起動する際に、初期化として実行するコードを書きます。 予め import しておきたいクラスなどがある場合に使うようです。
  • mainClass in Compile は成果物の Jar ファイルや sbt シェルでの「run 」による実行でエントリー・ポイントになるメイン・クラスを指定します
    • mainClass in (Compile, packageBin) は成果物の Jar ファイルを生成する場合のメイン・クラスを指定します。
    • mainClass in (Compile, run) は sbt シェルで「run」によってプロジェクトを実行する場合のメイン・クラスを指定します。
  • crossPaths は、false に設定すると作製する Jar ファイル名に scala のバージョンが入らなくなります。

build.sbt を書く際の注意点
build.sbt を書く際にいくつか注意点があるようです:

  • 設定項目は空白行で区切る
  • 設定値の変更は「=」ではなく「:=」でする*3

値を設定するには「:=」以外にも

  • +=, ++=
  • ~=
  • <<=
  • <+=, <++=

といったものがあるようです(More Kinds of Setting 参照)。 Scala まだあんまり知らないんですが、普通の Scala プログラミングでよく使う演算子(メソッド)なんでしょうかね。 「+=」 は元の値(コレクション)に(右辺で指定される)1つの要素を追加する、「++=」は元の値に(右辺の)コレクションの要素を全て追加するという演算子で、依存するライブラリを指定する(libraryDependencies の設定)のによく使うので要チェック。

えー、長くなりそうなので、ビルドの実行の仕方などは次回に。

Scalaスケーラブルプログラミング第2版

Scalaスケーラブルプログラミング第2版

  • 作者: Martin Odersky,Lex Spoon,Bill Venners,羽生田栄一,水島宏太,長尾高弘
  • 出版社/メーカー: インプレスジャパン
  • 発売日: 2011/09/27
  • メディア: 単行本(ソフトカバー)
  • 購入: 12人 クリック: 235回
  • この商品を含むブログ (46件) を見る
実践プログラミングDSL ドメイン特化言語の設計と実装のノウハウ (Programmer’s SELECTION) オブジェクト指向プログラマが次に読む本 ?Scalaで学ぶ関数脳入門

*1:Gradle のドキュメントによると、どうも Gradle の Idea プラグインが言語として Java にしか対応していない模様。 Scala はもちろん Groovy にも対応してないみたい。 まぁ Groovy の方は IDEA の方がデフォルトでサポートしてて普通に使えますがね。

*2:上記のディレクトリ構造には書いてない

*3:関数型言語が普通そうであるように、実際には設定値を変更しているのではなく、不変な設定を新たに生成してるそうです。