我正在尝试使用插件范围内的任务编写插件(例如:“my-plugin:update”)。 这是我的示例代码(sbt 0.13.0):
import sbt._
import Keys._
object MyPlugin extends Plugin
{
lazy val conf = config("my-plugin")
val update = taskKey[Unit]("Wow!.") in conf
override lazy val settings = inConfig(conf)(Seq(
update := println("wow")
))
}
但是当我尝试使用这个插件时,我收到了这个错误:
检测到的AttributeKey ID冲突:'update'(sbt.Task [Unit], sbt.Task [sbt.UpdateReport])
是否可以在没有冲突的情况下在插件范围内定义任务?
答案 0 :(得分:4)
快速回答您的问题是,您无法定义名为"update"
的任务键。
要解决此问题,那些参与Plugin namespacing: A good solution?合着Plugins Best Practices的人今天仍然站着。请参阅Avoid namespace clashes部分:
避免命名空间冲突
有时,您需要一个新密钥,因为没有现有的sbt密钥。在这种情况下,请在sbt命名空间和Scala val中使用的(字符串)键名中使用特定于插件的前缀。有两种可行的方法可以实现这一目标。
只需使用val前缀
package sbtobfuscate object Plugin extends sbt.Plugin { val obfuscateStylesheet = settingKey[File]("Obfuscate stylesheet") }
在这种方法中,每个val都以混淆开始。该插件的用户将参考如下设置:
obfuscateStylesheet := ...
使用嵌套对象
package sbtobfuscate object Plugin extends sbt.Plugin { object ObfuscateKeys { val stylesheet = SettingKey[File]("obfuscateStylesheet") } }
在此方法中,所有非常见设置都在嵌套对象中。一个 该插件的用户将参考如下设置:
import ObfuscateKeys._ // place this at the top of build.sbt stylesheet := ...
我认为选择取决于您的偏好以及您要定义的键数。对于sbt-buildinfo,我选择使用"只需使用val前缀"为了简单起见,但对于我已经去过的任何其他插件"使用嵌套对象"方法包括sbt-assembly。
有关详细信息,另请参阅主题Mark's post:
1:3。相关,配置是错误的轴分组设置 插入。使用插件的主要任务(例如' assembly')来执行此操作。 否则,每个项目我只能轻松使用一次插件。这个 某些插件可能没问题,但这是不必要的限制。
1:4。范围不是命名空间。对于任何给定的密钥名称,只能 是一种类型。也就是说,你不能拥有:
SettingKey[Int]("value")
和
SettingKey[Double]("value")
将密钥放在嵌套对象中只有在拥有密钥时才有用 密钥/类型由两个不同的插件定义,因此在Scala中 标识符级别,它是不明确的:
object A extends Plugin { val a = SettingKey[Int]("a") } object B extends Plugin { val a = SettingKey[Int]("a") } // ambiguous in a build.sbt a := 3
正确的解决方案是:a)重用内置密钥和b)定义a 公共密钥库。键是设置的接口 系统。