多项目build.sbt中自定义sbt插件任务执行异常及检测问题
sbt自定义插件任务在所有项目执行的原因及类型安全判断方案
一、任务在所有项目执行的原因及解决方法
原因
- 插件自动启用规则:你的插件设置了
override def trigger = allRequirements,同时requires = empty。sbt中allRequirements触发器表示当所有依赖的插件都已启用时自动启用当前插件,由于requires为空,这个条件会始终满足,导致插件被自动应用到所有项目,哪怕你只在client项目显式调用了enablePlugins(MyPlugin)。 - sbt任务执行逻辑:当你在根项目执行
sbt myTask时,sbt默认会遍历所有聚合的项目,只要项目中存在该任务的定义(由于插件的autoImport将myTask全局暴露,所有项目都能识别这个任务键),就会执行该任务。
解决方法
修改插件的触发器为noTrigger,这样只有显式调用enablePlugins(MyPlugin)的项目才会启用插件并应用任务定义:
object MyPlugin extends AutoPlugin { // ... 其他代码不变 override def trigger = noTrigger // ... 其他代码不变 }
修改后,root和core项目不会启用插件,也就不会有myTask的自定义实现。如果要确保只在client项目执行任务,也可以直接执行命令:
sbt client/myTask
二、类型安全判断插件是否启用的方案
直接解析thisProject.value.plugins的字符串确实不够类型安全,你可以通过自定义设置键来标记插件状态:
步骤1:在插件的autoImport中添加设置键
object autoImport { val myTask = taskKey[Unit]("Do something.") val myPluginEnabled = settingKey[Boolean]("标记MyPlugin是否已启用") }
步骤2:在插件的projectSettings中设置该标记
override lazy val projectSettings = Seq( myPluginEnabled := true, myTask := { if (myPluginEnabled.value) { println(s"project: ${thisProject.value.id} MyPlugin已启用") } } )
步骤3:设置全局默认值(可选)
如果需要在未启用插件的项目中也能读取myPluginEnabled,可以在插件中添加全局设置:
override lazy val globalSettings = Seq( myPluginEnabled := false )
这样,你就能在任务中通过myPluginEnabled.value类型安全地判断插件是否在当前项目启用,无需解析字符串。
内容的提问来源于stack exchange,提问作者user1460067
相关产品推荐
相关产品推荐

