ant4sbtプラグイン使用メモ
ant4sbtプラグインのビルド
参考:ant4sbtプラグインのbitbucketリポジトリ
リポジトリに登録されていないようなので、ビルドしてローカルリポジトリに配布する。
hg clone https://bitbucket.org/jmhofer/ant4sbt
cd ant4sbt
sbt
8/22にsbt-0.13.0がリリースされたようだが、ビルド環境のsbtバージョンをアップデートすると
ダウンロードできなくなるライブラリが存在するため、しばらくはsbt-0.12.4を使用する。
set scalaVersion := "2.9.2" set sbtBinaryVersion := "0.12" set sbtVersion := "0.12.4" publish-local
ant4sbtプラグインの読み込み
plugins.sbt に以下の設定を記述する。
addSbtPlugin("de.johoop" % "ant4sbt" % "1.1.1")
project/Build.scalaに以下の設定を記述する。
object AppBuild extends Build { // SETTING: プロジェクト共通設定 ≪省略≫ ) ++ antSettings ++ site.settings ++ MyEclipse.eclipseSettings
ant4sbtプラグインの実行
以下のタスクでベースディレクトリに置いたbuild.xmlのタスクを実行する。
ant-run
antタスクの実行は別のJavaVMを起動して実行しているようで、上記タスクを実行する際に依存タスクとして以下のタスクが実行される。
ant-start-server
Windows環境でエラー発生
Windowsでant-runタスクを実行した際にエラーが出た。
クラスパスに空白を含むパスが含まれていることで例外が発生しているよう。
> ant-run [error] Error: Could not find or load main class Files\Java\jdk1.7.0_21\lib\tools.jar;C:\Program > last [debug] Starting Ant server... [error] Error: Could not find or load main class Files\Java\jdk1.7.0_21\lib\tools.jar;C:\Program java.net.ConnectException: Connection refused: connect at java.net.DualStackPlainSocketImpl.connect0(Native Method) ≪省略≫ at de.johoop.ant4sbt.ant.AntClient.retry(AntClient.scala:33) at de.johoop.ant4sbt.ant.AntClient.retry(AntClient.scala:33) at de.johoop.ant4sbt.ant.AntClient.retry(AntClient.scala:33) at de.johoop.ant4sbt.ant.AntClient.ping(AntClient.scala:23) at de.johoop.ant4sbt.ForkedAntServer$class.startAntServer(ForkedAntServer.scala:48) at de.johoop.ant4sbt.Ant4Sbt$.startAntServer(Ant4Sbt.scala:18) ≪省略≫ at java.lang.Thread.run(Unknown Source)
例外発生個所のソースコード調べてみた。(WindowsにmercurialインストールしていないのでUbuntuで作業)
hg clone https://bitbucket.org/jmhofer/ant4sbt cd ant4sbt vi src/main/scala/de/johoop/ant4sbt/ForkedAntServer.scala ≪省略≫ val process = "java %s -cp %s de.johoop.ant4sbt.ant.AntServer %s %s %d".format( options, PathFinder(classpath).absString, buildFile.absolutePath, baseDir.absolutePath, port) run logging(streams.log)
クラスパス指定箇所を以下の通り変更してビルドし、ant-run実行できるようになったことを確認できた。
val command = "java %s -cp \"%s\" de.johoop.ant4sbt.ant.AntServer %s %s %d".format(
AntServerクラスに対する引数部分も空白含んでいたら同じ結果になるのではと思い、ちょっと確認してみたところ例外が発生した。
[info] Set current project to root (in build file:/C:/Users/takamatu/work/template%20sbt-scala/) > ant-run [error] Exception in thread "main" java.lang.NumberFormatException: For input string: "C:\Users\takamatu\work\template" > last [debug] Starting Ant server... [error] Exception in thread "main" java.lang.NumberFormatException: For input string: "C:\Users\takamatu\work\template" [error] at java.lang.NumberFormatException.forInputString(Unknown Source) [error] at java.lang.Integer.parseInt(Unknown Source) [error] at java.lang.Integer.parseInt(Unknown Source) [error] at scala.collection.immutable.StringLike$class.toInt(StringLike.scala:231) [error] at scala.collection.immutable.StringOps.toInt(StringOps.scala:31) [error] at de.johoop.ant4sbt.ant.AntServer$.main(AntServer.scala:31) [error] at de.johoop.ant4sbt.ant.AntServer.main(AntServer.scala) java.net.ConnectException: Connection refused: connect at java.net.DualStackPlainSocketImpl.connect0(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source) ≪省略≫ at de.johoop.ant4sbt.ant.AntClient.retry(AntClient.scala:33) at de.johoop.ant4sbt.ant.AntClient.retry(AntClient.scala:33) at de.johoop.ant4sbt.ant.AntClient.ping(AntClient.scala:23) at de.johoop.ant4sbt.ForkedAntServer$class.startAntServer(ForkedAntServer.scala:52) at de.johoop.ant4sbt.Ant4Sbt$.startAntServer(Ant4Sbt.scala:18) ≪省略≫ at java.lang.Thread.run(Unknown Source)
AntServerクラスに対する引数部分も合わせて以下の通り修正した。
val command = "java %s -cp \"%s\" de.johoop.ant4sbt.ant.AntServer \"%s\" \"%s\" %d".format(
リポジトリをフォークしてプログラムを修正。
hg clone https://tkmtmkt@bitbucket.org/tkmtmkt/ant4sbt cd ant4sbt hg branch path_with_space ≪プログラム修正≫ hg commit -m "Changed to no problem even if the path includes a space." hg push --new-branch
プルリクエスト実行
https://bitbucket.org/tkmtmkt/ant4sbt/ 「Pull request」を押す。 左「path_with_space」を選択 右「default」を選択
追記
scalaから外部プロセスの実行を行う場合に、引数をリストで指定する方法があるだろうと思い、Scala逆引きレシピを見てみたけど、文字列に対して「!」メソッドを読んで結果を取得する方法が書いてあった。
あとでScala API調べてみる。
Scala Standard Library API (Scaladoc) 2.10.2
以下のimplicitでコマンド文字列をProcessBuilderに変換している。
scala.sys.process trait ProcessImplicits extends AnyRef implicit def stringToProcess(command: String): ProcessBuilder
ProcessBuilderのメソッドが以下の通りとなっている。(ForkedAntServer.scalaにProcessImplicitsのimportが無いがどこで変換しているのか?)
scala.sys.process trait ProcessBuilder extends Source with Sink abstract def !(log: ProcessLogger): Int abstract def run(log: ProcessLogger): Process
ProcessImplicits に文字列のリストからProcessBuilderへの変換も定義されているので、コマンド文字列部分をSeq()に変更するだけでよさそう。
scala.sys.process trait ProcessImplicits extends AnyRef implicit def stringSeqToProcess(command: Seq[String]): ProcessBuilder