2015-06-19 39 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