Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何使SBT任务依赖于同一SBT项目中定义的模块?_Scala_Sbt_Sbt Assembly_Sbt Plugin - Fatal编程技术网

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

Scala 如何使SBT任务依赖于同一SBT项目中定义的模块?,scala,sbt,sbt-assembly,sbt-plugin,Scala,Sbt,Sbt Assembly,Sbt Plugin,我有一个多模块SBT项目中的模块A和模块B。我想为模块B编写一个资源生成器任务,调用模块a中的代码。一种方法是在project/下从模块a中提取所有代码,但这是不可行的,因为模块a很大,我希望将其保留在原来的位置(请参阅)。我如何在SBT中做到这一点 其次,是否有可能完全摆脱模块B,即我希望模块A的资源生成器任务实际调用模块A中的代码,但模块A是根模块,不在SBT的项目中 注意:这个问题不是这个问题的重复:因为这个问题决定将代码移动到SBT的项目中,这是我在这里特别想要避免的事情。我想我正在做一

我有一个多模块SBT项目中的模块A和模块B。我想为模块B编写一个资源生成器任务,调用模块a中的代码。一种方法是在
project/
下从模块a中提取所有代码,但这是不可行的,因为模块a很大,我希望将其保留在原来的位置(请参阅)。我如何在SBT中做到这一点

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

注意:这个问题不是这个问题的重复:因为这个问题决定将代码移动到SBT的项目中,这是我在这里特别想要避免的事情。

我想我正在做一些类似于以下项目中的第一部分的事情:My相当于您的模块a,my相当于模块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
}
//从中汲取灵感
// http://stackoverflow.com/questions/11509843/
lazy val ugenGenerator=TaskKey[Seq[File]](“ugen生成”、“生成ugen类文件”)
惰性val gen=Project(id=“gen”,base=file(“gen”)。。。
lazy val core=Project(id=“core”,base=file(“core”))
.设置(

编译中的sourceGenerators基于上面的@0\uuuuuuu答案,以下是我的简化版本:

  /**
    * Util to run the main of a sub-module from within SBT
    *
    * @param cmd The cmd to run with the main class with args (if any)
    * @param module The sub-module
    */
  def runModuleMain(cmd: String, module: Reference) = Def.task {
    val log = streams.value.log
    log.info(s"Running $cmd ...")
    val classPath = (fullClasspath in Runtime in module).value.files
    val opt = ForkOptions(bootJars = classPath, outputStrategy = Some(LoggedOutput(log)))
    val res = Fork.scala(config = opt, arguments = cmd.split(' '))
    require(res == 0, s"$cmd exited with code $res")
  }
然后,您可以通过以下方式调用它:

resourceGenerators in Compile += Def.taskDyn {
  val dest = (resourceManaged in Compile).value
  IO.createDirectory(dest)
  runModuleMain(
    cmd = "com.mycompany.foo.ResourceGen $dest $arg2 $arg3 ...",
    module = $referenceToModule // submodule containing com.mycompany.foo.ResourceGen
  ).taskValue
  dest.listFiles()
}
有必要这样做:

resourceGenerators in Compile += Def.taskDyn {
  val dest = (resourceManaged in Compile).value
  IO.createDirectory(dest)      
  Def.task {
    val cmd = "com.mycompany.foo.ResourceGen $dest $arg2 $arg3 ..."        
    (runMain in Compile).toTask(" " + $cmd).value 
    dest.listFiles()
  }
}.taskValue

我想你可以摆脱
lhs这是否意味着我必须在某个地方添加Scala编译器本身作为依赖项???不确定,但我的“gen”模块确实添加了编译器:
“org.Scala lang”%”Scala编译器“%scalaVersion.value
(不记得为什么)嗯,还有一件事-模块A本身从它自己的资源中加载一些其他东西。当我执行
getClass.getResourceAsStream(foo)时,使用Fork.scala调用模块A似乎会抛出一个NPE
在模块A中。我如何解决这个问题?我是否需要以某种方式将resourced to Fork选项传入?不确定,但建议您可能需要
fullClasspath