ねこ元帥の中の人@リウマチ

日々の覚書など。ブログ名はオンラインゲームのアカウント名をいつも「ねこ元帥」にしているから。そして、2013年11月リウマチと診断されたとです。(2012年11月から時々手足に原因不明の痛みが発生、2013年9月以降は足の痛みが常態化、2013年12月30日からMTX服用開始、4月過ぎるころにはわずかの痛みが残る程度まで回復して現在に至る。)

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

参考:自分用sbtテンプレート

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