scala - 如何使 SBT 任务依赖于同一 SBT 项目中定义的模块?

标签 scala sbt sbt-assembly sbt-plugin

我在多模块 SBT 项目中有模块 A 和模块 B。我想为模块 B 编写一个从模块 A 调用代码的资源生成器任务。一种方法是从 project/ 下的模块 A 中提取所有代码,但这是不可行的,因为模块 A 是巨大,我想将其保留在原处(参见 https://stackoverflow.com/a/47323703/471136 )。我如何在 SBT 中执行此操作?

其次,是否有可能完全摆脱模块 B,即我希望模块 A 的资源生成器任务实际上从模块 A 调用代码,但模块 A 是根模块并且不存在于 SBT 的项目?

注意:这个问题不是这个问题的重复:Defining sbt task that invokes method from project code?因为那个人决定将代码移到 SBT 的项目中,这是我在这里特别要避免的事情。

最佳答案

认为我正在做类似于您在以下项目中的第一部分的事情:我的module gen相当于你的模块A,我的module core相当于你的模块B,未经测试,结构大致如下:

// taking inspiration from
// http://stackoverflow.com/questions/11509843/
lazy val ugenGenerator = TaskKey[Seq[File]]("ugen-generate", "Generate UGen class files")

lazy val gen = Project(id = "gen", base = file("gen")) ...

lazy val core = Project(id = "core", base = file("core"))
  .settings(
    sourceGenerators in Compile <+= ugenGenerator in Compile,
    ugenGenerator in Compile := {
      val src   = (sourceManaged       in Compile        ).value
      val cp    = (dependencyClasspath in Runtime in gen ).value
      val st    = streams.value
      runUGenGenerator(description.value, outputDir = src, 
        cp = cp.files, log = st.log)
    }
  )

def runUGenGenerator(name: String, outputDir: File, cp: Seq[File],
                    log: Logger): Seq[File] = {
  val mainClass   = "my.class.from.Gen"
  val tmp         = java.io.File.createTempFile("sources", ".txt")
  val os          = new java.io.FileOutputStream(tmp)

  log.info(s"Generating UGen source code in $outputDir for $name")

  try {
    val outs  = CustomOutput(os)
    val fOpt  = ForkOptions(javaHome = None, outputStrategy = Some(outs), bootJars = cp,
        workingDirectory = None, connectInput = false)
    val res: Int = Fork.scala(config = fOpt,
      arguments = mainClass :: "-d" :: outputDir.getAbsolutePath :: Nil)

    if (res != 0) {
      sys.error(s"UGen class file generator failed with exit code $res")
    }
  } finally {
    os.close()
  }
  val sources = scala.io.Source.fromFile(tmp).getLines().map(file).toList
  tmp.delete()
  sources
}

这在 sbt 0.13 中有效,但我还没有时间弄清楚为什么它在 1.x 中不起作用。

对了,sourceGenerators in Compile <+= ugenGenerator in Compile怎么写?没有弃用的语法?

关于scala - 如何使 SBT 任务依赖于同一 SBT 项目中定义的模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47418859/

相关文章:

scala - SBT assembly-plugin 的 PathList 中的 "xs @ _*"是什么意思?

scala - scala 中的逆变

sbt: "impossible to get artifacts when data has not been loaded. IvyNode = org.antlr#stringtemplate;3.2.1"

scala - 拆分 sbt 多模块项目 scala 构建文件

scala - SBT 是否支持循环依赖?

playframework - com.typesafe.config.ConfigException$缺少 : No configuration setting found for key 'play.application'

scala - 从宏中调用宏

没有vars的scala编程

scala - 如何在 Eclipse 中将 Swing 与 Scala 2.11 一起使用?

git - 设置sbt发布到基于git分支的artifactory