SBT:编译前为子模块生成代码

SBT: generate code for submodule before compilation

我在 build.sbt 配置方面遇到以下问题。 我需要在编译之前生成一些代码。 现在就是这样。

lazy val rootProject = project.in(file("."))

lazy val rootSourceGenerator = Def.task {
  val f: File = (sourceManaged in Compile).value / "com" / "myproject" / "Version.scala"

  IO.write(
    f,
    s"""package com.myproject
       |
       |object Version {
       |  some code ...
       |}
       |""".stripMargin
  )

  Seq(f)
}

inConfig(Compile)(
  Seq(
    sourceGenerators += rootSourceGenerator
  ))

现在我需要为新的子模块做同样的事情。

lazy val rootProject = project.in(file(".")).dependsOn(submodule)
lazy val submodule = project.in(file("submodule"))

lazy val submoduleSourceGenerator = Def.task {
  val f: File = (sourceManaged in (submodule, Compile)).value / "com" / "myproject" / "SubmoduleVersion.scala"

  IO.write(
    f,
    s"""package com.myproject
       |
       |object SubmoduleVersion {
       |  some code ...
       |}
       |""".stripMargin
  )

  Seq(f)
}

inConfig(submodule / Compile)(
  Seq(
    sourceGenerators += submoduleSourceGenerator
  ))

inConfig(submodule / Compile) 不起作用。错误是关于 / 的未知语法。 有什么解决方法的建议吗?

有多种解决方案,但我认为最干净的解决方案。

project/GenerateVersion.scala 中创建具有以下内容的 AutoPlugin

import sbt.Keys._
import sbt._

object GenerateVersion extends AutoPlugin {
  override def trigger = noTrigger

  override def projectSettings: Seq[Def.Setting[_]] = {
    Seq(
      sourceGenerators in Compile += Def.task {
        val f: File =
          (sourceManaged in Compile).value / "com" / "myproject" / "Version.scala"
        IO.write(
          f,
          s"""package com.myproject
                 |
                 |object Version {
                 |}
                 |""".stripMargin
        )
        Seq(f)
      }.taskValue
    )
  }
}

为所有需要 Version.scala 生成的 projects/submodules 启用新创建的插件 GenerateVersion。可以按照build.sbt

中的以下方式完成
lazy val sub = project
  .in(file("sub"))
  .enablePlugins(GenerateVersion)

lazy val root = project
  .in(file("."))
  .enablePlugins(GenerateVersion)
  .aggregate(sub)
当触发根任务时,

aggregate(sub) 被添加到 sub 模块中的 运行 任务。例如,sbt compile 将 运行 同时 sbt "root/compile" "sub/compile"

此解决方案更容易以 SBT 插件的形式在多个 SBT 项目之间共享。

此外,您可能对 sbt-builtinfo 插件感兴趣

谢谢 Ivan Stanislavciuc!但我找到了另一种解决方案。 只需将以下所有内容添加到 /subproject/build.sbt

lazy val submoduleSourceGenerator = Def.task {
  val f: File = (sourceManaged in Compile).value / "com" / "myproject" / "SubmoduleVersion.scala"

  IO.write(
    f,
    s"""package com.myproject
       |
       |object SubmoduleVersion {
       |  some code ...
       |}
       |""".stripMargin
  )

  Seq(f)
}

inConfig(Compile)(
  Seq(
    sourceGenerators += submoduleSourceGenerator
  ))