コンニチハ!システムインテグレーション部の遠藤です。

前回、ScalaでHello Worldをご紹介させていただきましたが、今回は、Scalaを使う上でなくてはならないsbtをご紹介したいと思います。

sbtとは?

http://www.scala-sbt.org/0.13.0/docs/home.html

sbtとは、簡単に言うとScala用のビルドツールです。

コンパイルはもちろん、プロジェクトに必要なパッケージやライブラリの管理を行ってくれる非常に怖い強力なツールです。

前回、Scalaのソースファイルをコンパイルする際、「Scalac」を実行してからの応答時間が気になった方もいましたでしょう。

Scalaのコンパイルは重たいそうですが、その点sbtを利用すれば、あまり気にならなくなります。

(と、聞いたことがある気がします笑)

インストール

さて、早速sbtの実行環境をインストールしてみましょう。

Mac

インストール方法は様々ですが、今回もHomebrewでインストールしてしまいましょう。

$ brew install sbt

Windows

Windowsのインストール方法も幾つかあります。今回は下記からmsiをダウンロードしてインストールしましょう。

http://www.scala-sbt.org/release/docs/Getting-Started/Setup.html

その他、詳しくは上記をご参照ください。

インストール確認

コマンドラインツールで下記のように確認します。

尚、「CURRENT_DIRECTORY」には、お使いのマシンのカレントディレクトリが表示されます。

$ sbt sbt-version
[info] Set current project to CURRENT_DIRECTORY (in build file:CURRENT_DIRECTORY)
[info] 0.13.1

ディレクトリ構造

sbtを利用するには、下記のようなディレクトリ構造となっている必要があります。

$ tree
.
└── src
     └── main
          ├── java
          └── scala

今回は「MyProject」というルートフォルダを作成して、その中で操作していきましょう。

ではMyProject配下のディレクトリを作成します。

後ほど、sbtを利用してJavaのリソースもコンパイルしてみたいとおもいますので、Scalaのソース配置用の「MyProject/src/main/scala」とJavaのソース配置用の「MyProject/src/main/java」の二つのディレクトリを下記のように作成しましょう。

$ mkdir -p MyProject/src/main/scala
$ mkdir -p MyProject/src/main/java
$ cd MyProject/
$ tree
.
└── src
    └── main
        ├── java
        └── scala

Configuration Fileを作成

Configuration Fileとは、ビルドの元となるファイルです。

Configuration Fileには簡素な記述が出来る「Basic Configuration」と、さらに詳細な記述が出来る「Full Configuration」の2種類があります。

Basic Configuration

Basic Configuration Fileは「Build.sbt」といった名前でファイルを作成し、下記のように記述し、プロジェクトのルートディレクトリに配置します。

name := "My Project"
version := "1.0"
scalaVersion := "2.10.0"

引用元:http://www.scala-sbt.org/

Full Configuration

今回はBasic Configurationを利用しますので、こちらは参考程度に。

Full Configuration Fileは「Build.scala」といった名前で(つまりScalaのソースとして)ファイルを作成し、「project/」配下に配置します。

$ mkdir ./project

次に、下記内容のファイルを「project/」配下に「Build.scala」として作成してください。

import sbt._
import Keys._

object MyBuild extends Build {
  lazy val root = Project (
    "MyProject",
    file("."),
    settings = Seq(
      version := "1.0",
      scalaVersion := "2.10.0"
    )
  )
}

Configuration作成後

下記のようなディレクトリ構造になっていればOKです。

$ tree
.
├── build.sbt
└── src
    └── main
        ├── java
        └── scala

Hello Worldの作成

sbtを動かす前に、コンパイル対象のプログラムを作成しましょう。今回ScalaとJavaの両方でHello Worldを作成します。

Scala

Scalaの場合は前回と同じで良いでしょう。

object名はわかりやすく「HelloWorldScala」としています。

$ vim src/main/scala/HelloWorldScala.scala

 

object HelloWorldScala {
  def main(args: Array[String]) :Unit = {
    println("Hello World by Scala")
  }
}

Java

Javaの場合についても、下記のように簡単で良いでしょう。

$ vim src/main/java/HelloWorldJava.java

 

public class HelloWorldJava {
    public static void main(String[] args) {
        System.out.println("Hello World by Java");
    }
}

ビルドの実行

ここまでで、下記のディレクトリ構造になっていればOKです。

$ tree
.
├── build.sbt
└── src
    └── main
        ├── java
        |   └── HelloWorldJava.java
        └── scala
            └── HelloWorldScala.scala

ではさっそくsbtを使ってコンパイルします。
下記のコマンドを実行してください。

$ sbt compile
[success] Total time: 9 s, completed 2014/02/07 21:54:01

特にエラーが無ければ、sbtを利用したコンパイルが成功です。
成功すると、ディレクトリ構造が下記のようになります。

$ tree
.
├── build.sbt
├── project
│   └── target
│       └── config-classes
│           ├── $14759fddb42336a049c0$$anonfun$$sbtdef$1.class
│           ├── $14759fddb42336a049c0$.class
│           ├── $14759fddb42336a049c0.cache
│           ├── $14759fddb42336a049c0.class
│           ├── $16780968a37baefb5487$$anonfun$$sbtdef$1.class
│           ├── $16780968a37baefb5487$.class
│           ├── $16780968a37baefb5487.cache
│           ├── $16780968a37baefb5487.class
│           ├── $b38b1b79c238fe617138$$anonfun$$sbtdef$1.class
│           ├── $b38b1b79c238fe617138$.class
│           ├── $b38b1b79c238fe617138.cache
│           └── $b38b1b79c238fe617138.class
├── src
│   └── main
│       ├── java
│       │   └── HelloWorldJava.java
│       └── scala
│           └── HelloWorldScala.scala
└── target
    ├── resolution-cache
    │   ├── myproject
    │   │   └── myproject_2.10
    │   │       └── 1.0
    │   │           ├── resolved.xml.properties
    │   │           └── resolved.xml.xml
    │   └── reports
    │       ├── ivy-report.css
    │       ├── ivy-report.xsl
    │       ├── myproject-myproject_2.10-compile-internal.xml
    │       ├── myproject-myproject_2.10-compile.xml
    │       ├── myproject-myproject_2.10-docs.xml
    │       ├── myproject-myproject_2.10-optional.xml
    │       ├── myproject-myproject_2.10-plugin.xml
    │       ├── myproject-myproject_2.10-pom.xml
    │       ├── myproject-myproject_2.10-provided.xml
    │       ├── myproject-myproject_2.10-runtime-internal.xml
    │       ├── myproject-myproject_2.10-runtime.xml
    │       ├── myproject-myproject_2.10-scala-tool.xml
    │       ├── myproject-myproject_2.10-sources.xml
    │       ├── myproject-myproject_2.10-test-internal.xml
    │       └── myproject-myproject_2.10-test.xml
    ├── scala-2.10
    │   └── classes
    │       ├── HelloWorld$.class
    │       ├── HelloWorld.class
    │       └── HelloWorldJava.class
    └── streams
        ├── $global
        │   ├── $global
        │   │   └── $global
        │   │       └── out
        │   ├── ivyConfiguration
        │   │   └── $global
        │   │       └── out
        │   ├── ivySbt
        │   │   └── $global
        │   │       └── out
        │   ├── projectDescriptors
        │   │   └── $global
        │   │       └── out
        │   └── update
        │       └── $global
        │           ├── inputs
        │           ├── out
        │           └── output
        └── compile
            ├── $global
            │   └── $global
            │       └── data
            ├── compile
            │   └── $global
            │       ├── export
            │       └── out
            ├── dependencyClasspath
            │   └── $global
            │       └── export
            ├── externalDependencyClasspath
            │   └── $global
            │       └── export
            ├── incCompileSetup
            │   └── $global
            │       └── inc_compile
            ├── internalDependencyClasspath
            │   └── $global
            │       └── export
            ├── managedClasspath
            │   └── $global
            │       └── export
            ├── unmanagedClasspath
            │   └── $global
            │       └── export
            └── unmanagedJars
                └── $global
                    └── export

コンパイルされたプログラムの実行

実行は下記のコマンドで行えます。

$ sbt run

sbtはプロジェクト内の実行可能なプログラムを探しに行きます。
今回の場合、Scala版とJava版のHello Worldを作成しているので、実行可能なリソースは2つとなり、下記のようにコンソールに表示されるはずです。

$ sbt run
[info] Set current project to MyProject (in build file:/CURRENT_DIRECTORY/MyProject/)

Multiple main classes detected, select one to run:

 [1] HelloWorldJava
 [2] HelloWorldScala

Enter number:

ScalaのHello Worldを実行するため、「2」を入力しましょう。

Enter number: 2

[info] Running HelloWorldScala
Hello World by Scala
[success] Total time: 12 s, completed 2014/02/07 21:59:53

JavaのHello Worldを実行するため、「1」を入力しましょう。

$ sbt run
[info] Set current project to MyProject (in build file:/CURRENT_DIRECTORY/MyProject/)

Multiple main classes detected, select one to run:

 [1] HelloWorldJava
 [2] HelloWorldScala

Enter number: 1

[info] Running HelloWorldJava
Hello World by Java
[success] Total time: 3 s, completed 2014/02/07 22:01:28

さいごに

いかがでしたでしょうか?

今回はコンパイルをするだけという簡単な例でしたが、ほかにも様々な機能があります。

自動でさまざまなライブラリをMavenのCentral Repositoryからダウンロードしてビルドすることもできたりと、Scalaを使う上で非常に強力なツールとなりますので、是非一度お試しください!

かく言う遠藤もまだまだ勉強中ですので、覚えた事は今後も随時ここでご紹介させていただきます!

一緒に使いこなせる様になりましょう!