如何在 SBT 中的 onLoad 挂钩上应用设置更改?
How can I apply setting changes on onLoad hook in SBT?
我在 SBT 中有一些设置,我需要在加载的插件执行一些副作用后生成值。 onLoad
挂钩似乎是执行此操作的最佳位置。钩子收到一个 State
,将其转换并 returns 一个新的。使用 State
方法调度命令很容易,但更改设置似乎并不容易。
我首先尝试了以下代码,它失败了,因为它似乎导致对 onLoad
的递归调用,并且由于重复的参与者名称(可能是递归的产物)而失败。
onLoad in Global := (onLoad in Global).value andThen { state =>
val settings = generateMySettings
Project.extract(state).append(settings, state)
}
我看到的另一种选择是直接调用 State
中的 put
或 update
方法,但这看起来很丑陋且容易出错。有better/cleaner方法吗?
在 github sbt repo 的 onLoad 挂钩中有一个如何 "rewire" 项目设置的好例子:https://github.com/sbt/sbt-community-plugins/blob/master/project/Dependencies.scala
我不确定为什么 onLoad 挂钩可能会被执行多次,但您的问题的解决方案是简单地定义一个布尔标志属性,以便在标志未被触发时有条件地仅调用您的挂钩一次然而。
在提到的例子中,他们就是这样做的,
trait GenerateMySettingsStartup extends Build {
private lazy val generated = AttributeKey[Boolean]("my-settings-generated")
def generateCommandName = "generate-my-settings"
private final def fixState(state: State): State =
if(state.get(generated) getOrElse false) {
state
} else {
// >>> generate and append your settings here <<<
state.put(generated, true)
}
private def initialize = Command.command(generateCommandName)(fixState(_))
final def generateSettings: Seq[Setting[_]] = Seq(
commands += initialize,
// initialize onLoad task if not yet defined
onLoad in Global <<= (onLoad in Global) ?? idFun[State],
// append generateCommandName onLoad handler
onLoad in Global <<= (onLoad in Global) apply ( _ andThen (generateCommandName :: _))
)
}
然后只需将 GenerateMySettingsStartup#generateSettings 应用到您的项目设置。
P.S。不确定我是否完全正确,但在这里我认为 onLoad 挂钩是通过 Command 定义的,因为它可以访问可能未在某些范围内定义的状态,这只是一个疯狂的猜测所以如果我的假设是错误的请澄清我,谢谢!
我在 SBT 中有一些设置,我需要在加载的插件执行一些副作用后生成值。 onLoad
挂钩似乎是执行此操作的最佳位置。钩子收到一个 State
,将其转换并 returns 一个新的。使用 State
方法调度命令很容易,但更改设置似乎并不容易。
我首先尝试了以下代码,它失败了,因为它似乎导致对 onLoad
的递归调用,并且由于重复的参与者名称(可能是递归的产物)而失败。
onLoad in Global := (onLoad in Global).value andThen { state =>
val settings = generateMySettings
Project.extract(state).append(settings, state)
}
我看到的另一种选择是直接调用 State
中的 put
或 update
方法,但这看起来很丑陋且容易出错。有better/cleaner方法吗?
在 github sbt repo 的 onLoad 挂钩中有一个如何 "rewire" 项目设置的好例子:https://github.com/sbt/sbt-community-plugins/blob/master/project/Dependencies.scala
我不确定为什么 onLoad 挂钩可能会被执行多次,但您的问题的解决方案是简单地定义一个布尔标志属性,以便在标志未被触发时有条件地仅调用您的挂钩一次然而。
在提到的例子中,他们就是这样做的,
trait GenerateMySettingsStartup extends Build {
private lazy val generated = AttributeKey[Boolean]("my-settings-generated")
def generateCommandName = "generate-my-settings"
private final def fixState(state: State): State =
if(state.get(generated) getOrElse false) {
state
} else {
// >>> generate and append your settings here <<<
state.put(generated, true)
}
private def initialize = Command.command(generateCommandName)(fixState(_))
final def generateSettings: Seq[Setting[_]] = Seq(
commands += initialize,
// initialize onLoad task if not yet defined
onLoad in Global <<= (onLoad in Global) ?? idFun[State],
// append generateCommandName onLoad handler
onLoad in Global <<= (onLoad in Global) apply ( _ andThen (generateCommandName :: _))
)
}
然后只需将 GenerateMySettingsStartup#generateSettings 应用到您的项目设置。
P.S。不确定我是否完全正确,但在这里我认为 onLoad 挂钩是通过 Command 定义的,因为它可以访问可能未在某些范围内定义的状态,这只是一个疯狂的猜测所以如果我的假设是错误的请澄清我,谢谢!