1. 生成文件

生成文件 

sbt 提供标准挂钩,用于添加源文件和资源生成任务。

生成源文件 

源文件生成任务应该在 sourceManaged 的子目录中生成源文件,并返回生成的源文件列表。源文件生成函数(成为任务的基础)的签名通常如下所示

def makeSomeSources(base: File): Seq[File]

要添加任务的键称为 sourceGenerators。由于我们要添加任务,而不是执行后获得的值,因此我们使用 taskValue 代替通常的 valuesourceGenerators 应该根据生成的文件是主文件(Compile)还是测试(Test)源文件进行范围限定。这种基本结构如下所示

Compile / sourceGenerators += <task of type Seq[File]>.taskValue

例如,假设一个方法 def makeSomeSources(base: File): Seq[File]

Compile / sourceGenerators += Def.task {
  makeSomeSources((Compile / sourceManaged).value / "demo")
}.taskValue

作为一个具体的示例,以下源文件生成器生成 Test.scala 应用程序对象,该对象一旦执行,就会在控制台中打印 "Hi"

Compile / sourceGenerators += Def.task {
  val file = (Compile / sourceManaged).value / "demo" / "Test.scala"
  IO.write(file, """object Test extends App { println("Hi") }""")
  Seq(file)
}.taskValue

执行 run 将打印 "Hi"

> run
[info] Running Test
Hi

Compile 更改为 Test 以使其成为测试源文件。

注意: 为了提高构建效率,sourceGenerators 应该避免在每次调用时重新生成源文件。相反,输出应该基于输入值进行缓存,可以使用 文件跟踪系统 或使用 sbt.Tracked.{ inputChanged, outputChanged } 等手动跟踪输入值。

默认情况下,生成的源文件不会包含在打包的源文件工件中。要做到这一点,请像添加其他映射一样添加它们。请参阅 向包中添加文件。源文件生成器可以返回 Java 和 Scala 源文件的混合,它们在同一个序列中。它们将在稍后根据其扩展名进行区分。

生成资源 

资源生成任务应该在 resourceManaged 的子目录中生成资源,并返回生成的资源列表。与源文件生成函数类似,资源生成函数(成为任务的基础)的签名通常如下所示

def makeSomeResources(base: File): Seq[File]

要添加任务的键称为 resourceGenerators。由于我们要添加任务,而不是执行后获得的值,因此我们使用 taskValue 代替通常的 value。它应该根据生成的文件是主文件(Compile)还是测试(Test)资源进行范围限定。这种基本结构如下所示

Compile / resourceGenerators += <task of type Seq[File]>.taskValue

例如,假设一个方法 def makeSomeResources(base: File): Seq[File]

Compile / resourceGenerators += Def.task {
  makeSomeResources((Compile / resourceManaged).value / "demo")
}.taskValue

执行 run(或 package,而不是 compile)将在 resourceManaged 中添加一个名为 demo 的文件,resourceManagedtarget/scala-*/resource_managed"。默认情况下,生成的资源不会包含在打包的源文件工件中。要做到这一点,请像添加其他映射一样添加它们。请参阅 向包中添加文件.

作为一个具体的示例,以下代码会生成一个名为 myapp.properties 的属性文件,其中包含应用程序名称和版本

Compile / resourceGenerators += Def.task {
  val file = (Compile / resourceManaged).value / "demo" / "myapp.properties"
  val contents = "name=%s\nversion=%s".format(name.value,version.value)
  IO.write(file, contents)
  Seq(file)
}.taskValue

Compile 更改为 Test 以使其成为测试资源。

注意: 为了提高构建效率,resourceGenerators 应该避免在每次调用时重新生成资源文件,而是使用 sbt.Tracked.{ inputChanged, outputChanged } 等对输入值进行缓存。