次のようなファイルを含む、3 つのサブプロジェクトを含む Scala プロジェクトがあるとします。
foo/src/main/scala/Foo.scala
foo/src/main/resources/foo.txt
bar/src/main/scala/Bar.scala
bar/src/main/resources/bar.txt
baz/src/main/scala/Baz.scala
baz/src/main/resources/baz.txt
Foo.scala
特定のパスでリソースを読み取る単純なマクロが含まれています。
import scala.language.experimental.macros
import scala.reflect.macros.Context
object Foo {
def countLines(path: String): Option[Int] = macro countLines_impl
def countLines_impl(c: Context)(path: c.Expr[String]) = {
import c.universe._
path.tree match {
case Literal(Constant(s: String)) => Option(
this.getClass.getResourceAsStream(s)
).fold(reify(None: Option[Int])) { stream =>
val count = c.literal(io.Source.fromInputStream(stream).getLines.size)
reify(Some(count.splice))
}
case _ => c.abort(c.enclosingPosition, "Need a literal path!")
}
}
}
リソースを開くことができる場合はcountLines
、行数を返します。それ以外の場合は空です。
他の 2 つの Scala ソース ファイルは、このマクロを呼び出すだけです。
object Bar extends App {
println(Foo.countLines("/foo.txt"))
println(Foo.countLines("/bar.txt"))
println(Foo.countLines("/baz.txt"))
}
と:
object Baz extends App {
println(Foo.countLines("/foo.txt"))
println(Foo.countLines("/bar.txt"))
println(Foo.countLines("/baz.txt"))
}
リソースの内容は、この質問の目的にはあまり関係ありません。
これが Maven プロジェクトの場合、ルート プロジェクトが 3 つのサブプロジェクトを集約し、 にbaz
依存するように簡単に構成できます。詳細については、この Gistを参照してください。bar
foo
Maven を使用すると、すべてが期待どおりに機能します。とBar
のリソースを表示できます:foo
bar
Some(1)
Some(2)
None
そしてBaz
それらすべてを見ることができます:
Some(1)
Some(2)
Some(3)
今、私はSBTで同じことを試しています:
import sbt._
import Keys._
object MyProject extends Build {
lazy val root: Project = Project(
id = "root", base = file("."),
settings = commonSettings
).aggregate(foo, bar, baz)
lazy val foo: Project = Project(
id = "foo", base = file("foo"),
settings = commonSettings
)
lazy val bar: Project = Project(
id = "bar", base = file("bar"),
settings = commonSettings,
dependencies = Seq(foo)
)
lazy val baz: Project = Project(
id = "baz", base = file("baz"),
settings = commonSettings,
dependencies = Seq(bar)
)
def commonSettings = Defaults.defaultSettings ++ Seq(
scalaVersion := "2.10.2",
libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _)
)
}
しかし、今Bar
では以下のリソースしか見ることができませんfoo
:
Some(1)
None
None
とのみをBaz
見ることができます:foo
bar
Some(1)
Some(2)
None
何が起きてる?この SBT ビルド ファイルは、Maven 構成のかなり文字通りの翻訳のように思えます。たとえば、プロジェクトでコンソールを開いてbar
を読むのに問題はないのに/bar.txt
、マクロを呼び出すときにこれらのプロジェクトが独自のリソースを表示できないのはなぜですか?