其他答案非常适合这个问题,但我认为 OP 也可能从我的问题中受益 :)
OP 询问了 “我想定义一个非常简单的任务,当我在 sbt 中输入 generate 时,将调用我的 my.App.main(..) 方法来生成一些东西。” 这最终可能会使构建。
Sbt 已经提供了一种在构建时生成文件的方法 - sourceGenerators 和 resourceGenerators - 在阅读了这个问题之后,我似乎没有注意到需要为此定义一个单独的任务。
在Generating files(见the future version of the document in the commit)你可以阅读:
sbt 为添加源或资源生成提供标准钩子
任务。
根据知识可以想到以下解决方案:
sourceGenerators in Compile += Def.task {
my.App.main(Array()) // it's not going to work without one change, though
Seq[File]() // a workaround before the above change is in effect
}.taskValue
要完成这项工作,您应该返回一个包含生成文件的Seq[File](而不是空的Seq[File]())。
代码工作的主要变化是将my.App 类移动到project 文件夹。然后它成为构建定义的一部分。它还反映了类的作用,因为它实际上是构建的一部分,而不是它的产物。当相同的代码是构建和工件本身的一部分时,您不会将不同的关注点分开。如果 my.App 类参与构建,它应该属于它 - 因此移动到 project 文件夹。
项目的布局如下:
$ tree
.
├── build.sbt
└── project
├── App.scala
└── build.properties
关注点分离(又名@joescii in da haus)
@joescii 的答案中有一点(我在答案中进行了扩展)-“使其成为其他项目可以使用的单独项目。为此,您需要将您的 App 对象放入一个单独的项目并将其作为依赖项包含在project/project"中,即
假设您有一个单独的项目build-utils,App.scala 在src/main/scala 下。这是一个只有 Scala 代码的常规 sbt 配置。
jacek:~/sandbox/so/generate-project-code
$ tree build-utils/
build-utils/
└── src
└── main
└── scala
└── App.scala
您可以将其作为常规 Scala 应用程序进行测试,而不会弄乱 sbt。不需要额外的设置(并且让您从有时可能有益的 sbt 中解放出来 - 较少的设置总是有帮助的)。
在另一个项目 - project-code - 使用 App.scala 应该是构建的基础,build.sbt 如下:
项目代码/build.sbt
lazy val generate = taskKey[Unit]("Generate my file")
generate := {
my.App.main(Array())
}
现在最重要的部分 - 项目之间的连接,因此 App 代码对于 project-code 的构建是可见的:
project-code/project/build.sbt
lazy val buildUtils = RootProject(
uri("file:/Users/jacek/sandbox/so/generate-project-code/build-utils")
)
lazy val plugins = project in file(".") dependsOn buildUtils
使用构建定义,执行generate 会为您提供以下信息:
jacek:~/sandbox/so/generate-project-code/project-code
$ sbt
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Loading project definition from /Users/jacek/sandbox/so/generate-project-code/project-code/project
[info] Updating {file:/Users/jacek/sandbox/so/generate-project-code/build-utils/}build-utils...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Updating {file:/Users/jacek/sandbox/so/generate-project-code/project-code/project/}plugins...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 1 Scala source to /Users/jacek/sandbox/so/generate-project-code/build-utils/target/scala-2.10/classes...
[info] Set current project to project-code (in build file:/Users/jacek/sandbox/so/generate-project-code/project-code/)
> generate
Hello from App.main
[success] Total time: 0 s, completed May 2, 2014 2:54:29 PM
我已将App 的代码更改为:
> eval "cat ../build-utils/src/main/scala/App.scala"!
package my
object App {
def main(args: Array[String]) {
println("Hello from App.main")
}
}
项目结构如下:
jacek:~/sandbox/so/generate-project-code/project-code
$ tree
.
├── build.sbt
└── project
├── build.properties
└── build.sbt
其他变化也就是好东西
我还建议对源代码生成器的代码进行一些其他更改:
- 将代码从
main 方法移到一个单独的方法,该方法返回生成的文件并让main 调用它。这将使重用 sourceGenerators 中的代码更容易(无需不必要的 Array() 调用它以及显式返回文件)。
- 对
convert 使用filter 或map 函数(以增加功能性)。