将多个 sbt 任务合并为一个

Posted

技术标签:

【中文标题】将多个 sbt 任务合并为一个【英文标题】:Combine several sbt tasks into one 【发布时间】:2015-03-14 11:54:37 【问题描述】:

我对创建 Scala 任务的 Scala/SBT 文档有些困惑。目前我可以从命令行运行以下命令:

sbt ";set target := file(\"$PWD/package/deb-upstart\"); set serverLoading in Debian := com.typesafe.sbt.packager.archetypes.ServerLoader.Upstart; debian:packageBin; set target := file(\"$PWD/package/deb-systemv\"); set serverLoading in Debian := com.typesafe.sbt.packager.archtypes.ServerLoader.SystemV; debian:packageBin; set target := file(\"$PWD/package/rpm-systemd\"); rpm:packageBin"

这会将我的目标每次重置到不同的目录(deb-upstart、deb-systemv 和 rpm-systemd),并为每个设置运行一个 sbt-native-package 任务。 (是的,我意识到我正在编译它三个不同的时间;但是 sbt-native-packager 似乎没有工件目录的设置)

这在 bash 提示符下工作正常,但我一直试图将相同的目标放入 jenkins(用 $WORKSPACE 替换 $PWD),但我似乎无法正确转义引号。我认为通过 build.sbt 或 project/Build.scala 来运行所有这三个任务的任务可能更容易,每次都更改目标变量(并用完整路径替换 $PWD 或 $TARGET的基本目录)。

我尝试了以下方法:

 lazy val packageAll = taskKey[Unit]("Creates deb-upstart, deb-systenv and rpm-systemd packages")

packageAll := 
  target := baseDirectory.value / "package" / "deb-upstart"

  serverLoading in Debian := com.typesafe.sbt.packager.archetypes.ServerLoader.Upstart

  (packageBin in Debian).value

  target := baseDirectory.value / "package" / "deb-systemv"

  serverLoading in Debian := com.typesafe.sbt.packager.archetypes.ServerLoader.SystemV

  (packageBin in Debian).value

  target := baseDirectory.value / "package" / "rpm-systemd"

  (packageBin in Rpm).value


但问题是 .value 会导致任务在我的任务运行之前得到评估,因此他们没有获得新的目标设置(如另一个问题所述:How can I call another task from my SBT task?)

【问题讨论】:

我不确定,但您是否尝试将每个自定义 packageBin 步骤提取到自定义任务中,然后将它们与 packageAll 聚合?如果只更改一次输出目录,也可以使用target in Rpmtarget in Debian 设置。 @Muki 我希望我可以只是 target in [Setting] 但如果你仔细看,你会发现我为 Debian 更改了两次目标,一次用于 Upstart ServerLoader,一次用于 SystemV ServerLoader。我将如何将每个 packageBin 提取到自定义任务中? 【参考方案1】:

所以,我为您解决了这个问题 :) 正如您已经提到的,将多个任务合并到一个任务中,其中一些任务依赖于相同的设置,不会按预期工作。

相反,我们执行以下操作

    为我们的每个自定义步骤创建一个任务,例如为新贵包装 debian 定义按顺序执行这些命令的别名

定义任务

lazy val packageDebianUpstart = taskKey[File]("creates deb-upstart package")
lazy val packageDebianSystemV = taskKey[File]("creates deb-systenv package")
lazy val packageRpmSystemD = taskKey[File]("creates rpm-systenv package")

示例任务实现

实现非常简单,每个都相同 任务。

// don't forget this
import com.typesafe.sbt.packager.archetypes._

packageDebianUpstart := 
  // define where you want to put your stuff
  val output = baseDirectory.value / "package" / "deb-upstart"

  // run task
  val debianFile = (packageBin in Debian).value

  // place it where  you want
  IO.move(debianFile, output)
  output

定义别名

现在将这些任务组合成一个别名

addCommandAlias("packageAll", "; clean " + 
                          "; set serverLoading in Debian := com.typesafe.sbt.packager.archetypes.ServerLoader.SystemV" +
                          "; packageDebianSystemV " +
                          "; clean " + 
                          "; set serverLoading in Debian := com.typesafe.sbt.packager.archetypes.ServerLoader.Upstart" +
                          "; packageDebianUpstart " + 
                          "; packageRpmSystemD")

可以看完整代码here。

更新

在别名里面设置SystemLoader好像是对的 解决这个问题的方法。不幸的是,清洁是必要的 每个构建都使用相同的输出格式。

【讨论】:

此解决方案不起作用。它将包重命名为 deb-upstart 而不是将其放在目录中(我尝试在 val output 之后添加 scalax.file.Path(output).createDirectory(),但它仍然重命名包而不是将它们放在自己的目录中)。此外,如果您运行dpkg-deb -c deb-systemv,您会发现它实际上是新贵版本。 .value 在您的自定义任务之前运行这些任务。唯一的方法是使用命令。我一直在努力研究一个;如果我能弄清楚,可能会发出拉取请求。 我更新了示例。 sbt 似乎没有正确处理任务内部的设置,或者以其他方式完成。通过别名从外部设置它是可行的。该目录是为我正确创建的,它会按照描述移动文件。 IO.move(package, outputfolder).

以上是关于将多个 sbt 任务合并为一个的主要内容,如果未能解决你的问题,请参考以下文章

scala:如何在SBT设置中定义多个相关任务之间的执行顺序?

SBT:如何在多个任务中重用带有参数的代码?

sbt中多个测试包的多个jar

SBT:覆盖任务“test”的行为以仅从默认 testSource 文件夹运行测试,有多个测试源文件夹

将分组后列的多个值合并为python pandas中的一列

SBT 插件可以嵌入来自另一个插件的任务吗?