ぶらっ記ぃ

日本語の練習をしています

Coursier を使って最速でScalaの開発環境を整える

ざっくりまとめ

Coursierの setup コマンドを使うとJDKScala開発に必要なツールをまとめてインストールできるよ。

最近追加された install コマンド

get-coursier.io

Coursier といえば sbt v1.3.0 で取り込まれた高速でライブラリ依存を取得するためのOSSとして有名ですが、このCoursierにはCLIが提供されており、ライブラリ依存のグラフを出力したりアプリケーションの起動スクリプトを用意するコマンドが提供されています。

最近の Coursier v2.0.0-RC のアップデートで install コマンドが追加されました。

これはいわばパッケージマネージャのような機能で、JVM向けのCLIアプリケーションをインストールできるコマンドです。
以下の例はAmmoniteをインストールする例です。
以下のコマンドを実行するだけで、Ammoniteの最新版がインストールされます。

$ cs install ammonite
https://repo1.maven.org/maven2/org/scala-lang/scala-library/maven-metadata.xml
  No new update since 2020-03-16 10:26:09
https://repo1.maven.org/maven2/com/lihaoyi/ammonite_2.13.1/maven-metadata.xml
  No new update since 2020-01-14 04:26:58
Warning: /home/blacky/.local/share/coursier/bin is not in your PATH
To fix that, add the following line to your shell configuration file

export PATH="$PATH:/home/blacky/.local/share/coursier/bin"

$  ~/.local/share/coursier/bin/amm
Loading...
Compiling (synthetic)/ammonite/predef/interpBridge.sc
Compiling (synthetic)/ammonite/predef/replBridge.sc
Compiling (synthetic)/ammonite/predef/sourceBridge.sc  
Compiling (synthetic)/ammonite/predef/frontEndBridge.sc
Compiling (synthetic)/ammonite/predef/DefaultPredef.sc
Welcome to the Ammonite Repl 2.0.4 (Scala 2.13.1 Java 1.8.0_232)
@ println("Foo!")
Foo!

インストール可能なアプリケーションは以下のリポジトリで管理されており、このcontrib以下にプルリクエストを送れば自身で作成したアプリケーションを追加することもできそうです。

github.com

setup コマンドを使って一発でScala環境を整える

さて、本題になりますが、このCoursierにはさらに setup というコマンドが追加されています。
これを使うとJDKを含め、Scalaの開発環境に必要なアプリケーションをまとめてインストールしてくれます。

これを実験するために ubuntu:18.04 のコンテナからScalaの環境を整えてみます。
もちろん、JDKもインストールされていない状態です。

$ docker run -it --rm ubuntu:18.04
# java -version
bash: java: command not found

Coursierのインストールにcurlコマンドを使うのでインストールしておきます。

# apt update && apt install -y curl

Coursierコマンドをインストールします。ドキュメントに従ってコマンドを実行します。

# curl -Lo cs https://git.io/coursier-cli-linux && chmod +x cs && ./cs --help
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100   144  100   144    0     0    126      0  0:00:01  0:00:01 --:--:--  140k
100 51.3M  100 51.3M    0     0  5889k      0  0:00:08  0:00:08 --:--:-- 8030k
Coursier 2.0.0-RC6-11
Usage: cs \[options\] [command] [command-options]

Available commands: bootstrap, complete, fetch, install, java, java-home, launch, publish, resolve, setup, uninstall, update

Type  cs command --help  for help on an individual command

インストールが成功し、 ./cs --help コマンドを実行することができました。
Coursier CLIはGraalVMのNative Imageを使ってLinuxほか各OS専用のバイナリを作っているため、JVMのインストールなしに起動できます。

ここまでできたら setup コマンドを実行してみましょう。

# ./cs setup -y
Checking if a JVM is installed
No JVM found, should we try to install one? [Y/n] Y
Extracting
  /root/.cache/coursier/v1/https/github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u242-b08/OpenJDK8U-jdk_x64_linux_hotspot_8u242b08.tar.gz
in
  /root/.cache/coursier/jvm/adopt@1.8.0-242
Done
Should we update ~/.profile? [Y/n] Y
Some shell configuration files were updated. It is recommended to close this terminal once the setup command is done, and open a new one for the changes to be taken into account.

Checking if ~/.local/share/coursier/bin is in PATH
Should we add ~/.local/share/coursier/bin to your PATH via ~/.profile? [Y/n] Y

Checking if the standard Scala applications are installed
  Installed ammonite
  Installed cs
  Installed coursier
  Installed scala
  Installed scalac
  Installed sbt-launcher
  Installed scalafmt

JDKおよびScala関連のアプリケーションがインストールされました。
ログに出ている通り、 ~/.profile が更新され、 JAVA_HOMEPATH の設定が追加されていますので、 source コマンドを叩いて設定を反映させます。

# cat ~/.profile
# ~/.profile: executed by Bourne-compatible login shells.

if [ "$BASH" ]; then
  if [ -f ~/.bashrc ]; then
    . ~/.bashrc
  fi
fi

mesg n || true

# >>> JVM installed by coursier >>>
export JAVA_HOME="/root/.cache/coursier/jvm/adopt@1.8.0-242"
export PATH="$PATH:/root/.cache/coursier/jvm/adopt@1.8.0-242/bin"
# <<< JVM installed by coursier <<<

# >>> coursier install directory >>>
export PATH="$PATH:/root/.local/share/coursier/bin"
# <<< coursier install directory <<<

# source ~/.profile

あとは好きなようにコマンドを叩きましょう!

# java -version
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.242-b08, mixed mode)

# scala
Welcome to Scala 2.13.1 (OpenJDK 64-Bit Server VM, Java 1.8.0_242).
Type in expressions for evaluation. Or try :help.

scala> println("Foo!!")
Foo!!

setup コマンドでインストールされるアプリケーション

AdoptOpenJDK

デフォルトではAdoptOpenJDK 8、HotSpotVMがインストールされます。
インストールされるバージョンはコマンドのオプションで指定可能で--jvm 11 とするとJDK11がインストールされるようです。

# java -version
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.242-b08, mixed mode)

ammonite

Scalaの拡張REPL、およびScalaスクリプトの実行環境です。
Magic Importsを使った動的なライブラリの追加ができるので動作確認をしたり、Scalaスクリプトを書いて簡単な自動化を行ったりと、活用の幅は結構広く筆者オススメのツールです。

宣伝になりますが、Ammoniteについて同人誌を書いております。
興味がある方はぜひお手にとっていただければ幸いです🙇

booth.pm

# amm
Loading...
Welcome to the Ammonite Repl 2.0.4 (Scala 2.13.1 Java 1.8.0_242)
@ import $ivy.`com.lihaoyi::scalatags:0.8.2`
https://repo1.maven.org/maven2/com/lihaoyi/scalatags_2.13/0.8.2/scalatags_2.13-0.8.2.pom
  100.0% [##########] 1.6 KiB (1.3 KiB / s)
https://repo1.maven.org/maven2/com/lihaoyi/scalatags_2.13/0.8.2/scalatags_2.13-0.8.2-sources.jar
  100.0% [##########] 69.8 KiB (70.5 KiB / s)
https://repo1.maven.org/maven2/com/lihaoyi/scalatags_2.13/0.8.2/scalatags_2.13-0.8.2.jar
  100.0% [##########] 475.8 KiB (256.2 KiB / s)
import $ivy.$

@ import scalatags.Text.all._
import scalatags.Text.all._

html(head(tag("title")("scalatags")), body(div(h1("Foo!!"), p("Yeah")))).toString
res6: String = "<html><head><title>scalatags</title></head><body><div><h1>Foo!!</h1><p>Yeah</p></div></body></html>"

cs / coursier

Coursier自身もインストールされます。
cs コマンドはネイティブで実行され、 coursier コマンドはJVMで実行される違いがあるようです。

# time cs --help
Coursier 2.0.0-RC6-11
Usage: cs \[options\] [command] [command-options]

Available commands: bootstrap, complete, fetch, install, java, java-home, launch, publish, resolve, setup, uninstall, update

Type  cs command --help  for help on an individual command

real 0m0.021s
user 0m0.005s
sys 0m0.016s

# time coursier --help
Coursier 2.0.0-RC6-11
Usage: coursier \[options\] [command] [command-options]

Available commands: bootstrap, complete, fetch, install, java, java-home, launch, publish, resolve, setup, uninstall, update

Type  coursier command --help  for help on an individual command

real 0m0.973s
user 0m1.583s
sys 0m0.105s

scala

Scala本体のREPLです。コンパイルしたScalaコードの実行、またスクリプトの実行も可能です。

# scala -version
Scala code runner version 2.13.1 -- Copyright 2002-2019, LAMP/EPFL and Lightbend, Inc.

# echo "println(123)" > script.scala

# scala script.scala
123

scalac

Scalaコンパイラです。 sbtプロジェクト上で開発する場合に直接触る機会は少ないですが、コンパイラオプションは普段の開発に役立つことも多いので使い方は覚えておいて損はないと思います。

# scalac -version
Scala compiler version 2.13.1 -- Copyright 2002-2019, LAMP/EPFL and Lightbend, Inc.

# echo 'object Main { def main(args: Array[String]): Unit = println("Hello, Scala!") }' > Main.scala

# scalac Main.scala

# scala -cp . Main
Hello, Scala!

sbt-launcher

Coursierが提供するsbtを起動するためのスクリプトです。

sbt本体の起動スクリプトと異なる点に注意してください。
詳しくは調べていませんが、 -mem オプションなど、使えないオプションもありそうです。

また、sbtプロジェクト外で起動したときに異常終了するIssueも報告されていますので、現状sbtプロジェクト外でsbtを起動したい際は以下のようにオプションでsbtのバージョンを指定して実行する必要があります。

# sbt -Dsbt.version=1.3.8 new scala/scala-seed.g8
Getting scala-compiler 2.12.10
 [##########]   Downloaded 3 POM files in 1 s
 [##########]   Downloaded 3 JAR files in 25 s
Getting sbt 1.3.8
 [##########]   Downloaded 87 POM files in 6 s
 [##########]   Downloaded 78 JAR files in 97 s
[info] Set current project to root (in build file:/)
[info] Set current project to root (in build file:/)
[info] downloading https://repo1.maven.org/maven2/org/scala-sbt/sbt-giter8-resolver/sbt-giter8-resolver_2.12/0.11.0/sbt-giter8-resolver_2.12-0.11.0.jar ...
[info] downloading https://repo1.maven.org/maven2/org/scala-lang/scala-library/2.12.10/scala-library-2.12.10.jar ...
[info] downloading https://repo1.maven.org/maven2/org/scala-sbt/template-resolver/0.1/template-resolver-0.1.jar ...
[info] downloading https://repo1.maven.org/maven2/org/foundweekends/giter8/giter8_2.12/0.11.0/giter8_2.12-0.11.0.jar ...
[info] downloading https://repo1.maven.org/maven2/org/foundweekends/giter8/giter8-lib_2.12/0.11.0/giter8-lib_2.12-0.11.0.jar ...
[info] downloading https://repo1.maven.org/maven2/com/github/scopt/scopt_2.12/3.7.0/scopt_2.12-3.7.0.jar ...
(略)

A minimal Scala project.

name [Scala Seed Project]:

Template applied in /./scala-seed-project

# ls -la scala-seed-project/
total 24
drwxr-xr-x 4 root root 4096 Mar 22 07:00 .
drwxr-xr-x 1 root root 4096 Mar 22 07:00 ..
-rw-r--r-- 1 root root    8 Mar 22 07:00 .gitignore
-rw-r--r-- 1 root root  447 Mar 22 07:00 build.sbt
drwxr-xr-x 2 root root 4096 Mar 22 07:00 project
drwxr-xr-x 4 root root 4096 Mar 22 07:00 src

scalafmt

Scalaコードのフォーマッタです。
ルールを定義しておくことで、プロジェクト内のコードインデント幅などを統一させることが可能です。

# cat src/main/scala/example/Hello.scala
package example

object Hello extends
Greeting
with App {
          println(greeting)
}

trait Greeting {
  lazy val greeting: String =
{
"hello"
  }
}

# scalafmt

# cat src/main/scala/example/Hello.scala
package example

object Hello extends Greeting with App {
  println(greeting)
}

trait Greeting {
  lazy val greeting: String = {
    "hello"
  }
}

あとがき

Coursierの setup コマンドでScalaの開発環境を整えるのはとても簡単でした。
Scalaを始めるにはまず sbt のインストールから」だったところが、「まずは Coursier をインストール」に変わっていく可能性も大いにあるんじゃないかなぁと思いました。

install コマンドも同様に便利で、自身でCLIアプリケーションを公開することも可能なので、また別の機会で試してみたいですね。