Freewind @ Thoughtworks scala java javascript dart 工具 编程实践 月结 math python english [comments admin] [feed]

(2014-09-13) 使用build.sbt配置多个子项目

广告: 云梯:翻墙vpn (省10元) 土行孙:科研用户翻墙http proxy (有优惠)

在这里将配置build.sbt来支持多个项目

目录结构

我们的项目目录是multi,然后在里面创建了两个子目录coreutil,表示将有两个子项目。

这样我们的项目中实际上有三个项目:multi, core, util.

为了方便演示,我分别在这三个项目的根目录下,各创建了一个会打出Hello的scala程序。

multi
├── build.sbt
├── HelloMulti.scala
├── core
│   └── HelloCore.scala
└── util
    └── HelloUtil.scala

HelloMulti.scala

object HelloMulti {
  def main(args: Array[String]) {
    println("Hello, multi!")
  }
}

HelloCore.scala

object HelloCore {
  def main(args: Array[String]) {
    println("Hello, core!")
  }
}

HelloUtil.scala

object HelloUtil {
  def main(args: Array[String]) {
    println("Hello, util!")
  }
}

build.sbt

name := "Multi Demo"

version := "1.0"

scalaVersion := "2.11.0"

sbtVersion := "0.13.5"

lazy val util = project

lazy val core = project

通过project就可以声明一个新的子项目。在默认情况下,它会在项目根目录下寻找与变量名同名的目录,比如coreutil

运行

projects

我们可以通过projects任务,查看该项目有多少个子项目:

$ sbt
> projects
[info] In file:/sbttest/multi/
[info]     core
[info]   * multi
[info]     util

这里列出了三个项目,其中有*的表示“当前项目”。

project

通过project可以查看当前哪个项目被设为“当前项目”。有一些任务默认对当前任务起作用,比如run

$ sbt
> project
[info] multi (in build file:/sbttest/multi/)

运行run:

$ sbt
> run
[info] Running HelloMulti
Hello, multi! 

project newproject

通过给project任务一个参数,改变“当前项目”

$ sbt
> project
[info] multi (in build file:/sbttest/multi/)
> project core
[info] Set current project to core (in build file:/sbttest/multi/)
> run
[info] Running HelloCore
Hello, core!

可以看到已经更改了当前项目,并且在run的时候,将会执行另一个scala文件

指定目录

在前面,如果我们没有指明项目目录,它会默认使用与变量名同名的目录,如:

lazy val util = project

如果我们想使用另一个目录,如my-powerful-util来表示项目util,可以写成这样:

lazy val util = project in file("my-powerful-util")

这样,util实际指向的就是my-powerful-util目录了。

组合多个项目

上面定义的coreutil项目之间,实际上是没有任何关系的。比如我想compile这两个项目,就必须分别把这两个项目设为当前项目,再依次运行compile

我们可以新建一个项目root,把它们两个组合起来:

lazy val root = (project in  file(".")).aggregate(util, core)

lazy val util = project

lazy val core = project

由于我们显式地给了根项目一个名字root,原来以目录名命名的multi就不见了:

$ sbt
> projects
[info] In file:/sbttest/multi/
[info]     core
[info]   * root
[info]     util

如果在root下执行compile,则会看到coreutil也会跟着一起编译:

$ sbt
> clean
[success] Total time: 0 s, completed 2014-9-13 16:24:06
> compile
[info] Updating {file: /sbttest/multi/}root...
[info] Updating {file: /sbttest/multi/}core...
[info] Updating {file: /sbttest/multi/}util...
[info] Resolving jline#jline;2.11 ...
[info] Done updating.
[info] Resolving org.scala-lang#scala-library;2.10.2 ...
[info] Compiling 1 Scala source to  /sbttest/multi/target/scala-2.11/classes...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Resolving org.scala-lang#scala-library;2.10.2 ...
[info] Compiling 1 Scala source to  /sbttest/multi/util/target/scala-2.10/classes...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 1 Scala source to  /sbttest/multi/core/target/scala-2.10/classes...

顺序

会在多个子项目中并行执行,并且顺序不确定

指定不同时执行的任务

在组合项目时,我们还可以指定哪些任务不会被同时执行到子项目中:

lazy val root = (project in  file(".")).aggregate(util, core)
   .settings(
     aggregate in compile := false
   )

这样,再执行compile任务,它就不会被应用到coreutil上。

$ sbt
> clean
[success] Total time: 0 s, completed 2014-9-13 16:27:29
> compile
[info] Updating {file: /sbttest/multi/}root...
[info] Resolving jline#jline;2.11 ...
[info] Done updating.
[info] Compiling 1 Scala source to  /sbttest/multi/target/scala-2.11/classes...
[success] Total time: 0 s, completed 2014-9-13 16:27:32

可以看到,只有root项目中的scala文件被编译了。

依赖于其它项目

除了上面的组合,我们还可以让一个项目依赖于另一个项目,这样就可以在这个项目中使用另一个项目中定义的类。

比如,我们让core依赖于util:

lazy val util = project

lazy val core = project.dependsOn(util)

通过.dependsOn,我们让core项目依赖于util项目,这样我们就可以在core中使用util中定义的类了。

如果我在core中执行compile任务,它会自动先到util中执行compile.

依赖多个项目

lazy val mypro = project.dependsOn(core, util)
comments powered by Disqus