2014-06-04 70 views
0

范围在sbt中很重要。我完全没问题。但也有一些委托规则允许您构建设置的分层结构。我想用它来为更具体的规则带来额外的设置。为什么测试范围设置不能保持正确的值?

import sbt._ 
import Keys._ 

object TestBuild extends Build { 
    val sourceExample = settingKey[Seq[String]]("example source for setting dependency") 
    val targetExample = settingKey[Seq[String]]("example of a dependent setting") 

    override lazy val settings = super.settings ++ Seq (
    sourceExample := Seq("base"), 
    targetExample := "extended" +: sourceExample.value, 
    sourceExample in Test += "testing" 
) 
} 

的例子给了我意想不到的输出:

> show compile:sourceExample 
[info] List(base) 
> show test:sourceExample 
[info] List(base, testing) 
> show compile:targetExample 
[info] List(extended, base) 
> show test:targetExample 
[info] List(extended, base) 

我希望test:targetExampleList(extended, base, testing)List(extended, base)。一旦我得到结果,我立即找出它为什么如图所示工作。 test:targetExample代表来自*:targetExample的计算值,但不是用于在嵌套范围内计算它的规则。

这种行为给我编写自己的插件带来了两个困难。我有额外的工作来在每个范围内定义与插件开发人员相同的规则。我必须记住内部任务的范围定义以正确使用它作为用户。

我该如何克服这种不便?我想介绍的调用设置的语义,而不是的调用值。什么技巧可以为它工作?

P.S. libraryDependencies in Test看起来更简洁,使用% test


我应该清楚地知道,我完全理解sbt派生值,就像它在文档中描述的一样。它的工作原理就是让它工作。

但是我为什么要服从规则?我看到他们完全违反直觉。 Sbt引入了继承语义,它不同于以前如何定义继承。当你写

trait A { lazy val x : Int = 5 } 
trait B extends A { lazy val y : Int = x * 2} 
trait C extends A { override lazy val x : Int = 3 } 

你期望(new B with C).y是6,不知道10,这将是真正10可让您正确使用这种继承的,但离开你的欲望寻找实现继承的更多常规手段。您甚至可以根据name->value字典编写自己的实现。根据编程的第十个规则,你可以继续进行。

因此,我正在寻找一种能够根据常见语言实现继承语义的黑客攻击。作为一个起点,我可能会建议编写command来扫描所有设置并明确将它们从父母推送到孩子。而且每次运行sbt时都会自动调用该命令。

但是它对我来说似乎太脏了,所以我很好奇,如果有更优美的方式来实现类似的语义。

回答

0

的原因“不正确”值是targetExampleCompile范围取决于sourceExample为:

targetExample := "extended" +: sourceExample.value 

它应该使用sourceExample值从Test范围,使用in Test要明确你的愿望如下:

targetExample := "extended" +: (sourceExample in Test).value 

使用inspect知道依赖关系链。

顺便说一句,我强烈建议使用build.sbt文件这样一个简单的构建定义。

0

您可以使用默认设置,并按照Plugins Best Practices - Playing nice with configurations中所述的不同配置重新使用它。我相信,这应该会给你一种类似于你所寻找的语义。

您可以定义您的基本设置并在不同的配置中重复使用它。

import sbt._ 
import Keys._ 

object TestBuild extends Build { 

    val sourceExample = settingKey[Seq[String]]("example source for setting dependency") 
    val targetExample = settingKey[Seq[String]]("example of a dependent setting") 

    override lazy val settings = super.settings ++ 
    inConfig(Compile)(basePluginSettings) ++ 
    inConfig(Test)(basePluginSettings ++ Seq(
     sourceExample += "testing" // we are already "in Test" here 
    )) 

    lazy val basePluginSettings: Seq[Setting[_]] = Seq (
    sourceExample := Seq("base"), 
    targetExample := "extended" +: sourceExample.value 
) 

} 

PS。既然你正在谈论编写你的插件,你可能还想看看编写插件的新方法,即AutoPlugin,因为旧机制现在是deprecated

+0

如果还有更多设置,我应该怎么做?可以使用'libraryDependencies'作为例子。它不是每个任务定义的,因为它太麻烦,并且实现了自定义推理机制。这是'%test'依赖性定义的一部分。 – ayvango

+0

@ayvango我不确定我是否正确地得到它,但你可以添加不作为范围的设置作为另一个'lazy val',并将其添加到'settings',而不通过'inConfig'方法进行范围设置。但是,如果你在'basePluginSettings'中定义它,我想它也可以工作,你只是不要在配置中覆盖它 – lpiepiora

相关问题