JavaでもGradleの名前をよく聞く昨今ですが、個人的にはGradleよりもsbtの方をよく使っているため、こちらでできてもいいよねーということで。
あ、ちょっと興味があったので調べて書いていますが、どちらかといえばネタエントリに近いかも…。まあ、慣れという点もあるので、こちらで考えたいですけどねー。
では、いってみましょう。
とりあえず、普通にbuild.sbtとJavaソースコードを作成する
build.sbtを作成します。内容は、まあ普通に。依存関係には、スケープゴート的にCommons Lang3でいきましょう。
build.sbt
name := "sbt-simple-java-project" version := "0.0.1-SNAPSHOT" organization := "org.littlewings" libraryDependencies ++= Seq( "org.apache.commons" % "commons-lang3" % "3.3.2" )
Javaソースコードは、こんな感じで用意。
src/main/java/App.java
import java.util.Arrays; import java.util.List; import java.util.ArrayList; import org.apache.commons.lang3.StringUtils; public class App { public static void main(String[] args) { System.out.println(join(Arrays.asList("Hello", "World"))); } public static String join(Iterable<String> iterable) { return StringUtils.join(iterable, ", "); } }
この状態で、普通にコンパイルして
> compile
実行できます。
> run [info] Running App Hello, World
このままでも、普通に使えそうですね?
プロジェクトから、Scalaへの依存関係を取り除く
上記のように、最低限の設定でも普通に使えそうですが、packageしてみるとJARファイルの名前に妙なものがくっついてきます。
> package [info] Updating {file:/xxxxx/sbt-simple-java-project/}sbt-simple-java-project... [info] Resolving org.fusesource.jansi#jansi;1.4 ... [info] Done updating. [info] Compiling 1 Java source to /xxxxx/sbt-simple-java-project/target/scala-2.10/classes... [info] Packaging /xxxxx/sbt-simple-java-project/target/scala-2.10/sbt-simple-java-project_2.10-0.0.1-SNAPSHOT.jar ...
これですね。
sbt-simple-java-project_2.10-0.0.1-SNAPSHOT.jar
さらに言うと、Scalaへの依存関係までくっついています。
*sbt-dependency-graph(https://github.com/jrudolph/sbt-dependency-graph)使用
> dependencyTree [info] Updating {file:/xxxxx/sbt-simple-java-project/}sbt-simple-java-project... [info] Resolving org.fusesource.jansi#jansi;1.4 ... [info] Done updating. [info] org.littlewings:sbt-simple-java-project_2.10:0.0.1-SNAPSHOT [S] [info] +-org.apache.commons:commons-lang3:3.3.2
[S]が付いているのは、Scalaへの依存関係があることを表しています。
まず、できあがるJARファイルからScalaのバージョンを除くには、以下をbuild.sbtに加えます。
crossPaths := false
依存関係にScalaが追加されないようにするには、以下を加えます。
autoScalaLibrary := false
ここまでで、build.sbtはこうなりました。sbtコンソールを起動している場合は、reloadしてください。
name := "sbt-simple-java-project" version := "0.0.1-SNAPSHOT" organization := "org.littlewings" autoScalaLibrary := false crossPaths := false libraryDependencies ++= Seq( "org.apache.commons" % "commons-lang3" % "3.3.2" )
Javaソースコードのコンパイルオプションを指定する
特に何もしていせずとも実行環境のJavaのバージョンで動くようですが、明示的に指定する場合は以下の様に設定します。
javacOptions ++= Seq("-source", "1.8", "-target", "1.8")
JUnitテストケースを実行する
作成したソースコードの、テストを用意することもやってみましょう。build.sbtの依存関係を、以下の様に修正します。
libraryDependencies ++= Seq( "org.apache.commons" % "commons-lang3" % "3.3.2", "junit" % "junit" % "4.11" % "test" )
で、reload。
テストコードも、以下の様に用意してみます。
src/test/java/AppTest.java
import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import java.util.Arrays; import org.junit.Test; public class AppTest { @Test public void testJoin() { assertThat(App.join(Arrays.asList("Hello", "World")), is("Hello, World")); } }
では、テスト実行。
> test [info] Updating {file:/xxxxx/sbt-simple-java-project/}sbt-simple-java-project... [info] Resolving org.fusesource.jansi#jansi;1.4 ... [info] Done updating. [info] Compiling 1 Java source to /xxxxx/sbt-simple-java-project/target/classes... [info] Compiling 1 Java source to /xxxxx/sbt-simple-java-project/target/test-classes... [info] Passed: Total 0, Failed 0, Errors 0, Passed 0 [info] No tests to run for test:test
テストがないと言われます。
[info] No tests to run for test:test
sbtでJUnitのテストケースを実行するためには、もうちょっと設定が必要です。
依存関係に、以下を追加します。
libraryDependencies ++= Seq( "org.apache.commons" % "commons-lang3" % "3.3.2", "junit" % "junit" % "4.11" % "test", "com.novocode" % "junit-interface" % "0.11-RC1" % "test" )
追加したのは、ここですね。
"com.novocode" % "junit-interface" % "0.11-RC1" % "test"
sbtでJUnitテストケースを実行するには、junit-interfaceが必要になります。
junit-interface
https://github.com/sbt/junit-interface
reloadして、テスト実行。
> test [info] Updating {file:/xxxxx/sbt-simple-java-project/}sbt-simple-java-project... [info] Resolving org.fusesource.jansi#jansi;1.4 ... [info] Done updating. [info] Compiling 1 Java source to /xxxxx/sbt-simple-java-project/target/classes... [info] Compiling 1 Java source to /xxxxx/sbt-simple-java-project/target/test-classes... [info] Passed: Total 1, Failed 0, Errors 0, Passed 1
テストが実行されました。
ここまでで、build.sbtの設定はこんな感じになっています。
name := "sbt-simple-java-project" version := "0.0.1-SNAPSHOT" organization := "org.littlewings" javacOptions ++= Seq("-source", "1.8", "-target", "1.8") autoScalaLibrary := false crossPaths := false libraryDependencies ++= Seq( "org.apache.commons" % "commons-lang3" % "3.3.2", "junit" % "junit" % "4.11" % "test", "com.novocode" % "junit-interface" % "0.11-RC1" % "test" )
まあ、あんまり使うことはないかもしれませんが、簡単に使う分にはいいかも?
参考)
Beginning SBT - A Simple Java-Only Project with Eclipse
http://blog.jiffle.net/post/32451176640/beginning-sbt-a-simple-java-only-project-with-eclipse
Basic Definition Examples
http://www.scala-sbt.org/release/docs/Examples/Quick-Configuration-Examples.html
番外編 テストでのみScalaを使用する
通常はJavaで書きたいけれど、テストコードのみでScalaを使用したい場合は、依存関係に以下を加えます。
"org.scala-lang" % "scala-library" % scalaVersion.value % "test"
この時は、Scalaのバージョンを指定した方がいい気がします。
scalaVersion := "2.11.0"
つまり、こんな感じになります。
name := "sbt-simple-java-project" version := "0.0.1-SNAPSHOT" scalaVersion := "2.11.0" organization := "org.littlewings" javacOptions ++= Seq("-source", "1.8", "-target", "1.8") autoScalaLibrary := false crossPaths := false libraryDependencies ++= Seq( "org.apache.commons" % "commons-lang3" % "3.3.2", "junit" % "junit" % "4.11" % "test", "com.novocode" % "junit-interface" % "0.11-RC1" % "test", "org.scala-lang" % "scala-library" % scalaVersion.value % "test" )
参考)
Configuring Scala
http://www.scala-sbt.org/0.13.2/docs/Detailed-Topics/Configuring-Scala.html