2015-06-19 41 views
8

我想发明一个系统到动态发现子项目并将它们自动聚合到我的项目中。或者至少配置这个不知何故。sbt:子项目的动态聚合

要做到这一点,我打算有一个“模块”文件夹或可选配置文件包含模块的路径。

在任何情况下我需要通过子文件夹环路(或环路通过从配置文件路径的列表),并聚集各子项目。我不知道该怎么做。

目前我正在建立Play框架与build.sbt文件。我需要添加这样的循环:

name := "mysite" 
version := "1.0" 
scalaVersion := "2.11.1" 
lazy val root = (project in file(".")).enablePlugins(PlayJava) 
//pseudocode: 
foreach(folder in the 'modules' folder) { 
    lazy val module = (project in file(folder)).enablePlugins(PlayJava) 
    root = root.dependsOn(module).aggregate(module) 
} 

有没有办法做到这一点?

编辑3: 这里的代码几乎工作:

object MyBuild extends Build { 
    name := "mysite" 
    version := "1.0" 
    scalaVersion := "2.11.6" 

    var m = new File("modules") 
    var list = Seq[ProjectReference]() 
    var deps = Seq[ClasspathDependency]() 
    if (m.exists) { 
    val subs = m.listFiles.filter (_.isDirectory).foreach { folder => 
     var modulePath = new File("modules", folder.getName) 
     println("Found module " + modulePath) 
     lazy val module:ProjectRef = ProjectRef(modulePath,folder.getName) 
     lazy val dep:ClasspathDependency = ClasspathDependency(module, None) 
     list = list :+ module 
     deps = deps :+ dep 
    } 
    } 

    lazy val root = Project(id = "mysite", base = file(".")).enablePlugins(PlayJava).aggregate(list:_*).dependsOn(deps:_*) 
} 

编辑4:下面

见戴尔Wijnand的解决方案。

关于错误:RuntimeException: No project 'myModule' in 'file:/Users/me/mysite/modules/myModule'。我解决了这个使用该解决方案从https://stackoverflow.com/a/28820578

+0

'println(“Found module”+ folder.getName)''的输出是什么? – Peanut

+0

这是“Found module foo”(我的模块文件夹名为“foo”)。看来,r.depends(模块)失败。它可能不是一个Project对象。因为某些原因。 – Emmanuel

回答

2

这里:

项目/ Build.scala

import sbt._ 
import sbt.Keys._ 

import play.sbt._ 
import play.sbt.Play.autoImport._ 

object Build extends Build { 
    val commonSettings: Seq[Setting[_]] = Seq(
    scalaVersion := "2.11.7" 
) 

    lazy val modules = (file("modules") * DirectoryFilter).get.map { dir => 
    Project(dir.getName, dir).enablePlugins(PlayJava).settings(commonSettings: _*) 
    } 

    lazy val root = (project in file(".")) 
    .enablePlugins(PlayJava) 
    .settings(
     name := "mysite", 
     version := "1.0" 
    ) 
    .settings(commonSettings: _*) 
    .dependsOn(modules map (m => m: ClasspathDependency): _*) 
    .aggregate(modules map (m => m: ProjectReference): _*) 

    override lazy val projects = root +: modules 
} 

注意事项,确保模块目录不还含有build.sbt文件定义他们为项目,这将导致混乱RuntimeException: No project 'x' in 'file:/x'类型例外情况,请参阅Can't use sbt 0.13.7 with Play subprojects

+0

这是迄今为止最完整的解决方案。但我仍然遇到同样的错误:RuntimeException:'file:/ Users/me/mysite/modules/myModule'中没有项目'myModule'。任何想法为什么会这样? – Emmanuel

+0

注意:子项目本身可以自行编译。 – Emmanuel

+0

我懂了!解决方案在这里:http://stackoverflow.com/a/28820578基本上,项目的根定义在主构建和子项目构建中是重复的。解决方案是删除build.sbt中的子项目的根项目定义。 // lazy val root = ... – Emmanuel

0

你可以尝试这样的事情:

import sbt._ 
import sbt.Keys._ 

import play.sbt._ 
import play.sbt.Play.autoImport._ 

object Build extends Build { 

    lazy val modules = (file("modules") * DirectoryFilter).get.map { dir => 
    Project(dir.getName, dir).enablePlugins(PlayJava) 
    } 

    lazy val root = (project in file(".")) 
    .enablePlugins(PlayJava) 
    .settings(
     name := "mysite", 
     version := "1.0" 
    ) 
    .dependsOn(modules map (m => m: ClasspathDependency): _*) 
    .aggregate(modules map (m => m: ProjectReference): _*) 

    override lazy val projects = root +: modules 
} 

注:通过戴尔的回答启发,但我不得不删除“commonSettings”,否则它不会为我工作。

+0

我试过类似的东西。但root = root.dependsOn()不起作用;该val是不可变的。我得到一个“重新分配val”的错误。我是斯卡拉的新手,所以请握住我的手。 – Emmanuel

+0

解决方案是使根为“var”而不是“val”。现在我有一些工作正在进行,但我遇到了一个不同的问题。看到我上面更新的代码。 – Emmanuel

+0

对不起,我迷失在这个代码中。我不知道“t”和“r”是什么。 – Emmanuel