sbt 1.2.0

@eed3si9n

皆さんこんにちは。Lightbend Tooling team にかわって sbt 1.2.0 をアナウンスします。これは sbt 1 のフィーチャーリリース第二弾で、バイナリ互換性は維持しつつ新機能にフォーカスを当てたリリースとなっている。sbt 1 は Semantic Versioning にもとづいてリリースされるので、プラグインは sbt 1.x シリーズ中機能することが期待されている。

sbt 1.2 の主な新機能はクロスJDK forking、composite project、そして実験的な thin client だ。sbt 1.1 から 6ヶ月の間他にも色々なバグ修正や改善点がたまっていた。

プラグイン開発のための SbtPlugin

SbtPlugin は、プロジェクトが sbt plugin であることを宣言するためのプラグインだ。これは自動的に scripted test を導入して、sbtPlugin := true を設定する。

lazy val root = (project in file("."))
  .enablePlugins(SbtPlugin)

互換性に関する注意: ScritpedPlugin は triggered plugin ではなくなった。

#3875 by @eed3si9n

クロス JDK forking

runtest を fork した場合、java++ を使って Java Home を切り替えれるようになった。

sbt:helloworld> run
[info] Running (fork) Hello
[info] 1.8.0_171
sbt:helloworld> java++ 10!
[info] Reapplying settings...
sbt:helloworld> run
[info] Running (fork) Hello
[info] 10.0.1

sbt は、インストール済みの Java home を検知して discoveredJavaHomes セッティングに代入し、shyiko/jabba もサポートする。それで不十分な場合は Global / javaHomes を用いて補足する:

Global / javaHomes += "6" -> file("/something/java-6")

この機能は、ライブラリを古い JDK でテストして互換性の確認を取ることを目的としている。

#4139 by @2m, @cunei, and @eed3si9n

Composite project

sbt 1.2.0 は CompositeProject という trait を導入して、プラグイン作者が、クロスビルドなどのためにサブプロジェクトを生成することを可能とする。

trait CompositeProject {
  def componentProjects: Seq[Project]
}

これは @BennyHill さんによって #4056 にてコントリビュートされた。

Project matrix

実験段階CompositeProject のレファレンス実装として、projectMatrix という DSL を導入する sbt-projectmatrix というプラグインを実装した。

lazy val core = (projectMatrix in file("core"))
  .scalaVersions("2.12.6", "2.11.12")
  .settings(
    name := "core"
  )
  .jvmPlatform()

lazy val app = (projectMatrix in file("app"))
  .dependsOn(core)
  .scalaVersions("2.12.6")
  .settings(
    name := "app"
  )
  .jvmPlatform()

このプラグインはよりジェネリックなクロスビルド (Scala バージョン、プラットフォーム、その他) をサポートして、サブプロジェクトとして表現することを目的としている。上の例の projectMatrixcoreJVM2_12coreJVM2_11、そして appJVM2_12 という 3つのサブプロジェクトを作る。

Semantic Version selector API

sbt 1.2.0 は、VersionNumber() データ型に Semantic Version selector を導入し、基本的なマッチ、比較 (<=, <, >=, >)、論理演算 (>1.0.0 <2.0.0, ||)、範囲 (A.B.C - D.E.F)、ワイルドカード (2.12.x) をサポートする。

scala> import sbt.librarymanagement.{ VersionNumber, SemanticSelector }
import sbt.librarymanagement.{VersionNumber, SemanticSelector}

scala> VersionNumber("2.12.5").matchesSemVer(SemanticSelector(">=2.12"))
res1: Boolean = true

scala> VersionNumber("2.12.5").matchesSemVer(SemanticSelector("<2.12"))
res2: Boolean = false

scala> VersionNumber("2.13.0-M4").matchesSemVer(SemanticSelector("2.13"))
res3: Boolean = false

scala> VersionNumber("2.12.5").matchesSemVer(SemanticSelector("2.12.1 - 2.12.6"))
res4: Boolean = true

scala> VersionNumber("2.12.5").matchesSemVer(SemanticSelector("2.12.x"))
res5: Boolean = true

scala> VersionNumber("2.12.5").matchesSemVer(SemanticSelector("2.11.x || 2.12.x"))
res6: Boolean = true

これは Rikito Taniguchi (@tanishiking) さんにより lm#239 にてコントリビュートされた。

addPluginSbtFile コマンド

IntelliJ チームからビルドに安全にプラグインを注入したいというリクエストが以前よりあった。sbt 1.2.0 は -addPluginSbtFile というコマンドを追加してそれを可能とする。

$ cat /tmp/extra.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.7")

$ sbt -addPluginSbtFile=/tmp/extra.sbt
...
sbt:helloworld> plugins
In file:/xxxx/hellotest/
  ...
  sbtassembly.AssemblyPlugin: enabled in root

これは @eed3si9n により #4211 にて実装された。

拡張可能な sbt server

実験段階。プラグインを用いて sbt server を拡張できるようにした。

    Global / serverHandlers += ServerHandler({ callback =>
      import callback._
      import sjsonnew.BasicJsonProtocol._
      import sbt.internal.protocol.JsonRpcRequestMessage
      ServerIntent(
        {
          case r: JsonRpcRequestMessage if r.method == "lunar/helo" =>
            jsonRpcNotify("lunar/oleh", "")
            ()
        },
        PartialFunction.empty
      )

この機能はまだ実験的なので今後 API などが変更される可能性がある。

#3975 by @eed3si9n

Thin client(s)

実験段階。sbt 1.2.0 は -client という新しいモードを追加する。sbt が -client コマンドとともに実行されると、ビルドを読み込まず、JSON-RPC を用いて sbt server のインスタンスに接続しようとする。サーバが走っていなければ (portfile が見つからなければ) 新たな sbt インスタンスを全く別の新しい JVM 上に fork する。

これによって sbt をターミナル上、もしくはエディタなどから呼び出すことができる。

$ time sbt -client clean
[info] entering *experimental* thin client - BEEP WHIRR
[info] server was not detected. starting an instance
[info] waiting for the server...
[info] waiting for the server...
[info] waiting for the server...
[info] waiting for the server...
[info] server found
> clean
[success] completed
sbt -client clean  9.23s user 2.33s system 22% cpu 50.558 total

# server stays
$ ps | rg java
21860 ttys015    1:22.43 java -Xms2048M -Xmx2048M -Xss2M -jar /usr/local/Cellar/sbt/1.1.6/libexec/bin/sbt-launch.jar
22014 ttys015    0:00.00 rg java

$ time sbt -client clean
[info] entering *experimental* thin client - BEEP WHIRR
> clean
[info] Updating ...
[info] Done updating.
[success] completed
sbt -client clean  3.39s user 1.75s system 104% cpu 4.898 total

server を終了させるには sbt -client shutdown を呼び出す。 #4227 by @eed3si9n

さらに、thin client の代替実装も既に出ていて、Rust を用いてクリスさん cb372/sbt-client と Dale dwijnand/sbtl が作っている。

互換性に影響のある変更点

その他のバグ修正や改善点

内部実装に関する変更

Scala Spree NYC

2018年6月19日に Scala Days の周辺イベントとして Scala Spree も New York City に来た。主催は Tapad社と Scala Center で、Lightbend社は朝食とランチを提供した。Scala Spree は OSS な Scala プロジェクトの代表者 (通常はメンテナ) と一緒に作業して pull request を送って、Scala コントリビュータになろうというハッカソンの一種だ。

Lightbend Tooling Team は sbt を代表して参加した。前準備として、Dale と僕は GitHub issue に “help wanted”“good first issue” といったラベル付けを行って、コントリビュータ希望者が作業できるものを見つけれるようにした。

一日を通してディスカッションやバグ調査が行われ、当日や後日も含め複数の pull request があった:

イベントに皆が参加しやすいようにサポートしていたフレンドリーな Tapad の皆さんにお礼を言いたい。

参加

前回の sbt 1 フィーチャーリリースは 2028年1月の sbt 1.1.0 だった。それ以降バグ修正などのために 6本のパッチリリースをリリースしたが、機能追加などは 1.x ブランチに merge されてきた。

2月の段階で sbt 1.2.0 roadmap を公開して、その中で以下の点に注力することを提案した:

2018年を通して Lightbend Tooling team はオープンソースにおけるコントリビューションにフォーカスしてきた。これは、僕たちがコミュニティーにどう貢献できるかということと、sbt や Zinc といったツール群が Scala コミュニティー全般から参加しやすくするにはどうすればいいのかという両方を含んでいる。毎週水曜日にミーティングを行ったり (是非参加したい人は声をかけてほしい)、ロードマップを公開したり、コントリビュータガイドを改善したり、再現性の低い CI テストを直すなどといったことを具体的に行ってきた。さらに、一言でコントリビューションといっても様々な方法があることを強調してきた:

  1. 採用するのを手伝う
  2. 職場や Stackoverflow などで他のユーザをアシストする
  3. ドキュメンテーションにコントリビュートする
  4. issue トラッカーのガーデニング
  5. pull request のレビューを手伝う
  6. issue を報告する
  7. エコシステムを拡張する
  8. コアをパッチする

sbt と Zinc 1 の改善に手伝ってくれた皆さんにこの場をお借りして感謝します。

sbt 1.2.0 は 60名のコントリビュータのお陰でできました (敬称略): Dale Wijnand, Eugene Yokota, Kenji Yoshida (xuwei-k), Yasuhiro Tatsuno (exoego), Łukasz Wawrzyk, Jorge Vicente Cantero (jvican), Alistair Johnson, Antonio Cunei, Jason Zaugg, Rikito Taniguchi (tanishiking), Seiya Mizuno, Tim Harper, Aloisia Davì (alodavi), Arnout Engelen, Ethan Atkins, Johannes Rudolph, Krzysztof Romanowski, Allan Renucci, Brian P. Holt, Filipe Regadas, Hiroshi Ito, Martijn Hoekstra, OlegYch, Seth Tisue, natans, Aaron S. Hawley, Alex Khvatov, Alexander Samsig, Andreas Jim-Hartmann, Andrei Pozolotin, Andrey Kaygorodov, Anthony Garo, Christopher Hunt, Colin Dean, Daniel Riquelme, Deokhwan Kim, Gerard Maas, Guillaume Poirier, Heikki Vesalainen, Jason Pickens, Jonas Fonseca, Julien Jerphanion, Justin Pihony, Kazufumi Nishida, Kyle Goodale, Maksym Fedorov, Mark Canlas, Martynas Mickevičius, Michael Pollmeier, Mike Skells, Nafer Sanabria, Naohisa Murakami (tiqwab), PanAeon, Peter Neyens, Rui Gonçalves, Sean Sullivan, Stephen Nancekivell, Veera Venky, blakkan, ortigali. Thank you!