我想创建一个与默认配置相同的编译配置,但添加了一个编译器插件。在我的特殊情况下,我希望有一个" dev"配置,但使用linter插件(https://github.com/HairyFotr/linter),因为它减慢了编译时间,并且不需要在生产或持续集成中运行它。
现在这就是我的尝试:
lazy val Dev = config("dev") extend Compile
lazy val root = (project in file(".")).configs(Dev).settings(
inConfig(Dev)(addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1.12")): _*)
并且 应该工作,因为当我inspect dev:libraryDependencies
时,它是我所期望的 - 它有org.psywerx.hairyfotr:linter:0.1.12:plugin->default(compile)
。通常,如果我使用"插件添加库#34;范围,它适用于默认设置:
libraryDependencies += ("org.psywerx.hairyfotr" %% "linter" % "0.1.12" % "plugin"
如果我在不同的配置下添加它,它就不起作用,所以这里肯定会有其他的东西。
答案 0 :(得分:2)
这解决了这个问题,但并没有完全按照问题的方式解决。这是完整的build.sbt
:
libraryDependencies ++= Seq(
"org.psywerx.hairyfotr" %% "linter" % "0.1.14" % "test")
val linter = Command.command("linter")(state => {
val linterJar = for {
(newState, result) <- Project.runTask(fullClasspath in Test, state)
cp <- result.toEither.right.toOption
linter <- cp.find(
_.get(moduleID.key).exists(mId =>
mId.organization == "org.psywerx.hairyfotr" &&
mId.name == "linter_2.11"))
} yield linter.data.absolutePath
val res = Project.runTask(scalacOptions, state)
res match {
case Some((newState, result)) =>
result.toEither.right.foreach { defaultScalacOptions =>
Project.runTask(compile in Test,
Project.extract(state).append(
scalacOptions := defaultScalacOptions ++ linterJar.map(p => Seq(s"-Xplugin:$p")).getOrElse(Seq.empty),
newState))
}
case None => sys.error("Couldn't get defaultScalacOptions")
}
state
})
lazy val root = (project in file(".")).configs(Test).settings(commands ++= Seq(linter))
您返回未修改状态的事实意味着您不会更改项目设置。因此,如果您运行sbt linter
,则应使用其他scalacOptions
编译项目,但如果您在同一个sbt会话中运行compile
,则不会使用这些其他设置。
这里棘手的问题是scalacOptions
实际上是TaskKey
,而不是SettingKey
。我不知道为什么会这样,但为了获得它的价值,你必须完成这项任务。一个原因可能是,在sbt中,您无法根据任务进行设置,但您可以根据任务创建任务。换句话说,scalacOptions
可以依赖于其他任务值,也可能在内部确实,我还没有检查过。如果当前的答案对您有用,我可以尝试考虑更优雅的方法来实现相同的结果。
编辑:修改了代码,为linter插件指定了scalacOptions
。请注意,该插件必须是托管依赖项,而不仅仅是下载的jar,才能使此解决方案正常工作。如果你想让它不受管理,那就是一种方式,但我现在还没有进入它。此外,为了便于说明,我还自由地将其用于测试代码。
答案 1 :(得分:1)
在源代码中查看Defaults.scala,似乎编译命令始终从编译范围中获取选项。所以,如果我是正确的,你只能有一组编译选项!
这似乎可以通过scalacOptions
表现相同的事实得到证实,这也是为什么我没有看到这些类似问题的非黑客答案的原因:
我很高兴被证明是错的。
编辑:FWIW,可能无法在同一个项目中定义另一个scalac选项配置文件,但您可以在&#34;不同的&#中执行此操作 34;项目:
lazy val dev = (project in file(".")).
settings(target := baseDirectory.value / "target" / "dev").
settings(addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1.12"): _*)
这样做的缺点是它有一个单独的输出目录,因此需要更多空间,更重要的是,不会在两个项目之间进行增量编译。然而,在花了一些时间思考它之后,这可能是设计上的。毕竟,即使直径不足,一些scalac编译选项也可以想象地改变输出。这会使尝试将增量编译的元数据从一组scalac选项保留到另一组scalac选项变得毫无意义。因此,不同的scalac选项确实需要不同的目标目录。