範圍在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:targetExample
是List(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時都會自動調用該命令。
但是它對我來說似乎太髒了,所以我很好奇,如果有更優美的方式來實現類似的語義。
如果還有更多設置,我應該怎麼做?可以使用'libraryDependencies'作爲例子。它不是每個任務定義的,因爲它太麻煩,並且實現了自定義推理機制。這是'%test'依賴性定義的一部分。 – ayvango
@ayvango我不確定我是否正確地得到它,但你可以添加不作爲範圍的設置作爲另一個'lazy val',並將其添加到'settings',而不通過'inConfig'方法進行範圍設置。但是,如果你在'basePluginSettings'中定義它,我想它也可以工作,你只是不要在配置中覆蓋它 – lpiepiora