Build.scala でアプリケーションをサブ プロジェクトに分割します。
サブプロジェクトクラスのセットに対してコンパイル時にタスクを実行する必要があります。サブプロジェクト自体をプラグインにし、それらに依存せずにサブプロジェクトクラスを静的にインポートする方法がないため、リフレクションに頼っています。
val fooTask = TaskKey[Unit]("foo", "Description...")
val foo = fooTask := {
val classpath = Array("pathA", "pathB", "...")
val sbtLoader = this.getClass.getClassLoader
val appLoader: ClassLoader = URLClassLoader(classpath, sbtLoader)
val mainClass = appLoader.loadClass("Foo")
val mainMethod = mainClass.getMethod("main", classOf[Array[String]])
try {
mainMethod.invoke(new Object, Array(""))
}
catch {
case e: InvocationTargetException => println(e.getCause)
}
}
呼び出されたメソッドにリフレクションが含まれていなければ、すべて正常に動作しますが、残念ながらそこにもリフレクションが必要です! FWIW、Foo の使用例は、各サブ プロジェクトのコントローラーに基づいて Play フレームワーク javascript ルートのセットを生成し、コンパイル時に静的ファイルに書き込むことです。
collection.map{ clazz=>
clazz.getFields.map(_.get(null)).flatMap { c=>
c.getClass.getDeclaredMethods.map(
_.invoke(c).asInstanceOf[JavascriptReverseRoute]
)
}
}.flatten
Scala 2.10にのみ存在するもので爆発しjava.lang.ClassNotFoundException: scala.reflect.ClassTag$
ますが、2.10.2に対してコンパイルされたアプリケーションには問題ありません。ただし、SBT 0.12.3 は Scala 2.9.2 を使用しており、カードのリフレクション ハウスがクラッシュする場所に違いありません。
ターミナル セッション経由で、目的のクラスを Scala 2.10.2 経由で直接実行でき、javascript ルートが正常に生成されます。ただし、コンパイルのたびに Task が新しい Scala セッションを起動しないようにしたいと思います。
誰でも回避策のアイデアがありますか? SBT 0.13 は Play とそのすべての 0.12 ベースのプラグインをビルドするには新しすぎます。
ありがとう