我一直在寻找这种情况是否有可能暂时没有成功。
使用SBT,您是否可以通过编程方式创建子项目,而无需将每个项目明确分配给它自己的val
?
我目前的项目结构如下所示:
root/
common/ <--- This is another sub-project that others dependOn
project/
build.scala
src/main/scala
apps/ <--- sub-projects live here
Sub1/
Sub2/
Sub1
和Sub2
都是他们自己的SBT项目。
我首次将这些项目链接在一起的尝试如下:
// root/project/build.scala
import sbt._
import Keys._
object build extends Build {
lazy val common = project /* Pseudo-code */
val names = List("Sub1", "Sub2")
lazy val deps = names map { name =>
Project(id = name, base = file(s"apps/$name")).dependsOn(common)
}
lazy val finalDeps = common :: deps
lazy val root = project.in(file(".")).aggregate(finalDeps.map(sbt.Project.projectToRef) :_*)
.dependsOn(finalDeps.map(ClassPathDependency(_, None)) :_*)
}
但是,由于SBT使用反射来构建它的项目和子项目,这不起作用。
仅在明确说明每个子项目时才有效:
lazy val Sub1 = project.in(file("apps/Sub1"))
所以问题是:
有没有办法在SBT中以编程方式构建子项目依赖项?
答案 0 :(得分:2)
Sbt允许为构建本身制作构建定义:
http://www.scala-sbt.org/release/docs/Getting-Started/Full-Def.html
您可以尝试创建包含源生成器的project / project / build.scala文件,如下所示:
// project/project/build.scala
sourceGenerators in Compile <+= sourceManaged in Compile map { out =>
Generator.generate(out / "generated")
}
编辑:您应该自己实现Generator对象。
此源生成器将依次扫描最顶层的apps文件夹,并为包含所有子项目的对象创建源。
// project/subprojects.scala
// This is autogenerated from the source generator
object Subprojects{
lazy val Sub1 = project.in(file("apps/Sub1"))
lazy val Sub2 = project.in(file("apps/Sub2"))
lazy val all = Seq(Sub1,Sub2)
}
现在在你的main build.scala中写一下:
// project/build.scala
lazy val root = project.in(file("."))
.aggregate(Subprojects.all.map(sbt.Project.projectToRef) :_*)
.dependsOn(Subprojects.all.map(ClassPathDependency(_, None)) :_*)
我没有通过编译器运行所有这些,所以有些错误是可能的,但原则应该有效。
编辑:我在Github上创建了一个repo,我在那里实现了解决方案。去那里看看它是如何完成的。