【问题标题】:Generate resources for compile and test生成用于编译和测试的资源
【发布时间】:2015-08-19 16:01:30
【问题描述】:

我打算根据模板和 sbt 设置生成资源。 CompileTest 应该有不同的 sbt 设置。模板位于project/resources/hdfs/*.xml。从 sbt-dev gitter 聊天中,我得到了使用 SettinginConfig 的建议,但我无法让它工作。

到目前为止的代码:

val hdfsNamenode = settingKey[String]("Namenode for the HDFS access")

def genHdfsConfigs: Setting[_] =
  hdfsNamenode := {
    resourceGenerators += Def.task {
      val files = ((baseDirectory.value / "project" / "resources" / "hdfs" ) * "*.xml").get
      files.foreach({ hdfsTemplate =>
        val config = IO.read(hdfsTemplate).replace("{{namenode}}", hdfsNamenode.value)
        IO.write(resourceManaged.value / hdfsTemplate.getName, config)
      })
      files.toSeq
    }.taskValue
  }

hdfsNamenode in Test := "localhost"
hdfsNamenode in Compile := "172.31.32.228"

def allHdfsNamenodeConfigs: Seq[Setting[_]] =
  inConfig(Compile)(Seq(hdfsNamenode)) ++ inConfig(Test)(Seq(hdfsNamenode))

错误:

[error]  found   : sbt.Def.Setting[Seq[sbt.Task[Seq[java.io.File]]]]
[error]  required: String
[error]       resourceGenerators += Def.task {
[error]                          ^

[error]  found   : sbt.SettingKey[String]
[error]  required: sbt.Def.Setting[_]
[error]     inConfig(Compile)(Seq(hdfsNamenode)) ++ inConfig(Test)(Seq(hdfsNamenode))
[error]        

下一次迭代,我不知道如何在Compile/Test 范围内获取hdfsNameNode,而不是在非范围内。

lazy val hdfsNameNode = settingKey[String]("Namenode for the HDFS access")

val genHdfsConfig = Def.task {
  val files = ((baseDirectory.value / "project" / "templates" / "resources" / "hdfs" ) * "*.xml").get
  files.map({ hdfsTemplate =>
    val config = IO.read(hdfsTemplate).replace("{{namenode}}", hdfsNameNode.value)
    val outputPath = resourceManaged.value / hdfsTemplate.getName
    IO.write(outputPath, config)
    outputPath
  })
}

Seq(
    hdfsNameNode := "undefined", // Only this one is accepted
    hdfsNameNode in Test := "localhost",
    hdfsNameNode in Compile := "172.31.32.228",
    resourceGenerators in Compile += genHdfsConfig.taskValue,
    resourceGenerators in Test += genHdfsConfig.taskValue
  )

当前(丑陋的)解决方案:

val hdfsTestNameNode = "localhost"
val hdfsMainNameNode = "172.31.32.228"

val hdfsNameNode = settingKey[String]("Namenode for the HDFS access")

val genTestHdfsConfig = Def.task {
  val files = ((baseDirectory.value / "project" / "templates" / "resources" / "hdfs" ) * "*.xml").get
  files.map({ hdfsTemplate =>
    val config = IO.read(hdfsTemplate).replace("{{namenode}}", (hdfsNameNode in Test).value)
    val outputPath = resourceManaged.value / hdfsTemplate.getName
    IO.write(outputPath, config)
    outputPath
  })
}

val genCompileHdfsConfig = Def.task {
  val files = ((baseDirectory.value / "project" / "templates" / "resources" / "hdfs" ) * "*.xml").get
  files.map({ hdfsTemplate =>
    val config = IO.read(hdfsTemplate).replace("{{namenode}}", (hdfsNameNode in Compile).value)
    val outputPath = resourceManaged.value / hdfsTemplate.getName
    IO.write(outputPath, config)
    outputPath
  })
}

Seq(
  hdfsNameNode in Test := hdfsTestNameNode,
  hdfsNameNode in Compile := hdfsMainNameNode,
  resourceGenerators in Compile += genCompileHdfsConfig.taskValue,
  resourceGenerators in Test += genTestHdfsConfig.taskValue
 )

【问题讨论】:

  • 这个带有Def.task.taskValue 的东西对我来说看起来很复杂。也许旧的 sbt 版本需要这个?你看过scala-sbt.org/0.13/tutorial/… - 它应该和taskKey:= 一样简单。
  • @0__ 然后我不知道如何将它添加到 resourceGenerators 所以它被拾取。

标签: scala sbt


【解决方案1】:

在定义资源生成器时只需将配置作为参数传递。

val hdfsTestNameNode = "localhost"
val hdfsMainNameNode = "172.31.32.228"

val hdfsNameNode = settingKey[String]("Namenode for the HDFS access")

def genHdfsConfig(cfg: Configuration) = Def.task {
  val files = ((baseDirectory.value / "project" / "templates" / "resources" / "hdfs" ) * "*.xml").get
  files.map({ hdfsTemplate =>
    val config = IO.read(hdfsTemplate).replace("{{namenode}}", (hdfsNameNode in cfg).value)
    val outputPath = (resourceManaged in cfg).value / hdfsTemplate.getName
    IO.write(outputPath, config)
    outputPath
  })
}

Seq(
  hdfsNameNode in Test := hdfsTestNameNode,
  hdfsNameNode in Compile := hdfsMainNameNode,
  resourceGenerators in Compile += genHdfsConfig(Compile).taskValue,
  resourceGenerators in Test += genHdfsConfig(Test).taskValue
)

不想指定范围两次?只需再重构一点。

val hdfsTestNameNode = "localhost"
val hdfsMainNameNode = "172.31.32.228"

val hdfsNameNode = settingKey[String]("Namenode for the HDFS access")

def addHdfsConfigGenerator(cfg: Configuration) = {
  inConfig(cfg) {
    val hdfsConfigGenerator = Def.task {
      val files = ((baseDirectory.value / "project" / "templates" / "resources" / "hdfs" ) * "*.xml").get
      files.map({ hdfsTemplate =>
        val config = IO.read(hdfsTemplate).replace("{{namenode}}", (hdfsNameNode in cfg).value)
        val outputPath = (resourceManaged in cfg).value / hdfsTemplate.getName
        IO.write(outputPath, config)
        outputPath
      })
    }
    resourceGenerators += hdfsConfigGenerator.taskValue
  } last
}

Seq(
  hdfsNameNode in Test := hdfsTestNameNode,
  hdfsNameNode in Compile := hdfsMainNameNode,
  addHdfsConfigGenerator(Compile),
  addHdfsConfigGenerator(Test)
)

【讨论】:

  • 我希望有一种方法,无需两次指定范围。
  • 我一直在寻找一种更加 sbt 重构的解决方案,但这同样有效。
猜你喜欢
  • 2017-09-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-03
  • 2015-09-25
  • 1970-01-01
  • 2021-01-03
  • 2012-06-11
  • 1970-01-01
相关资源
最近更新 更多