我尝试将SBT用于一个主项目A和一个子项目B.A取决于B。
我很难找到使用SBT文档的方法。无论如何,我以下面的A / project / B.scala文件结束了:
object B extends Build {
lazy val root = Project(id = "a", base = file(".")) dependsOn (b)
lazy val b = RootProject(file("../b"))
}
(我不确定Project
和RootProject
的使用是否正确,但它基本上是从命令行和Eclipse编译的。)
只要项目A在〜/ workspace / a中,项目B在〜/ workspace / b
,它在我的开发工作站上工作正常但是,我的持续集成服务器Jenkins的情况并非如此,其中A的源文件位于〜/ jobs / A / workspace中,B的源文件位于〜/ jobs / B / workspace
我最近从Maven转到了SBT,它曾经和Maven一起工作(我不记得我是怎么做到的,但我相信我实际上可以在Maven本地存储库中引用一个源目录。)
也许更多的上下文会有所帮助:B是A使用的文件格式的解析器,可能是使用相同文件格式标准的其他项目。
如何管理这种情况?
答案 0 :(得分:2)
我认为您的构建配置混合了一些不同的概念。在sbt中,具有子项目的项目意味着在文件系统中表示为唯一容器。我通常做的就是写下这些内容:
object RootBuild extends Build {
lazy val root = Project(id = "root", base = file(".")) aggregates(a, b)
lazy val a = Project(id = "a", base = file("./a"))
lazy val b = Project(id = "b", base = file("./b")) dependsOn(a)
}
聚合指示sbt在编译根时编译a和b。当您在此配置中运行sbt时,您可以按如下方式切换项目
$ sbt
> project a
切换项目后,将对该项目运行所有命令。否则,您可以为特定项目运行命令(例如,编译),而无需按以下方式切换:
$ sbt
> a/compile
甚至没有按如下方式进入sbt shell:
$ sbt 'a/compile'
在我看来,如果你想拥有一个没有公共项目容器的文件夹结构,你真的不想使用子项目,而是想让你的项目引用另一个作为依赖项。在这种情况下,假设您在git存储库中有依赖项目,您可能希望执行以下操作:
object A extends Build {
lazy val dep = RootProject(uri("git://somerepo.com/B.git"))
lazy val a = Project(id = "a", base = file("./")) dependsOn(dep)
}
在这种情况下,您将A和B管理为具有自己的构建和自己的依赖项的简单项目,并且在构建A项时依赖sbt来获取和构建B项目。
我肯定知道这适用于git和github,可能sbt也支持其他类型的SCM甚至档案,请查看sbt docs以获取更多信息。
答案 1 :(得分:1)
答案与@AldoStracquadanio已经发布的答案非常相似,但只利用build.sbt
(而不是project/*.scala
文件)中的多项目定义{{3} }。
期望是(我从问题和评论中收集了它们并引用而没有更改):
使用它们,这是我的解决方案 - 使用一个目录作为顶级根项目,包含两个子项目 - a
和b
。
jacek:~/sandbox/so/multi-0.13.1
$ tree
.
├── a
├── b
├── build.sbt
└── project
└── build.properties
3 directories, 2 files
a
和b
现在是空目录,它们将成为子项目的主目录。
build.sbt
如下:
scalaVersion := "2.10.4-RC1"
lazy val root = project in file(".") aggregate (a, b)
lazy val a = project dependsOn b
lazy val b = project
这解决了需求#1和#4,因为项目是独立的,可以在他们自己的build.sbt
中进行配置。
project/build.properties
如下:
sbt.version=0.13.1
当你启动sbt shell时,最终得到3个项目 - root
,a
和b
,tree
命令的输出显示{{1}之间的依赖关系}和root
与a
一样好。它们由b
项目聚合,项目中执行的任何任务都会传播到root
和a
。
由于b
取决于a
,所以任务的执行顺序将从 - b
开始,以b
结束。您可以使用a
自行查看show [task]
:
compile
通过设置,任何针对项目[root]> show compile
[info] Updating {file:/Users/jacek/sandbox/so/multi-0.13.1/}b...
[info] Resolving org.scala-lang#scala-library;2.10.3 ...
[info] Updating {file:/Users/jacek/sandbox/so/multi-0.13.1/}root...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Resolving org.scala-lang#scala-library;2.10.4-RC1 ...
[info] Updating {file:/Users/jacek/sandbox/so/multi-0.13.1/}a...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] a/compile:compile
[info] Analysis:
[info] b/compile:compile
[info] Analysis:
[info] root/compile:compile
[info] Analysis:
[success] Total time: 4 s, completed Jan 4, 2014 6:23:10 PM
执行的任务/命令都会注意到项目b
中的任何更改,因为a
取决于a
。这解决了要求#3和#6。
Jenkins也应该适应新的项目布局,因为它会将项目从SCM存储库作为单个项目下拉,并针对顶级b
项目执行必要的命令将它们传播到子项目,root
首先跟随b
。这解决了要求#2和#5。
您可以改为使用系统属性指向相关项目a
和a
的不同位置,但我认为这只会使配置复杂化。