sbtの基礎力をつけるために調べたことメモ

# 始めに

※sbt0.13.x を使っています。

```lang:build.sbt
name := "myProject"

version := "1.0"

scalaVersion := "2.11.7" 

libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3"
```
この基本形以上はよく分からないまま使っているんだけど、
もっとSBT使えるようになりたいので、そのために調べてみたことを書いてみる。

# この書き方は何？

```scala:build.sbt
lazy val root = (project in file("."))
  .settings(
    name := "MyProject",
    version := "1.0",
    scalaVersion := "2.11.7",
    libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3"
  )
```
最初の基本形と同じことを違う書き方になっただけで同じ意味。
最初の書き方は設定ファイル風味だけど、こちらはscalaプログラムなので調べやすそう。

※もっとscala的な書き方をする方法があるけと旧式のやりかたらしい
http://www.scala-sbt.org/0.13/docs/ja/Full-Def.html

# さっそく意味わからん

## project in file(".") とは？

[Projectクラスのドキュメント](http://www.scala-sbt.org/0.13/api/index.html#sbt.Project)

> def in(dir: File): Project
> Sets the base directory for this project.

``project in file(".")``でbuild.sbtがある場所をプロジェクトの起点フォルダとして設定しているように読めたけど、それで合ってた。

ちなみに``file(".")``は``new File(".")``と同じ。
sbt packageオブジェクトで定義されてる`` def file(s: String): File = new File(s)``があるので、このメソッドが使われている。
https://github.com/sbt/sbt/blob/3e5449f02d082c1326da7e6319d70d5b26b84bfd/sbt/src/main/scala/package.scala

## settingsとは？

> def settings(ss: Def.Setting[_]*): Project
> Appends settings to the current settings sequence for this project.

プロジェクトに必要な設定を追加・更新している。これは見たまま。

## settingsで使っているname, versionってどこから来ているのか？

http://www.scala-sbt.org/0.13/sxr/sbt/Keys.scala.html

```Keys.scala.htmlの抜粋
val name = SettingKey[String]("name", "Project name.", APlusSetting)
val version = SettingKey[String]("version", "The version/revision of the current module.", APlusSetting)
val scalaVersion = SettingKey[String]("scala-version", "The version of Scala used for building.", APlusSetting)
val libraryDependencies = SettingKey[Seq[ModuleID]]("library-dependencies", "Declares managed dependencies.", APlusSetting)
```

sbt.Keysクラスに定義されたval変数がsettingsの中に書くキーの一覧らしい。
nameは``SettingKey[String]``なので、``name := "myProject"``はSettingKeyクラスのインスタンスに対して``:=``メソッドを実行しているということになる。

## name := "myProject" は何してるの？

http://www.scala-sbt.org/0.13/api/index.html#sbt.SettingKey
> final def :=(v: T): Def.Setting[T]

Def.Setting[T] を返却してる。それでそれがどういう意味を持つんだ？
http://www.scala-sbt.org/0.13/docs/ja/Basic-Def.html を読むと、
> name キーの := メソッドは Setting を返すが、特に Setting[String] を返す。 String は name 自体の型にも表れていて、そちらは SettingKey[String] となる。 ここで返された Setting[String] は、sbt の Map における name というキーを追加または置換して "hello" という値に設定する変換である。

sbtがMapを持ってると考えると理解が進んだ気がする。settingsでそのMapを更新してるのは想像しやすい。

## キーの種類

http://www.scala-sbt.org/0.13/docs/ja/Basic-Def.html#%E3%82%AD%E3%83%BC

> SettingKey[T]: 一度だけ値が計算されるキー（値はプロジェクトの読み込み時に計算され、保存される）。
> TaskKey[T]: 毎回再計算されるタスクを呼び出す、副作用を伴う可能性のある値のキー。
> InputKey[T]: コマンドラインの引数を入力として受け取るタスクのキー。 　「始める sbt」では InputKey を説明しないので、このガイドを終えた後で、Input Tasks を読んでみよう。

|クラス名|キーの具体例|何のために使うか？|
|:------------|:-----------------|:------------------------------------|
| SetteingKey | name, version    | 設定値(固定値）を定義 |
| TaskKey     | compile, package | 処理の実行 |
| InputKey    | run, runMain     | 引数付きの処理の実行？（まだよくわからん） |

# TaskKeyを作って実行してみる

```scala:build.sbt
lazy val hello = taskKey[Unit]("task sample") // 追加

lazy val root = (project in file("."))
  .settings(
	name := "MyProject",
	version := "1.0",
	scalaVersion := "2.11.7",
  	libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3",
  	hello := { println("hello sbt!") }　// 追加
  )
```

```bash:consoleでの実行結果
$ sbt
[info] Loading project definition from C:\Users\xxxx\workspace\sbtStudy\project
[info] Set current project to MyProject (in build file:/C:/Users/xxxx/workspace/sbtStudy/)
> hello
hello sbt!
[success] Total time: 0 s, completed 2016/01/24 4:23:56
```

これもチュートリアル通りに沿ってhelloというキー名でTaskKeyを作り、settingsでhelloの動作を追加したあとに実行してみた。


とりあえず1回目はここまで。