sbt 1.0.0 

互換性に影響のある新機能、バグ修正、その他の変更点 

移植に関しては Migrating from sbt 0.13.x も参照。

  • sbt 1.0 は、ビルド定義とプラグインに Scala 2.12 を使う。そのため、JDK 8 以上を必要とする。
  • case class の多くは Contraband を用いて生成された疑似 case class に置き換えられた。.copy(foo = xxx)withFoo(xxx) に書き換える必要がある。例えば、UpdateConfigurationRetrieveConfigurationPublishConfiguration などはビルダーパターンを使うようにリファクタリングした。
  • Zinc 1 は、Scala 2.9 及びそれ以前のバージョンのサポートを打ち切る。Scala 2.10 は 2.10.2 以降、Scala 2.11 は 2.11.2 以降を使う必要がある。(最新のパッチ版を使うことを推奨する)
  • config("xyz") は、val Xyz = config("xyz") のように 頭文字が大文字val に直接代入する必要がある。これは左辺項の識別子を捕捉して後でシェルから使えるようにするためだ。
  • publishTootherResolvers は SettingKey から TaskKey へと変更した。#2059/#2662 by @dwijnand
  • Path.relativizeFile(baseFile, file)IO.relativizeFile(baseFile, file) へと名前が変わった。
  • PathFinder.*** メソッドは .allPaths メソッドへと名前が変わった。
  • PathFinder.x_!(mapper)PathFinderdef pair に変更された。
  • sbt.Path の多くのメソッド (relativeTorebaseflat など) は以前は sbt のパッケージオブジェクト経由でデフォルトの名前空間に入っていたが、それが無くなったので sbt.io.Path を使ってアクセスしてほしい。
  • sbt 1.0 は、スコープ成分としての GlobalZero と名前を変えて、GlobalScope と区別するようにした。 @eed3si9n
  • 今まで update.value.configuration(...) のような所でコンフィギュレーションを参照するのに文字列が使われていたのを、ConfigRef を使うように変更した。
  • sourceArtifactTypesdocArtifactTypesSet[String] から Seq[String] セッティングへと変更した。
  • early command 機能を --<command> という構文から early(<command>) へと変更した。
  • sbt 0.12 スタイルのハイフン区切りされたキー名を撤廃した (例えば publish-local から publishLocal に移行する)。
  • ログのオプションとして、"early(error)" などの代わりに -error-warn-info-debug オプションを追加した。
  • sbt.Processsbt.ProcessExtra は撤廃した。scala.sys.process に移行する。
  • name hashing が常に有効となったため、incOptions.value.withNameHashing(...) はオプションは無くなる。
  • TestResult.ValueTestResult に名前を変更する。
  • Scripted プラグインはクロスバージョンされるため、使う場合は %% を使う必要がある。

以前より廃止勧告が出ていて、今回撤廃されたもの:

  • sbt 0.12 スタイルの Build trait は sbt 0.13.12 に廃止勧告となり、この度削除した。build.sbt へと移行する必要がある。Auto plugin と Build trait は相性が悪く、またこの機能は既に普及しているマルチプロジェクト build.sbt によって置き換えられた。
  • sbt 0.12 スタイルの Project(...) コンストラクタは、2つのパラメータを受け取るものだけに制限する。これは、settings パラメータは Auto plugin と相性が悪いからだ。代わりに、project を使ってほしい。
  • sbt 0.12 スタイルのキー依存演算子 <<=, <+=, <++= は撤廃した。:=、 +=、および ++= 演算子へと移行してほしい。古い演算子は多くのユーザにとって混乱の元となっており、長らく 0.13 のドキュメンテーションからは削除され、sbt 0.13.13 以降正式に撤廃勧告が出ていた。
  • Auto plugin ではない sbt.Plugin を撤廃した。AutoPlugin へと移行してほしい。Auto plugin の方が設定が簡単で、プラグイン間の協調が可能だからだ。
  • Project より settingsSet メソッドおよび add/setSbtFiles を削除する。
  • 廃止勧告が出ていた InputTask apply メソッドと inputTask DSL メソッドを撤廃する。Def.inputTaskDef.spaceDelimited().parsed へと移行してほしい。
  • 廃止勧告が出ていた ProjectReference への暗黙の変換を撤廃する。RootProject(<uri>)RootProject(<file>)、もしくは LocalProject(<string>) へと移行してほしい。
  • 廃止勧告が出ていた seq(...) DSL メソッドを撤廃する。Seq(...) を使うか、そのまま setting を渡すようにしてほしい。
  • 廃止勧告が出ていた File/Seq[File] セッティングの暗黙の変換を撤廃する。.valueDef.setting へと移行してほしい。
  • 廃止勧告が出ていた SubProcessapply オーバーロードを撤廃する。SubProcess(ForkOptions(runJVMOptions = ..)) へと移行する。
  • toError(opt: Option[String]): Unit を廃止する (opt foreach sys.error と同様)。ScalaRun#run と併用する場合、scalaRun.run(...).failed foreach (sys error _.getMessage) というように書き換える。

新機能 

  • 新しいインクリメンタル・コンパイラ Zinc 1。 (詳細は以下の項目)
  • インタラクティブ・シェルにネットワーク API が追加された。(詳細は以下の項目)
  • Library management API とアーティファクトの並列ダウンロード。(詳細は以下の項目)
  • イベント・ロギング。(詳細は以下の項目)
  • Scala Center がコントリビュートした build.sbt の静的バリデーション。(詳細は以下の項目)
  • sbt-cross-building のプラグインのクロスビルド用の ^^^ コマンドの移植。on projects that adopts Scalafmt

改善点 

  • Scala Center は、Java フレンドリーな Zinc API をコントリビュートした。これは、他のビルドツールからも Scala を取り扱えるように Zinc の API を改善したものだ。 zinc#304 by @jvican
  • Scala Center は、Zinc 内部の保存用のバイナリフォーマットをコントリビュートした。on projects that adopts Scalafmt
  • scalas を使ったときの、スタートアップのログレベルを -error まで落とした。 #840 by @eed3si9n
  • クロスビルドのサポートを sbt-doge に置き換えた。これによって、複数のプロジェクトを異なる Scala バージョンの組み合わせでクロスビルドする必要があるビルドを正しく扱うことができるようになった。++ の振る舞いが変更され、Scala バージョンのサポートを予め列挙するサブプロジェクトのみが変更されるようになった。しかし、! を追加することで全てのプロジェクトを変更することもできる。どのプロジェクトが変更されたのかの詳細な情報を表示するための、-v オプションも追加された。#2613 by @jroper
  • CI 環境が検知された場合は、ivyLoggingLevelUpdateLogging.Quiet に落とすようにした。 @eed3si9n
  • build.sbt (*.sbt) ファイル名をログに表示するようにした。 #1911 by @valydia
  • 現在のプロジェクトに対して、build.sbt ファイルから aggregate を呼べるようにした。 By [@xuwei-k][@xuwei-k]
  • inspect tree などで表示される ASCII グラフの最大幅を決める asciiGraphWidth という新しいグローバルセッティングを追加した。デフォルトでは、40文字。By @RomanIakovlev.
  • スコープのドキュメンテーションを刷新して、スコープ委譲のページを追加した。 @eed3si9n
  • クロスバージョンを使ったライブラリの排除ができるようになった。 #1518/lm#88 by @jvican
  • Ivy ベースのライブラリ管理に新しいオフラインモードを追加した。 lm#92 by @jvican
  • 依存性ロッキングに関連するいくつかの機能が追加された。(詳細は以下の項目)
  • Eviction 警告の表示の改善。(詳細は以下の項目)
  • main class 検知の改善。 zinc#287 by @smarter
  • より速いスタートアップのために、autoImport の検知に Java リフレクションを使うようにした。 #3115 by @jvican
  • より速いスタートアップのために、パーシングに同じコンパイラ Global のインスタンスを再利用するようにした。 #3115 by @jvican
  • sbt 0.13 との互換性維持のために、sbt-core-next から InteractionService を追加した。 #3182 by @eed3si9n
  • PollingWatchService と Java NIO を抽象化する新しい WatchService を追加した。 io#47 by @Duhemm on behalf of The Scala Center.
  • IO.copyFileIO.copyDirectorysbt.io.CopyOptions() を受け取るバリエーションを追加した。(詳細は以下の項目)
  • Path.directoryPath.contentOf を sbt-native-packager から寄付してもらった。 io#38 by @muuki88
  • Zinc のデバッグに使われる ApiDiff 機能を Dotty の Scala 実装のものから借りてきた。 zinc#346 by @Krever
  • Zinc 内部で ExtractAPI が perRunCaches を使うようにした。 zinc#347 by @gheine

内部 

  • ソースコードのフォーマットに Scalafmt を採用して、neo-sbt-scalafmt を用いる。
  • Scala Center が Scripted test フレームワークがバッチ・モード実行できる再設計をコントリビュートした。これによって Scripted は同じ sbt インスタンスを再利用して sbt テストを実行でき、CI ビルド時間を 50% ダウンさせた。 #3151 by @jvican
  • sbt 1.0.0 は sbt 1.0.0-RC3 を用いてビルドされた。 #3184 by @dwijnand

大きな変更の詳細点 

Zinc 1: クラスベースの name hashing 

(Lightbend の委託で) Grzegorz Kossakowski が Zinc 1 にもたらした大きな改善として、クラスベースの name hashing がある。これは、大規模な Scala プロジェクトにおいて差分コンパイルが高速化することが見込まれる。

Zinc 1 の name hashing は、コード間の依存性をファイルではなく、クラスのレベルで追跡する。GitHub issue sbt/sbt#1104 に有名なプロジェクトの既存のクラスにメソッドを追加した場合の比較データがある:

ScalaTest   AndHaveWord class:          Before 49s, After 4s (12x)
Specs2      OptionResultMatcher class:  Before 48s, After 1s (48x)
scala/scala Platform class:             Before 59s, After 15s (3.9x)
scala/scala MatchCodeGen class:         Before 48s, After 17s (2.8x)

これは、クラスがどのようにまとめられているかといった様々な要素に依存するが、3x ~ 40x の向上が見られるのが分かる。高速化の理由は、クラスをソースファイルという「くくり」から分けたことで少ない数のソースファイルをコンパイルしているからだ。scala/scala の Platform クラスにメソッドを追加した例だと、sbt 0.13 の name hashing は 72 のソースをコンパイルしていたのに対し、新しい Zinc は 6 のソースをコンパイルしている。

Zinc API の変更 

  • xsbti.compile パッケージ以下の IncOptions などの Java クラスはコンストラクタを隠蔽する。ファクトリーメソッドである xsbti.compile.Foo.of(...) に移行する。
  • ivyScala: IvyScala キーは scalaModuleInfo: ScalaModuleInfo に名前が変わる。
  • xsbti.Reporter#log(...)xsbti.Problem をパラメータとして受け取るようになった。log(problem.position, problem.message, problem.severity) と呼び出すことで以前の log(...) に委譲できる。
  • xsbi.Maybexsbti.F0sxbti.F1 は対応する Java 8 クラスである java.util.Optionaljava.util.Supplier、および java.util.Function に変更する。
  • 使われていなかった “resident” オプションを撤廃する。 zinc#345 by @lukeindykiewicz

sbt サーバ: ツーリング統合のための JSON API 

sbt 1.0 はサーバ機能を含み、IDE や他のツールは JSON API を用いてビルドのセッティングをクエリしたり、コマンドを呼び出すことができる。sbt 0.13 においてインタラクティブ・シェルが shell コマンドによって実装されていたのと同様に、「サーバ」も shell コマンドによって実装されていて、人間とネットワークの両方の入力を受け取るようになっている。ユーザ視点で見ると、サーバが加わったことによる影響はほとんど無いはずだ。

2016年3月に「サーバ」機能が最小限になるようにリブートが行われた。JetBrain社で IntelliJ の sbt インターフェイスを担当する @jastice とコラボして機能のリストを絞っていった。sbt 1.0 の段階では当初欲しかった機能の全ては入っていないが、長期的に IDE と sbt エコシステムの連携が向上する布石になることを目指している。例えば、IDE 側から compile タスクを命令して、コンパイラ警告を JSON イベントして受け取るといったことができる:

{"type":"xsbti.Problem","message":{"category":"","severity":"Warn","message":"a pure expression does nothing in statement position; you may be omitting necessary parentheses","position":{"line":2,"lineContent":"  1","offset":29,"pointer":2,"pointerSpace":"  ","sourcePath":"/tmp/hello/Hello.scala","sourceFile":"file:/tmp/hello/Hello.scala"}},"level":"warn"}

関連して追加された機能として、テスト中にバックグラウンドで web サーバなどを実行するのに使える bgRun タスクがある。

イベント・ロギング 

sbt 1.0 は、Log4J 2 と sjson-new を用いて実装したイベント・ロギングを導入する。 普通の String ベースのログの他に、logger に対して case clase や Contraband によって生成された疑似 case class を渡すことができる:

def registerStringCodec[A: ShowLines: TypeTag]: Unit = ...
final def debugEvent[A: JsonFormat: TypeTag](event: => A): Unit = logEvent(Level.Debug, event)
final def infoEvent[A: JsonFormat: TypeTag](event: => A): Unit = logEvent(Level.Info, event)
final def warnEvent[A: JsonFormat: TypeTag](event: => A): Unit = logEvent(Level.Warn, event)
final def errorEvent[A: JsonFormat: TypeTag](event: => A): Unit = logEvent(Level.Error, event)

[success] メッセージといった様々なイベントは、内部でイベント・ロギングを用いて送信されている。 この機構をサーバと併用することで、プラグインやコンパイラから JSON イベントを発行することができる。

また、Log4J 2 を内部に採用したことで SLF4J のバインディングを提供するようになった。

build.sbt の静的バリデーション 

sbt 1.0 は、タスク内において if 式の本文や匿名関数内からの .value の呼び出しを禁止する。@sbtUnchecked アノテーションを使ってこのチェックを無効化できる。

他に、静的バリデーションは、タスクの本文内から .value を呼び忘れるのも予防する。

#3216 and #3225 by @jvican

Eviction 警告の表示 

sbt 1.0 は eviction 警告の表示を改善する。

ビフォー:

[warn] There may be incompatibilities among your library dependencies.
[warn] Here are some of the libraries that were evicted:
[warn]  * com.google.code.findbugs:jsr305:2.0.1 -> 3.0.0
[warn] Run 'evicted' to see detailed eviction warnings

アフター:

[warn] Found version conflict(s) in library dependencies; some are suspected to be binary incompatible:
[warn]
[warn]      * com.typesafe.akka:akka-actor_2.12:2.5.0 is selected over 2.4.17
[warn]          +- de.heikoseeberger:akka-log4j_2.12:1.4.0            (depends on 2.5.0)
[warn]          +- com.typesafe.akka:akka-parsing_2.12:10.0.6         (depends on 2.4.17)
[warn]          +- com.typesafe.akka:akka-stream_2.12:2.4.17 ()       (depends on 2.4.17)
[warn]
[warn] Run 'evicted' to see detailed eviction warnings

#3202 by @eed3si9n

sbt-cross-building 

@jrudolph の sbt-cross-building はプラグイン作者のためのプラグインだ。 ^ (クロス) コマンドと ^^ (sbtVersion スイッチ) コマンドを追加して、これは +++ を sbt のメジャーバージョン間の切り替えに対応させたものだと考えることができる。 プラグインを sbt 1.0 に対応させるのに便利なので、sbt 0.13.16 においてこれらのコマンドを sbt 本体にマージした。

シェルから sbtVersion in pluginCrossBuild をスイッチするには以下を実行する:

^^ 1.0.0

これで sbt 1.0.0 (とその Scala バージョンである 2.12) を使うようになる。

sbt バージョンに特定のコードを含む必要があれば、src/main/scala-sbt-0.13src/main/scala-sbt-1.0 などバイナリ sbt バージョンを末尾に追加したディレクトリを作る。

複数の sbt バージョンをまたいでコマンドを実行するには、まず:

crossSbtVersions := Vector("0.13.16", "1.0.0")

と設定して、以下を実行する:

^ compile

#3133 by @eed3si9n (forward ported from 0.13.16-M1)

CopyOptions 

sbt IO 1.0 は IO.copyFileIO.copyDirectory のバリエーションとして sbt.io.CopyOptions() を受け取るものを追加する。 CopyOptions() は疑似 case class の一例で、ビルダーパターンに似ている。

import sbt.io.{ IO, CopyOptions }

IO.copyDirectory(source, target)

// The above is same as the following
IO.copyDirectory(source, target, CopyOptions()
  .withOverwrite(false)
  .withPreserveLastModified(true)
  .withPreserveExecutable(true))

io#53 by @dwijnand

Library management API とアーティファクトの並列ダウンロード 

sbt 1.0 は Lightbend社の Eugene Yokota (@eed3si9n) と Scala Center の Martin Duhem (@Duhemm) 共著で書かれた Library management API を追加する。 この API は Apache Ivy および cached resolution や Coursier といったその他の代替依存性解決エンジンを抽象化することを目指している。

Ivy エンジンのためのアーティファクトの並列ダウンロードは Scala Center の Jorge (@jvican) によってコントリビュートされた。 また、これは Gigahorse OkHttp を Network API として導入し、内部で Square OkHttp をアーティファクトのダウンロードにも用いる。

lm#124 by @eed3si9n/@Duhemm, lm#90 by @jvican/@jsuereth and lm#104 by @eed3si9n.

Zinc の内部構造保存のためのバイナリ形式 

Zinc の内部構造の保存方法として Google Protocol Buffer を用いたバイナリ形式が Scala Center の Jorge (@jvican) によってコントリビュートされた。この新形式は主に 3つの利点がある:

  1. フォーマットレベルでの後方および前方互換性の向上。
  2. ファイルへのシリアライズ・デシリアライズの高速化 (1.5 ~ 2x)。
  3. ファイルのマシン非依存性の向上。

zinc#351 by @jvican

ライブラリ依存性のロッキング 

ライブラリ依存性のロッキング機能はまだ実装途中だが、Scala Center の Jorge (@jvican) は関連する機能を追加して、最終的にロッキングが可能となる予定だ。

  • Ivy ベースのライブラリ管理に frozen モードを追加して、解決が全て intransitive であることを保証できるようにした。 lm#100
  • ライブラリごとにリゾルバを指定できるようにした。 lm#97
  • Ivy にチェックサムをスキップするように指示する “managed checksums” を追加した。 lm#111

コントリビュータの皆さん 

感謝しなければいけない人が多すぎでここにおさまらなった。Credits を参照してほしい。