ObjectSquare [2011 年 1 月号]

[オージス総研の本]




プログラミングScalaの表紙
(写真はオライリー・ジャパン様より引用)

プログラミング Scala


Dean Wampler, Alex Payne著
株式会社オージス総研 オブジェクトの広場編集部訳
オライリー・ジャパン 定価 3,990 円(税込)
2011/01出版
ISBN:978-4-87311-481-1

原著:https://oreilly.com/catalog/9780596155964

まえおき

オブジェクトの広場編集部の有志で O'Reilly Media Inc. の『 Programming Scala 』の翻訳を行いました。 Scala はオブジェクト指向と関数型を高度に融合させたハイブリッドの言語で、Java の次の言語として非常に注目されています。 本書『プログラミング Scala 』はこれから Scala を始める方、さらにScalaについて深く知りたい方に向けた Scala の入門書です。 Scala2.7と2.8に対応しています。

今回オライリー・ジャパン様から特別に許可をいただき、オブジェクトの広場に本書の一部を公開することが可能になりました。 訳者まえがきと日本語版オリジナルの 15 章の一部を公開いたします。


目次


訳者まえがき

2006年頃に Ruby on Rails を知ったとき、生産性の高さやアーキテクチャそのものよりも、その実装に驚きました。 それまでの Ruby のライブラリのほとんどには、標準ライブラリを勝手に拡張しないという暗黙の了解がありました。 しかし、Ruby on Rails はこの暗黙の了解をあえて大胆に破ることによって、非常に使いやすいライブラリを提供していたのです。 このことは、提供されたライブラリを開発者が自由に拡張して便利に使っているという点で、とても印象的な出来事でした。

Ruby on Rails を知ってからというもの、静的型付け言語、特に Java にも同様の拡張性が必要だと考えるようになりました。 Java ではサードパーティのライブラリやフレームワークが返すクラスに機能を追加することができないので、アプリケーション固有の共通機能は別のラッパークラスなどに集めます。 しかしせっかくラッパークラスを開発しても、型変換や呼び出しが面倒なのでなかなかアプリケーション開発者に使ってもらえません。 その結果、いつの間にか重複コードが増えて、メンテナンスやデバッグが困難になるという問題を抱えていたのです。

そんなときに出会ったのが Scala です。 Martin Odersky 氏によって開発された Scala は、オブジェクト指向に関数型プログラミングをブレンドした新しいプログラミング言語です。 Scala の特長はいろいろありますが、最も魅力的だったのはその拡張性の高さでした。 Scala では、暗黙の型変換を使うことによって、簡単にラッパークラスへの変換とメソッド呼び出しを行うことができます。 Ruby on Rails で見た実装のように、アプリケーション開発者がアプリケーション共通ライブラリを作り、まるで元からあったメソッドかのように、ラッパークラスにしか存在しないメソッドを呼び出すことができるのです。 Scala の拡張性の高さはこれだけにとどまりません。アクターの ! 演算子のようにまるで最初から組み込まれていたかのような演算子を定義することもできますし、クロージャを使って独自の for 文を定義したりすることもできます。 型安全性を保ちつつ、静的型付け言語とは思えない拡張性 を手に入れることができる言語 Scala。 どうです、ちょっと面白そうじゃあありませんか?

本書は、2009 年 9 月に米国 O’Reilly Media, Inc. から出版された『 Programming Scala 』の全訳です。 執筆者は Dean Wampler 氏と Alex Payne 氏の二人です。 Dean Wampler 氏は、sake という Ant に似た Scala 用のビルドツールの作者です。 Alex Payne 氏は、Twitter のバックエンドの一部分であるメッセージキューを Ruby から Scala へ移植したチームの一人です。 本書は、彼ら 2 人の Scala アプリケーション開発者としての経験や知識に基づいて書かれています。 本書は Scala を効率よく学び、実践的に利用するための入門書です。 著者の Scala に関する実践的な知識やノウハウがぎっしりと詰め込まれています。 コード例も非常に多く、数行で試せるものから、複数のファイルを使った大きなものまで大小さまざまなコードが含まれています。 コード例を実際に動作させながら読めば、効率よく Scala を学んでいけるでしょう。

入門書とはいっても、取り扱う範囲は入門書にありがちな簡単なサンプルばかりではありません。 Scala の基本的な文法のみならず、並行処理、内部 DSL と外部 DSL 、さらにはアプリケーション設計といった非常に高度な内容も扱っています。 そのため、 Scala 入門者だけではなく、すでに Scala を使っている人たちにも参考になることが多いはずです。

本書でわからないことがあったり、もう少し Scala について深く知りたいと思ったら、『 Scala スケーラブルプログラミング』(インプレスジャパン)を参照するとよいでしょう。 本書がアプリケーション開発者の視点による Scala の解説書であるのに対して、『 Scala スケーラブルプログラミング』は言語設計者による言語解説であるため、相互に補う内容になっています。

ここで、日本語版と原著英語版との違いについて説明しておきます。 原著の執筆時点では Scala 2.8 がリリースされていなかったため、 Scala 2.7 とベータ版の Scala2.8 で動作確認されていました。 日本語版では、すべてのサンプルコードを Scala 2.8.0 最終版で動作確認し、 Scala 2.7 と Scala 2.8 で動作が異なる部分については、必要に応じて訳注を付けました。 さらに、 Scala2.8 の新機能をまとめて 16 章「 Scala 2.8 の新機能と移行のポイント、日本語環境、サンプルコード」として追加しました。 15 章「 Simple Build Tool を使った Scala の開発」も日本語版オリジナルの章です。 15 章では、 Scala プロジェクト管理ツールのデファクトスタンダードである Simple Build Tool を使い、依存関係の解決、プロジェクトのビルド、デプロイ、テスト、再配布といった作業を行うためのプロジェクト環境構築について説明しています。 この章は、実用的な Scala プロジェクトを開始するための最後のピースを埋めてくれるでしょう。


最後に、本書の出版を支えてくれた皆さまに感謝いたします。 翻訳で忙しい中、いつも温かく見守り、励ましてくれた翻訳者の家族の皆さん。 いつも陰で支えてくれた上司や同僚の皆さん。 忙しい中、 査読を引き受けてくださった筑波大学の水島宏太さん。 水島さんのこまやかで、かつ鋭い指摘によって本書の品質は大きく向上しました。 また、遅々として翻訳が進まない中、辛抱強く励ましてくださった編集の宮川直樹さん。 このような翻訳の機会を与えてくださった、株式会社オライリー・ジャパンと株式会社オージス総研オブジェクトの広場編集部。 そして、このようなすばらしい本を執筆された Dean Wampler さん、Alex Payne さんに感謝いたします。

2010年初冬
オブジェクトの広場編集部
訳者を代表して 岡本和己

TOP ページのトップへ戻る

15 章 Simple Build Tool を使った Scala の開発

菅野 洋史●オブジェクトの広場編集部

新しいプログラミング言語を学ぶときに最も近道なのは、小さくても実用的なプログラムを実際に作ってみることです。 しかし実際にプログラムを作るとなると心理的な壁も大きいものです。 気軽にプログラムを作成し試すことができる環境があれば、そのような心理的な壁を小さくすることができます。

手軽にプログラムを作成したりテストできる環境として、Scala には対話型インタプリタがあります。 しかし対話型インタプリタだけでは外部ライブラリへの依存を管理したり単体テストを自動実行したりすることはできません。 これだけでは実用的なプログラムを作成するのは困難でしょう。 日本語版オリジナルの15章では、手軽なだけではなく実用的に使えるプロジェクト環境を Simple Build Tool を使って構築し、その上で Scala ベースの簡単なツールを作成します。

15.1 Simple Build Tool

ある程度の実用的なプログラムを開発するためには、依存するライブラリの管理、ビルドやテストの実行、実行用アーカイブの作成等を自動的に行う環境が必要です。 つまり、このようなプロジェクト環境を作成するためのツールを導入する必要があります。

本章では Simple Build Tool(以降 Sbt と略す)というツールを利用します。 Sbt は Scala で作られた Scala 用のプロジェクトビルド環境構築ツールです。 Java における Maven 類似のツールですが、プロジェクトの設定を Scala による DSL で記述する点が大きな特徴です。 Java プロジェクトや Java-Scala 混在プロジェクトに利用することもできます。

Sbt を利用することにより、 Scala の実行環境自体を含む依存ライブラリの管理、テストの実行支援、組み込みWebサーバなどを備えたプロジェクトビルド環境を構築することができます。 またプラグインを利用することにより、 Sbt の機能を拡張することができます。 たとえば Sbt で作られたプロジェクト環境を Eclipse や Idea プロジェクトとしてインポートさせることができます。 これにより開発者はプロジェクト環境では Sbt を使い、コーディング環境としてそれぞれ好みのIDEを使うこともできます。

さらに Sbt は対話型シェルを備えており、コンパイル、テストを対話的に行うことが可能です。 Sbt の対話型シェルからは、プロジェクトで利用している各クラスパスが設定された状態でコマンドラインインタプリタを起動することもできます。 このコマンドラインインタプリンタを利用することで、プロジェクトで作成しているクラスを対話的に生成してメソッドを呼び出すことができます。

またプロジェクト環境を配布用のアーカイブにまとめるコマンドも用意されています。これによりプロジェクト環境自体を簡単に配布できます。

15.1.1 プロジェクト環境の構築

まずhttps://code.google.com/p/simple-build-tool/から、Sbt のランチャー sbt-launch-0.7.4.jar をダウンロードします。 このランチャーは Sbt の起動プログラムであると同時に、 Sbt 自体のインストーラ、プロジェクト環境の生成ツール、対話型シェル環境などを兼ねています。

最初に Sbt ランチャーを起動すると、プロジェクトビルド環境のランタイムを配置するためのディレクトリを作成します。 Sbt ランチャーは、 Sbt の本体や Scala ランタイム、 Scala コンパイラ、ライブラリをそれぞれのサイトから取得し、そのディレクトリの中にインストールします。 最初の Sbt ランチャーを動作させるために必要なものは、ランチャーを動かすための Java の開発環境のみです。 あらかじめ Scala をインストールする必要はありません。 プロジェクトごとに Scala の実行環境を持つので、それぞれ利用する Scala のバージョンを変えることもできます。

15.1.1.1 プロジェクトディレクトリの作成

それでは実際に単純なプロジェクト環境の作成を試して見ましょう。 最初にプロジェクト環境となるディレクトリ hello を作成します。

$ mkdir hello

次に先ほどダウンロードしたランチャー sbt-launch-0.7.4.jar をこの hello ディレクトリに配置します

ランチャーを起動するためのバッチプログラムもしくはシェルスクリプト( sbt.bat もしくは sbt )を hello ディレクトリ直下に作成します。 Windows では、次のような起動スクリプト sbt.bat を作成します。

@rem sbt.bat
@setlocal
@java -jar sbt-launch-0.7.4.jar %*

@rem proxy環境では以下のような引数をつける。
@rem -Dhttp.proxyHost=proxy.example.com -Dhttp.proxyPort=8080

Mac OSX や Linux では次のような起動スクリプト sbt を作成します。

#! /bin/sh

java -Xmx512M -jar `dirname $0`/sbt-launch-0.7.4.jar "$@"

# proxy環境では以下のような引数をつける。
# -Dhttp.proxyHost=proxy.example.com -Dhttp.proxyPort=8080
15.1.1.2 プロジェクトの作成

それでは起動用スクリプトを実行します。

$ sbt
Project does not exist, create new project? (y/N/s)

この章では、シェルのプロンプトは$で表し、sbtの対話環境のプロンプトを>で表します。

ここでyを入力すると、プロジェクト名、組織名、プログラムのバージョン、Scalaのバージョン、Sbt本体のバージョンを聞かれますので、入力します。

Project does not exist, create new project? (y/N/s) y
Name: hello
Organization: scalabook
Version [1.0]: 0.1
Scala version [2.7.7]: 2.8.0
sbt version [0.7.4]: 0.7.4

各種ライブラリのダウンロードが始まります。 Scala 本体や Sbt の本体もこのタイミングでダウンロードします。

Getting Scala 2.7.7 ...
downloading https://repo1.maven.org/maven2/org/scala-lang/scala-compiler/2.7.7/scala-compiler-2.7.7.jar ...
[SUCCESSFUL ] org.scala-lang#scala-compiler;2.7.7!scala-compiler.jar (19368ms)
downloading https://repo1.maven.org/maven2/org/scala-lang/scala-library/2.7.7/scala-library-2.7.7.jar ...
[SUCCESSFUL ] org.scala-lang#scala-library;2.7.7!scala-library.jar (9864ms)
(以下略)

Scala 本体と Sbt のライブラリは、個々のプロジェクト用ディレクトリにそれぞれ保存されます。 Sbt ランチャーの実行により次のようなディレクトリ階層が作成されます。

hello
├─lib
├─project
│  └─boot
│      ├─scala-2.7.7
│      │  ├─lib
│      │  └─org.scala-tools.sbt
│      │      └─sbt
│      │          └─0.7.4
│      │              ├─compiler-interface-bin_2.7.7.final
│      │              ├─compiler-interface-bin_2.8.0.RC2
│      │              ├─compiler-interface-src
│      │              └─xsbti
│      └─scala-2.8.0
│          └─lib
├─src
│  ├─main
│  │  ├─resources
│  │  └─scala
│  └─test
│      ├─resources
│      └─scala
└─target

project ディレクトリはプロジェクト環境自体に関係する各種ファイルを配置するディレクトリです。 その中でも、 project/boot は Sbt を動作させるためのランタイムを配置するためのディレクトリです。 Scala 実行環境や Sbt のライブラリや設定ファイルを配置します。 この例では Sbt 自体を動作させるための Scala ランタイム(2.7.7)とプロジェクトビルド用の Scala ランタイム(2.8.0)もそれぞれインストールされているのがわかります。

トップレベルにある lib は Sbt の管理外にあるライブラリの配置場所です。 後述しますが Sbt で管理されるライブラリは lib_managed というディレクトリが作成され、そこに配置されます。 src 以下にプロジェクトのソースを配置します。 src/main/scala にソースコード、 src/test にテストコードを配置します。 ビルド結果等は target に配置されます。

これでプロジェクト環境が構築できました。 ここで Sbt を終了します。 終了する場合には、 exit か quit と入力します。

> exit
[info]
[info] Total session time: 2 s, completed 2010/08/14 16:07:52
[success] Build completed successfully.
15.1.2 対話型シェル

引数をつけずにsbtを起動すると対話型シェルに入ります。

$ sbt
[info] Building project hello 0.1 against Scala 2.8.0
[info]    using sbt.DefaultProject with sbt 0.7.4 and Scala 2.7.7

対話型シェルでできることは help や actions コマンドを打ち込んで確認できます。

help によって、この対話型シェルに入力できるコマンドなどが説明されます。 たとえば ~ という記号をコマンド名の前に入れることによって、ソースファイルが変更したタイミングでコマンドを実行したり、<でファイルを読み込んで、そこに記述してあるコマンド列を実行することが出来ます。

> help
You may execute any project action or one of the commands described below. Only one action may be executed at a time in interactive mode and is entered by name as it would be at the command line. Also, tab completion is available.
Available Commands: 
   <action name> : Executes the project specified action.
   <method name> <parameter>* : Executes the project specified method.
   <processor label> <arguments> : Runs the specified processor.
   ~ <command> : Executes the project specified action or method whenever source files change.
   < file : Executes the commands in the given file.  Each command should be on its own line.  Empty lines and lines beginning with '#' are ignored
   + <command> : Executes the project specified action or method for all versions of Scala defined in crossScalaVersions.
   ++<version> <command> : Changes the version of Scala building the project and executes the provided command.  <command> is optional.

最も利用頻度が高いコマンドはアクションを指定して実行する<action name>でしょう。 コンパイルなどのビルド用の操作はアクションとして定義されています。 actions と入力することにより、実行可能なアクションがすべて表示されます。

> actions
        -empty
        clean: Deletes all generated files (the target directory).
        clean-cache: Deletes the cache of artifacts downloaded for automatically managed dependencies.
        clean-lib: Deletes the managed library directory.
        clean-plugins
        compile: Compiles main sources.
        console: Starts the Scala interpreter with the project classes on the classpath.
        console-quick: Starts the Scala interpreter with the project classes on the classpath without running compile first.
        copy-resources: Copies resources to the target directory where they can be included on classpaths.
        copy-test-resources: Copies test resources to the target directory where they can be included on the test classpath.
        deliver
        deliver-local
        doc: Generates API documentation for main Scala source files using scaladoc.

前述したように、対話型シェルを終了する場合は、exit か quit と入力します。

Sbt におけるほとんどの作業はこの Sbt の対話型シェルを起動したまま行うことになります。 常に Sbt のプロセスが上がった状態なので( JVM の立ち上がりを待つ必要がないので)コンパイルの速度などが高速化されます。

15.1.2.1 コンパイルと実行の確認

最初に簡単なプログラムを作成しましょう。

// code-examples/SimpleBuildTool/hello/src/main/Hello.scala
/** 最初のサンプル */
object Hello {
  def main(args:Array[String]):Unit = println("こんにちは!! Scala")
}

hello/src/main/scala ディレクトリに Hello.scala というファイルとして保存します。 ファイルのエンコーディングは UTF-8 にして下さい。

Sbt の起動スクリプトを実行し、対話型コンソールを開きます。

$ sbt
[info] Building project hello 0.1 against Scala 2.8.0
[info]    using sbt.DefaultProject with sbt 0.7.4 and Scala 2.7.7

コンパイルを実行します。

> compile
[info]
[info] == compile ==
[info]   Source analysis: 1 new/modified, 0 indirectly invalidated, 0 removed.
[info] Compiling main sources...
[info] Compilation successful.
[info]   Post-analysis: 2 classes.
[info] == compile ==
[success] Successful.
[info]
[info] Total time: 10 s, completed 2010/08/14 16:23:18

run アクションで先ほど作成したクラスを実行します。 Sbt は、 Java もしくは Scala ソースの中で main メソッドがあるクラスを自動的に見つけて実行します。

> run
[info]
[info] == copy-resources ==
[info] == copy-resources ==
[info]
[info] == compile ==
[info]   Source analysis: 1 new/modified, 0 indirectly invalidated, 0 removed.
[info] Compiling main sources...
[info] Compilation successful.
[info]   Post-analysis: 2 classes.
[info] == compile ==
[info]
[info] == run ==
[info] Running Hello
こんにちは!! Scala
[info] == run ==
[success] Successful.
[info]
[info] Total time: 4 s, completed 2010/08/14 16:23:32

main メソッドがあるクラスが複数存在した場合は、run 実行時にどのクラスを実行するかメニューが表示されます。 そこで実行するクラスを選択します。

15.1.2.2 単体テスト実行環境

Sbt には単体テスト実行をサポートする機能があります。 今回は ScalaTest ライブラリを利用して単体テスト環境を整えます。 そのために、依存ライブラリの設定とダウンロードを行う必要があります。

まず、hello/project/build ディレクトリを作成します。 このディレクトリは、Sbt がビルド作業を行うための各種設定ファイルなどを配置するためのディレクトリです。 この設定ファイルのフォーマットは Scala の内部 DSL として実現されています。 つまり設定内容を Scala のソースコードの形式で記述します。 このディレクトリに配置した設定ファイルはプログラムのソースコードと同様に Sbt によってコンパイルされ、その後、設定として読み込まれる仕組みになっています。 したがって設定ファイルの記述時に形式的なミスがあった場合はコンパイルエラーとして確認、修正することができます。

それではプロジェクト定義として、ScalaTest ライブラリへの依存関係を記述します。 hello/project/build ディレクトリに HelloProject.scala ファイルを作成します。 ダウンロード先リポジトリや依存ライブラリの設定は次のような DSL で記述します。

import sbt._ 
class HelloProject(info: ProjectInfo) extends DefaultProject(info) {
  val repoScala = "Snapshot Repository " at
                   "https://www.scala-tools.org/repo-snapshots/"
  val scalaTest = "org.scalatest" % "scalatest" % 
                   "1.2-for-scala-2.8.0.final-SNAPSHOT" % "test"
}

sbt.DefaultProject を継承したクラスを定義すると、そのクラスのフィールドがプロジェクトの設定として読み込まれます。 この定義でリポジトリの定義や依存ライブラリの定義を行うことができます。 またメソッドを追加することによりSbtから呼び出せるアクションを定義することもできます。 この HelloProject クラスではリポジトリ定義と依存ライブラリの定義を行っています。

依存ライブラリのダウンロード元になるリポジトリは、sbt.DefaultProject クラスのサブクラスである、HelloProject に sbt.MavenRepository 型の任意の名前のフィールドを宣言することによって定義できます。

val repoScala : sbt.MavenRepository = ...

実は String クラスに対し暗黙の型変換が定義されており、文字列に対して at メソッドを呼び出すことによって sbt.MavenRepository 型のオブジェクトを生成することができます。 暗黙の型変換と型推論によりリポジトリは次のように定義できます。

val フィールド名 = リポジトリ名 at リポジトリのURL

したがって val repoScala のリポジトリの定義は次の形になります

val repoScala = "Snapshot Repository " at 
                              "https://www.scala-tools.org/repo-snapshots/"

依存ライブラリ(アーティファクト)も、sbt.GroupArtifactID 型のフィールドによって定義できます。

val scalaTest: sbt.GroupArtifactID = ...

リポジトリ指定の時と同様に String クラスに対する暗黙の型変換が定義されており、% メソッドの呼び出しによって sbt.GroupArtifactID 型のオブジェクトを生成できます。 さらに % メソッドをチェーンしていくことによって、このオブジェクトへの値(アーティファクト名やバージョン情報など)の設定を行っていくことができます。 暗黙の型変換と型推論により依存ライブラリは次のように定義できます。

val フィールド名 = 組織名 % アーティファクト名 % バージョン % コンフィギュレーション

組織名、アーティファクト名、バージョンで依存ライブラリを決定し、コンフィギュレーションでどのタイミングでライブラリが利用される指定しています。 実は、この内容は Ivy という依存性管理ツールの設定ファイルと同等のものです。 Sbt の内部では、依存ライブラリの解決のために Ivy を利用しています。 コンフィギュレーションその他の用語も Ivy で利用されているものです。 Ivy についてはhttps://ant.apache.org/ivy/を参照して下さい。

結果 scalaTest への依存の定義は次の形になります。

val scalaTest = "org.scalatest" % "scalatest" % 
                                 "1.2-for-scala-2.8.0.final-SNAPSHOT" % "test"

Sbt にこれらの定義を反映させるには、シェルを再起動するか、reload アクションを実行します。 ここでは reload アクションを実行してみましょう。

> reload
[info] Recompiling project definition...
[info]    Source analysis: 1 new/modified, 0 indirectly invalidated, 0 removed.
[info] Building project hello 0.1 against Scala 2.8.0
[info]    using HelloProject with sbt 0.7.4 and Scala 2.7.7

reload によってプロジェクトの設定がコンパイルされ、新しい設定が取り込まれます。

次に実際に ScalaTest を取得します。ライブラリの取得には update アクションを実行します。

> update
[info]
[info] == update ==
[info] downloading https://www.scala-tools.org/repo-snapshots/org/scalatest/scala
test/1.2-for-scala-2.8.0.final-SNAPSHOT/scalatest-1.2-for-scala-2.8.0.final-SNAPSHOT.jar ...
[info]  [SUCCESSFUL ] org.scalatest#scalatest;1.2-for-scala-2.8.0.final-SNAPSHOT!scalatest.jar (5718ms)
[info] :: retrieving :: scalabook#hello_2.8.0 [sync]
[info]  confs: [compile, runtime, test, provided, system, optional, sources, javadoc]
[info]  1 artifacts copied, 0 already retrieved (1742kB/70ms)
[info] == update ==
[success] Successful.
[info]
[info] Total time: 8 s, completed 2010/08/14 18:17:26

検証のためにテスト対象となるコードとして、hello/src/main/scala/Adder.scala を追加します。 引数を足し合わせるオブジェクト Adder を定義します。

// code-examples/SimpleBuildTool/hello/src/main/scala/Adder.scala
object Adder {
  def add(a:Int)(b:Int):Int =  a + b 
}

テストコード AdderSuite.scala を hello/src/test/scala に作成します。

 // code-examples/SimpleBuildTool/hello/src/test/scala/AdderSuite.scala
import org.scalatest.FunSuite
class AdderSuite extends FunSuite {
  test("""Adderのテスト""") {
    assert(4 === Adder.add(1,3))
  }
}

Sbt の対話型のシェルで test と打ち込むことでコンパイル&テストを実行することができます。

 > test
[info]
[info] == compile ==
[info]  //中略.....
[info]
[info] == AdderSuite ==
[info] Test Starting: Adderのテスト
[info] Test Passed: Adderのテスト
[info] == AdderSuite ==
[info]
[info] == test-complete ==
[info] == test-complete ==
[info]
[info] == test-finish ==
[info] Passed: : Total 1, Failed 0, Errors 0, Passed 1, Skipped 0
[info]
[info] All tests PASSED.
[info] == test-finish ==
[info]
[info] == test-cleanup ==
[info] == test-cleanup ==
[info]
[info] == test ==
[info] == test ==
[success] Successful.
[info]
[info] Total time: 10 s, completed 2010/08/14 18:28:52

今回は単純な単体テストでしたが、必要があれば org.scalatest.Spec などを利用し、BDD における Specification を記述、実行することもできます。

15.1.2.3 バイナリ配布物の構築

実行形式のプログラムとして配布するためには、Sbt なしでも実行できるようにパッケージングする必要があります。 まずは Sbt を使って class ファイルを jar に固めます。

> package
[info]
[info] == compile ==
[info]   Source analysis: 0 new/modified, 0 indirectly invalidated, 0 removed.
[info] Compiling main sources...
[info] Nothing to compile.
[info]   Post-analysis: 16 classes.
[info] == compile ==
[info]
[info] == package ==
[info] == package ==
[success] Successful.

この jar ファイルを動作させるためには Scala ランタイムなど依存するライブラリも必要です。 現在の Sbt でコマンドラインのプログラムを作成する場合、本体 jar のパッケージングはできますが、マニフェストに対する依存ライブラリへのクラスパス設定などは自動化されていません。 したがって、今回は手動で依存ライブラリなどをパッケージにまとめます

まずプロジェクト直下に適当なディレクトリ( tool ディレクトリ)を作成し、先ほどのパッケージタスクによって作成された jar ファイルをコピーしましょう。

$ mkdir tool
$ copy target\scala_2.8.0\*.jar tool

次に関係する jar ファイルを lib_managed\scala_2.8.0\test\ のディレクトリから集めてきましょう。 コンパイル時に必要だった jar ファイルを全て取得して先ほど作成したディレクトリにコピーします。

$ copy lib_managed\scala_2.8.0\test\*.jar tool

Scala 自体のランタイムもコピーします

$ copy project\boot\scala-2.8.0\lib\scala-library.jar tool

これでパッケージング作業が完了しました。 toolディレクトリに移動して次のコマンドを実施します。

$ java -classpath ".\*" Hello
$ こんにちは!! Scala
15.1.2.4 ソースコード配布物の構築

作成したプロジェクトビルド環境自体を配布するためのアーカイブを作成することもできます。 このアーカイブを展開した後に、sbt を起動し、update アクションによってライブラリをダウンロードすれば、誰でも成果物のビルドやテストを行うことができます。

sbt のシェルから、package-project というアクションを実行します。

> package-project
[info]
[info] == package-project ==
[info] Packaging .\target\scala_2.8.0\hello_2.8.0-0.1-project.zip ...
[info] Packaging complete.
[info] == package-project ==
[success] Successful.
[info]
[info] Total time: 2 s, completed 2010/08/15 15:57:07

hello_2.8.0-0.1-project.zip というファイルが生成されます。 この ZIP ファイルにはランタイム用 Scala 環境や依存ライブラリ、target 以下に生成された成果物などを取り除いたプロジェクトビルド環境がアーカイブされています。

このファイルを展開し update すれば、全く同じプロジェクトビルド環境を誰でも再現することができます。


:Scalaがインストールされていない状態で起動させるために、ランチャーの jar には Scala 実行環境のサブセットが同封されています。 クラスパスの衝突を防ぐため、この jar ファイルを $SCALA_HOME/lib を含む既存の Java 実行環境のクラスパス上に置かないでください。 プロジェクトのディレクトリ毎に配置すると分かりやすいでしょう。

:Web アプリケーション用の Project としてセットアップした場合は、package アクションによって依存するクラスを WEB-INF/lib などに集めてくれます。

TOP ページのトップへ戻る

プログラミング Scala 読者プレゼント

今回特別に『プログラミングScala』を抽選で 1 名の方に読者プレゼントいたします。

ご希望の方は、以下の内容を明記の上、メールの Subject に「プログラミング Scala プレゼント係」と書いて OOSQUARE-EDITOR@ogis-ri.co.jp 宛にお送りください。

  1. お名前
  2. 郵便番号
  3. ご住所
  4. 電話番号
  5. 「オブジェクトの広場」で取り上げてほしい情報・記事
  6. 「オブジェクトの広場」の感想/本記事の感想
  7. Scalaへの熱い思い

締め切りは、2011年 1 月 31 日(月)です。当選者の発表はご本人宛にメールにてお知らせいたします。

【個人情報の取り扱いについて】 ご応募で頂いた個人情報につきましては、本件「プログラミング Scala 」プレゼントのご連絡のみに使用いたします。 お客様の個人情報は、当社の個人情報保護方針に基づき、適切にお取り扱いいたします。 また、ご本人の承諾なしに、第三者機関へ提供することはありません。

プレゼントの応募は締め切らせていただきました。 ご応募ありがとうございました。 抽選の結果、当選された方には 2/15 までに案内メールをお送りいたします。 (2011/02/09)

© 2011 OGIS-RI Co., Ltd.
HOME HOME TOP オブジェクトの広場 TOP