酢豚3 by mersy

初心者ぺちぱーがGitHubでScalaレッスンを始めたぞ。今回もScalaの標準的なビルドツールであるsbtの使い方の続き。IntelliJ IDEA用プロジェクトファイルを作れるようになろう。

sbt plugin - sbt-idea

GitHubのsbt-ideaというsbtプラグインを使うとgen-ideaというコマンドでIntelliJ IDEA用プロジェクトファイルが作れるようになる。

sbt plugins

READMEに書いてある通りだが、PROJECT_DIR/project/plugins.sbtに設定を追加しよう。この設定で、sbt-ideaプラグインが使えるようになる。

PROJECT_DIR/project/plugins.sbt
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0")

ちなみに、Getting-Started/Using Pluginsには、build.sbtでもplugins.sbtでもどちらでもいいけど、慣習的にplugins.sbtにする人もいるよね、というようなことが書いてあった。

reloadするとsbt-ideaがダウンロードされてくる。

$ sbt reload
[info] Loading project definition from /Users/satoshi/prj/work/scala/hello/project
[info] Updating {file:/Users/satoshi/prj/work/scala/hello/project/}default-df742a...
[info] Resolving org.scala-sbt#precompiled-2_10_0;0.12.2 ...
[info] downloading http://repo1.maven.org/maven2/com/github/mpeltonen/sbt-idea_2.9.2_0.12/1.2.0/sbt-idea-1.2.0.jar ...
[info] [SUCCESSFUL ] com.github.mpeltonen#sbt-idea;1.2.0!sbt-idea.jar (993ms)
[info] downloading http://repo1.maven.org/maven2/commons-io/commons-io/2.0.1/commons-io-2.0.1.jar ...
[info] [SUCCESSFUL ] commons-io#commons-io;2.0.1!commons-io.jar (73ms)
[info] Done updating.
[info] Set current project to hello (in build file:/Users/satoshi/prj/work/scala/hello/)
[info] Loading project definition from /Users/satoshi/prj/work/scala/hello/project
[info] Set current project to hello (in build file:/Users/satoshi/prj/work/scala/hello/)

gen-ideaコマンドが使えるようになったはずなので、試してみる。

$ sbt gen-idea
[info] Loading project definition from /Users/satoshi/prj/work/scala/hello/project
[info] Set current project to hello (in build file:/Users/satoshi/prj/work/scala/hello/)
[info] Trying to create an Idea module hello
[info] Resolving org.scala-lang#scala-reflect;2.10.0 ...
[info] Excluding folder target
[info] Created /Users/satoshi/prj/work/scala/hello/.idea/IdeaProject.iml
[info] Created /Users/satoshi/prj/work/scala/hello/.idea
[info] Excluding folder /Users/satoshi/prj/work/scala/hello/target
[info] Created /Users/satoshi/prj/work/scala/hello/.idea_modules/hello.iml
[info] Created /Users/satoshi/prj/work/scala/hello/.idea_modules/hello-build.iml

ログを見ると.ideaが作成されたようだ。これでIntelliJ IDEA用のプロジェクトファイルが出来上がった。

Start up IntelliJ IDEA

さて、IDEAを起動してみよう。起動後のプロジェクト選択画面の右側にある"Import Project"をクリックしよう。

ここで、IDEA用プロジェクトフォルダを選択する。今回はhelloプロジェクトなので、helloフォルダを選択する。

すると、選択したhelloプロジェクトがIDEAに認識されて、空の画面が表示される。左側に見える"Project"タブを選択すると、プロジェクトエクスプローラーが表示される。

よく見ると、External Librariesのscalaコンパイラが2.9.2になっている。。これはなんでだろう。

.idea/librariesにそれらしい設定ファイルが置いてあったが、このディレクトリにはSBT__scala_2_10_1.xmlSBT__scala_2_9_2.xmlがあった。2.9.2のxmlを移動してみると、External Librariesから消える。戻してみると復活する。しかし、2.10.1では移動しても、戻しても何も変化がなかった。IDEAを再起動しても同様に変化なし。ちなみに、これらのxmlファイルの中身はこんな感じ。

.idea/libraries/SBT__scala_2_10_1.xml
<component name="libraryTable">
<library name="SBT: scala:2.10.1">
<CLASSES>
<root url="jar://$USER_HOME$/.sbt/boot/scala-2.10.1/lib/scala-library.jar!/" />
<root url="jar://$USER_HOME$/.sbt/boot/scala-2.10.1/lib/scala-compiler.jar!/" />
<root url="jar://$USER_HOME$/.sbt/boot/scala-2.10.1/lib/scala-reflect.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
.idea/libraries/SBT__scala_2_9_2.xml
<component name="libraryTable">
<library name="SBT: scala:2.9.2">
<CLASSES>
<root url="jar://$USER_HOME$/.sbt/boot/scala-2.9.2/lib/scala-library.jar!/" />
<root url="jar://$USER_HOME$/.sbt/boot/scala-2.9.2/lib/scala-compiler.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

バージョンが違うぐらいで変なところはなさそうな気がする。パス通りの場所にjarファイルは配置されているし。うーん。2.10じゃなくて2.10.1になっているのは、きっとバイナリーバージョンじゃなくてコンパイラーのバージョンだからよね。

.idea/scala_compiler.xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ScalacSettings">
<option name="COMPILER_LIBRARY_NAME" value="SBT: scala:2.10.1" />
<option name="COMPILER_LIBRARY_LEVEL" value="Project" />
</component>
</project>

このファイルにはSBT: scala:2.10.1というように名前が指定してあって、"SBT_scala2101.xml "のライブラリ名と同じになっている。ぬーん。

修正するには、プロジェクトルートを右クリックして、Open Module Settingsを選択。Project Structure画面が開くので、Project Settings > Librariesを選択して、scala 2.9.2を選択して削除する。scala 2.10.1を右クリックして、Add to Modulesを選択。helloを選択してOKボタンをクリック。

これでExternal Librariesにscala 2.10.1が表示されるようになった。やったね!

IntelliJ IDEAからも2.10.1で実行できるか試してみる。すると、こんなエラーが出てきた。プロダクションコードとテストコードの出力先が同じになっていて、IDEAのexternal build modeはそれをサポートしてないから、出力先を分けるか、external build modeを無効にしろと言っている。なんでまだ2.9.2が出てきているのか分からない。sbtの設定を見ているから?でも確かに、テストコードは本番環境には不要なので、分けるべきなのかもしれない。sbtの設定をどう変更するかは次の宿題。とりあえずexternal build modeを無効にしてみる。

scala: Output path /Users/satoshi/prj/work/scala/hello/project/target/scala_2.9.2 is shared between: Module 'hello-build' production, Module 'hello-build' tests
Currently external Scala compiler prohibits output path sharing.
Either disable the external build mode or configure separate output paths.
TIP: you can use Project Artifacts to combine compiled classes.

Preferencesから環境設定を開き、Project Settings > Compilerを選択する。Use external buildにチェックが入っているので、チェックを外す。

これで、再度実行してみると、無事にへろーと表示された。ログに表示されるクラスパスには、2.10.1と表示されているので、ちゃんと動いたようだ。やったね!

Conclusion

Javaではmavenでこんなことをやるんだろうけど、自分はJavaのお作法を知らないので、ハマると調べるのに時間がかかるんだなーと思った。今回のsbtプロジェクトはGitHubの別リポジトリにした。まとめ!

  • sbt-ideaを使ってIntelliJ IDEA用のプロジェクトファイルを生成できる
  • sbtプラグインはproject/plugins.sbtに設定を書く
  • reload、gen-ideaコマンドを実行して.idea/を生成する
  • 外部ライブラリの設定がおかしいこともあるので、適宜修正する
  • sbtプロジェクトの場合はexternal build modeを無効にする

Reference