简体   繁体   English

SBT多项目建设与动态外部项目?

[英]SBT Multi-Project Build with dynamic external projects?

Let's say we have an SBT project bar with a dependency on some artifact foo : 假设我们有一个SBT项目bar ,它依赖于一些神器foo

val bar = Project('bar', file('.')).settings(    
  libraryDependencies += "com.foo" % "foo" % "1.0.0"
)

However, in certain cases, I want to checkout the source of foo and have SBT load the source from my file system instead of the published artifact; 但是,在某些情况下,我想检查foo的来源并让SBT从我的文件系统加载源而不是已发布的工件; that way, I could make local changes to foo and immediately test them with bar without having to publish anything. 这样,我可以对foo进行本地更改,并立即用bar测试它们,而不必发布任何内容。

val foo = Project('foo', file('foo'))

val bar = Project('bar', file('.')).dependsOn(foo)

We have a spec.json file in the root folder of bar that already specifies if foo should be used from source or as an artifact. 我们在bar的根文件夹中有一个spec.json文件,它已指定foo应该从源使用还是作为工件使用。 Is there any way to setup my build to read this file and add dependsOn or libraryDependencies based on the value in spec.json ? 有没有办法设置我的构建来读取此文件并根据libraryDependencies中的值添加dependsOnspec.json '

It's easy enough to do this for libraryDependencies : libraryDependencies做这个很容易:

val bar = Project('bar', file('.')).settings(    
  libraryDependencies ++= 
    if (containsFoo(baseDirectory.value / "spec.json")) {
      Seq()
    } else {
      Seq("com.foo" % "foo" % "1.0.0")
    }
)

However, we can't find any way to set do anything "dynamic" in dependsOn , such as reading the baseDirectory SettingKey . 但是,我们找不到任何设置在dependsOn做任何“动态”的方法,比如读取baseDirectory SettingKey

We tried a few approaches, but the only one we could get to work and that didn't feel like an incomprehensible/unmaintainable hack was to add an implicit class that adds a method to Project that can add a dependency either locally or as an artifact. 我们尝试了一些方法,但是我们唯一可以开始工作并且感觉不是难以理解/不可维护的黑客的方法是添加一个implicit class ,它向Project添加一个方法,可以在本地或作为工件添加依赖项。

Pseudo-code outline of the implementation: 伪代码大纲的实现:

implicit class RichProject(val project: Project) extends AnyVal {

  def withSpecDependencies(moduleIds: ModuleID*): Project = {
    // Read the spec.json file that tells us which modules are on the local file system
    val localModuleIds = loadSpec(project.base / "spec.json")

    // Partition the passed in moduleIds into those that are local and those to be downloaded as artifacts
    val (localModules, artifactModules) = moduleIds.partition(localModuleIds.contains)
    val localClasspathDependencies = toClasspathDependencies(localModules)

    project
      .dependsOn(localClasspathDependencies: _*)
      .settings(libraryDependencies ++= artifactDependencies)
  }
}

The usage pattern in an actual SBT build is pretty simple: 实际SBT构建中的使用模式非常简单:

val foo = Project("foo", file("foo")).withSpecDependencies(
  "com.foo" % "bar" % "1.0.0",
  "org.foo" % "bar" % "2.0.0"  
)

The Mecha build automation SBT plugin does this depending on whether there are other projects on the local file system. Mecha构建自动化SBT插件根据本地文件系统上是否有其他项目来执行此操作。 It's a new project, so docs are scarce, but you can take a look at its source: https://github.com/storm-enroute/mecha 这是一个新项目,因此文档很少,但您可以查看其来源: https//github.com/storm-enroute/mecha

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM