sbt 1.3.0-RC1

in

皆さんこんにちは。sbt プロジェクトを代表して sbt 1.3.0-RC1 をアナウンスします。これは sbt 1 のフィーチャーリリース第3弾で、バイナリ互換性は維持しつつ新機能にフォーカスを当てたリリースとなっている。sbt 1 は Semantic Versioning にもとづいてリリースされるので、プラグインは sbt 1.x シリーズ中機能することが期待されている。

  • 2019年3月29日までに大きな問題が見つからなければ、1.3.0-RC1 は 1.3.0 final 版となる予定だ。

sbt 1.3 の主な新機能はデフォルトでの Coursier を使ったライブラリ管理、ClassLoader レイヤリング、IO の改善、そして super shell だ。これらの機能の組み合わせがビルドのユーザーエクスペリエンスを向上することを願っている。

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

  • Coursier を用いたライブラリ管理。詳細は後ほど。
  • ClassLoader レイヤリング。詳細は後ほど。
  • super shell。詳細は後ほど。

sbt-projectmatrix を用いた並列クロスビルド

去年 sbt のクロスビルドを改善するために、sbt-projectmatrix という実験的プラグインを書いた。0.2.0 をリリースしたのでここで紹介する。

複数の Scala バージョンに対するビルド

sbt-projectmatrix をビルドに追加後、以下のようにして 2つの Scala バージョンを使ったマトリックスをセットアップする。

ThisBuild / organization := "com.example"
ThisBuild / scalaVersion := "2.12.8"
ThisBuild / version      := "0.1.0-SNAPSHOT"
 
lazy val core = (projectMatrix in file("core"))
  .settings(
    name := "core"
  )
  .jvmPlatform(scalaVersions = Seq("2.12.8", "2.11.12"))

これは coreJVM2_11coreJVM2_12 というサブプロジェクトを作る。
++ スタイルのステートフルなクロスビルドと違って、これは並列にビルドする。

git リポジトリの分岐

サブディレクトリを新しいリポジトリへ分岐させる

git clone --no-hardlinks --branch master originalRepoURL childRepo
cd childRepo
git filter-branch --prune-empty --subdirectory-filter path/to/keep master
git remote remove origin
git prune
git gc --aggressive

originalRepoURLmasterpath/to/keep などは適当な値に変える。全てのブランチを処理したい場合は -- --all を使う。

src を path/to/keep に戻す

--subdirectory-filterpath/to/keep 以下の src/ などをルートに移動してしまうので、元のパス (もしくは別のパス) に戻したい場合は移動させてコミットを 1つ追加する必要がある。

mkdir -p path/to/keep
git mv src path/to/keep
git commit -m "move files"

君達の JDK は全て SDKMAN! がいただいた

in

これは Travis CI に自分で JDK をインストールする解説の第2弾だ。以前は、jabba を紹介した。

今日は SDKMAN! という、Marco Vermeulen (@marc0der) さんが作った元気な名前のツールを見ていく。これは、JDK の他にも Groovy、Spark、sbt など JVM 上の様々なツールを対象とする環境マネージャーだ。

AdoptOpenJDK 11 と 8

以下は SDKMAN! を使って Travis CI 上で AdoptOpenJDK 8 と 11 を用いてクロスビルドする方法だ:

sudo: false
dist: trusty
group: stable
 
language: scala
 
scala: 2.12.8
 
matrix:
  include:
  - env:
      - TRAVIS_JDK=11.0.2.hs-adpt
  - env:

2019.03 mixtape

in

Spotify: https://open.spotify.com/user/1235450353/playlist/0guisAxA5Q2WO6biLJqdU0...
YouTube: https://www.youtube.com/playlist?list=PLSUh6oJ5ZotUlIMwWcbtV7FRTEzHqYm_7

2h 58m

track list

  • Mbr / Ajisai - Ametsub
  • Win In The Flat World - Lorenzo Senni
  • Opal - Four Tet Remix - Bicep, Four Tet
  • ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ৢ؞ؖ؞ - △▃△▓
  • Recursion - Throwing Snow
  • Opal Waltz - Supernaive
  • Turnhalle - Barker & Baumecker
  • #17 - Aphex Twin
  • Good Winds - Efdemin
  • Stingray Nebula - OUER

Docker での sbt

AdoptOpenJDK JDK 8 を用いる場合:

docker pull eed3si9n/sbt:jdk8-alpine
docker run -it --mount src="$(pwd)",target=/opt/workspace,type=bind eed3si9n/sbt:jdk8-alpine

AdoptOpenJDK JDK 11 を用いる場合:

docker pull eed3si9n/sbt:jdk11-alpine
docker run -it --mount src="$(pwd)",target=/opt/workspace,type=bind eed3si9n/sbt:jdk11-alpine

Pamflet 0.8.0

年末の連休中に Pamflet の left TOC (目次) を実装して、Pamflet 0.8.0 としてリリースした。

Pamflet は短い文書、特にオープンソース・ソフトウェアの ユーザ・ドキュメントを公開するためのアプリだ。

scopt 4

in

scopt 4 における関数型 DSL は以下のようになる:

import scopt.OParser
val builder = OParser.builder[Config]
val parser1 = {
  import builder._
  OParser.sequence(
    programName("scopt"),
    head("scopt", "4.x"),
    // option -f, --foo
    opt[Int]('f', "foo")
      .action((x, c) => c.copy(foo = x))
      .text("foo is an integer property"),
    // more options here...
  )
}
 
// OParser.parse returns Option[Config]
OParser.parse(parser1, args, Config()) match {
  case Some(config) =>
    // do something
  case _ =>
    // arguments are bad, error message will have been displayed
}

OptionParser 内でメソッドを呼ぶのではなく、関数型 DSL はまず特定の Config データ型に対するビルダーを作って、opt[A](...) など Oparser[A, Config] を返す関数を呼ぶ。

これらの OParser[A, Config] パーサーは OParser.sequence(...) を用いて合成できる。

最初は for 内包表記を使ってこの合成を表すことも考えていたが、その見た目に慣れて人にとっては分かりづらいと思ったので sequence 関数を作った。

芽キャベツのサラダ

Syndicate content