SBT

时间:2015-10-17 13:56:52

标签: scala sbt

我最近被告知不要在this answer上混淆任务和命令,这让我首先意识到存在差异。在我的研究过程中,混淆甚至更多,我必须承认,我显然无法将两者分开!我认为主要的问题是术语经常被同义地使用,但概念是不同的,高度相关并且在某种程度上非常相似。 阅读文档并没有让我满意。我不想在sbt文档中明确显示问题,所以不要误解我,但我希望你能看到我目前的进展。 我在旅程中将我的问题标记为粗体,并在其前面添加了一个数字。

研究

我咨询的第一个资源是文档中的Tasks and Commands部分,它仅指向入门指南。

入门

入门指南并没有真正解释这方面的差异。 特别是Defining tasks and settings部分似乎引入了更多的混乱,其中的类型之间存在着意义; Setting[T]Setting[Task[T]]Task[T]以及密钥及其相应类型的术语。

  

据说TaskKey[T]定义任务任务compilepackage等操作。他们可能会返回Unit(单位是void的Scala),或者他们可能返回与任务相关的值,例如package是{{1}它的值是它创建的jar文件。

这有点古怪但现在还可以,因此任务TaskKey[File]个实例,其结果类型为TaskKey

  

每次启动任务执行时,例如在交互式sbt提示符下键入T,sbt将重新运行所涉及的任何任务

因此,sbt提示符下的任何任务都可用。那么命令的区别在哪里呢?在其他部分,两者似乎都是同义词,如hereMore About Settings部分进一步描述了:

  

请记住,某些设置描述了任务,因此这种方法也会在任务之间创建依赖关系。

因此,任务可能相互依赖,由设置引入。

  

插件扩展了构建定义,最常见的是添加新设置。新设置可能是新任务。例如,插件可以添加codeCoverage任务,该任务将生成测试覆盖率报告。

插件可能会使用设置引入新任务。

  

还要记住.sbt构建定义,设置在项目重新加载之前具有固定值,同时为每个“任务执行”重新计算任务(每次有人在sbt交互式提示符或批处理模式下键入命令)。

这让我觉得命令只是在sbt提示符上输入的东西,或者是使用批处理模式直接输入到终端的东西。此外,它产生了一个想法,即命令仅作为每个任务的浅前端#1每个任务都有相应的命令吗?

  

通过定义触发的插件,可以使用自动插件作为在所有子项目中注入自定义任务命令的便捷方式。

在这里,我认为命令可以单独设置 - 与任务类似。但是,Running Commands部分讨论了为命令或任务创建别名,但没有说明任务的任何内容。我觉得这些概念可能是相同的,虽然我知道两者都不同。

任务

根据Tasks页面,这是与任务有关的功能列表

  1. 通过与设置系统集成,可以像设置一样轻松灵活地添加,删除和修改任务。
  2. 输入任务使用解析器组合器来定义其参数的语法。这允许灵活的语法和制表符完成与命令相同。
  3. 任务产生价值。其他任务可以通过在任务定义中调用值来访问任务的值。
  4. 可以动态更改任务图的结构。可以根据另一个任务的结果将任务注入执行图。
  5. 有办法处理任务失败,类似于try / catch / finally。
  6. 每个任务都可以访问自己的Logger,默认情况下会以比最初打印到屏幕更详细的级别保留该任务的日志记录。
  7. 在功能之上,它进一步说:

      

    在项目加载时评估设置。任务按需执行,通常是响应用户的命令。

    好的,所以某些任务可以通过其他方式启动。

    命令

    最后,command页面说明了:

      

    “命令”看起来类似于任务:它是一个可以从sbt控制台执行的命名操作。

    所以现在我认为对来自sbt提示符或批处理的指定任务或命令的任何调用都被称为命令。无论命令是指向任务还是命令实例。 #2因此,区分定义和呼叫级别是否有意义,以减少不确定性?例如:在呼叫级别,一切都是命令,但是在定义级别,这是compileCommand实例。

    这是一段显示命令定义的一般解剖结构的代码:

    TaskKey

    因此val action: (State, T) => State = ??? val parser: State => Parser[T] = ??? val command: Command = Command("name")(parser)(action) ' s command是状态转换,使其在函数式编程方面具有高度可组合性。与此相比,作为action实例的任务更像是返回类型TaskKey[T]的结果的简单函数。功能列表中的第3点指出,任务产生的值使得我认为任务更像纯粹的函数,只产生一些小的副作用,如第6点所述的日志记录,但返回类型为{{1}的任务除外}。

      

    但是,命令的实现将构建的整个状态(由State表示)作为其参数,并计算新状态。例如,这意味着命令可以查看或修改其他sbt设置。通常,当您需要执行在常规任务中不可能执行的操作时,您将使用命令。

    所以我认为命令在某些情况下有点优越。然后我问自己:任务和命令是否共享关于任务功能列表的相同功能子集,如明显的第2点?第1点指出,由于设置系统的集成,可以对设置进行任意修改,对于命令也不是这样吗?对于第4点,第5点和第6点也是如此。#3有人可以澄清这一点,特别是限制并说明我何时应该客观地更喜欢使用命令而不是任务或(计数器)示例何时不这样做?

2 个答案:

答案 0 :(得分:3)

尽可能尝试使用任务。它们更容易理解,更容易编写。

来自文档:

  

通常情况下,当您需要在常规任务中执行某些操作时,您可以使用命令。

如果没有说明任务的局限性,那当然没有用。但我个人认为:如果你想操纵构建的state,你可以使用命令。

此示例是您希望使用不同的设置运行任务。

任务可让您访问其他设置和任务,命令还可让您访问状态并允许您操作它。然而,这是以不熟悉其他开发人员和增加复杂性为代价的。

可能存在可以将某些事物表达为任务和命令的情况。在这里,我采取选择感觉更容易的方法。

答案 1 :(得分:0)

据我所知,“Command”API有一些你不能(轻松)使用Command做的事情。 命令不返回值。因此,您无法轻松地将其他任务基于命令的结果。 可以通过将结果存储在状态中并在另一个命令(或任务)中从那里获取它来模拟它,但我不太清楚SBT是否真的可以说 - 这也是相当迂回的。

我使用命令作为排序设备 - 定义常用命令序列的快捷方式。 例如 - 将javaOptions设置为某个值 - 使用一些参数运行某个主类(可以是命令的参数) - 然后将javaOptions(设置)重置为旧值。

当然,这个排序也可以手动完成,但是命令很好地包装所有这些部分样板。