如何管理SBT中的可变子项目位置?

时间:2014-01-01 14:22:55

标签: jenkins sbt

我尝试将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"))
}

(我不确定ProjectRootProject的使用是否正确,但它基本上是从命令行和Eclipse编译的。)

只要项目A在〜/ workspace / a中,项目B在〜/ workspace / b

,它在我的开发工作站上工作正常

但是,我的持续集成服务器Jenkins的情况并非如此,其中A的源文件位于〜/ jobs / A / workspace中,B的源文件位于〜/ jobs / B / workspace

我最近从Maven转到了SBT,它曾经和Maven一起工作(我不记得我是怎么做到的,但我相信我实际上可以在Maven本地存储库中引用一个源目录。)

也许更多的上下文会有所帮助:B是A使用的文件格式的解析器,可能是使用相同文件格式标准的其他项目。

如何管理这种情况?

2 个答案:

答案 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} }。

期望是(我从问题和评论中收集了它们并引用而没有更改):

  1. “我尝试将SBT与一个主项目A和一个子项目B一起使用.A依赖于B”“B是一个解析器,用于以下文件格式: A,以及可能使用相同文件格式标准的其他项目。“
  2. “我的持续集成服务器Jenkins不是这种情况”
  3. “我主要在做B,但我想从A进行大部分测试(包括测试B的API的可用性)”
  4. “B应单独打包和分发(如果可能,包括源代码)”
  5. “也许可以在同一个存储库中收集这两个项目。”
  6. “如果我在B中执行代码更改,A将不会注意到它”
  7. 使用它们,这是我的解决方案 - 使用一个目录作为顶级根项目,包含两个子项目 - ab

    jacek:~/sandbox/so/multi-0.13.1
    $ tree
    .
    ├── a
    ├── b
    ├── build.sbt
    └── project
        └── build.properties
    
    3 directories, 2 files
    

    ab现在是空目录,它们将成为子项目的主目录。

    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个项目 - rootabtree命令的输出显示{{1}之间的依赖关系}和roota一样好。它们由b项目聚合,项目中执行的任何任务都会传播到roota

    由于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。

    您可以改为使用系统属性指向相关项目aa的不同位置,但我认为这只会使配置复杂化。