2014-06-04 68 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

相關問題