gpt4 book ai didi

scala - 从 SBT 项目中的宏读取资源

转载 作者:行者123 更新时间:2023-12-04 15:12:29 25 4
gpt4 key购买 nike

假设我有一个包含三个子项目的 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返回行数;否则它是空的。

另外两个 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项目,我可以很容易地配置它,让根项目聚合三个子项目和 baz取决于 bar ,这取决于 foo .见 this Gist对于血腥的细节。

使用 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只能看到 foobar :
Some(1)
Some(2)
None

这里发生了什么?这个 SBT 构建文件在我看来是 Maven 配置的一个非常直白的翻译。我在 bar 中打开控制台没有问题项目和阅读 /bar.txt例如,那么为什么这些项目在调用宏时看不到自己的资源呢?

最佳答案

SBT 不会将当前项目的资源添加到构建类路径中。可能是因为很少需要它。

您只需要将一个(资源)通过管道传输到另一个(类路径):

def commonSettings = Defaults.defaultSettings ++ Seq(
scalaVersion := "2.10.2",
libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _),
// add resources of the current project into the build classpath
unmanagedClasspath in Compile <++= unmanagedResources in Compile
)

在那个项目中,你只需要 barbaz .

更新:自 sbt 0.13 起, <+=<++=由于新的基于宏的语法,是不必要的(并且没有记录):
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
unmanagedClasspath in Compile ++= (unmanagedResources in Compile).value

关于scala - 从 SBT 项目中的宏读取资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17134244/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com