我可以使用sbt的`apiMappings`设置来管理依赖项吗?

时间:2013-11-05 10:32:42

标签: sbt scaladoc

我想用sbt生成的ScalaDoc链接到外部库,在sbt 0.13中我们有autoAPIMappings,它应该为声明它们apiURL的库添加这些链接。但实际上,我使用的库中没有一个在他们的pom / ivy元数据中提供这个,我怀疑其中一些库永远不会这样做。

apiMappings设置应该只是帮助,但它被输入Map[File, URL],因此适合为非托管依赖项设置doc url。托管依赖项被声明为sbt.ModuleID的实例,无法直接插入该映射中。

我可以以某种方式使用将URL与托管依赖关系相关联的内容填充apiMappings设置吗?

一个相关的问题是:sbt是否提供了从File获取ModuleID的惯用方法?我想我可以尝试评估一些类路径并返回File来尝试将它们映射到ModuleID,但我希望有更简单的东西。

注意:这与https://stackoverflow.com/questions/18747265/sbt-scaladoc-configuration-for-the-standard-library/18747266有关,但该问题因链接标准库的scaladoc而异,其中有一个众所周知的File scalaInstance.value.libraryJar,而不是在这种情况下的情况。

3 个答案:

答案 0 :(得分:3)

我设法通过执行以下操作来引用scalaz并进行播放:

apiMappings ++= {
  val cp: Seq[Attributed[File]] = (fullClasspath in Compile).value
  def findManagedDependency(organization: String, name: String): File = {
    ( for {
        entry <- cp
        module <- entry.get(moduleID.key)
        if module.organization == organization
        if module.name.startsWith(name)
        jarFile = entry.data
      } yield jarFile
    ).head
  }
  Map(
      findManagedDependency("org.scalaz",        "scalaz-core") -> url("https://scalazproject.ci.cloudbees.com/job/nightly_2.10/ws/target/scala-2.10/unidoc/")
    , findManagedDependency("com.typesafe.play", "play-json")   -> url("http://www.playframework.com/documentation/2.2.1/api/scala/")
  )
}

YMMV当然。

答案 1 :(得分:3)

接受的答案是好的,但是当关于确切的项目依赖性的假设不成立时它会失败。这是一个可能有用的变体:

apiMappings ++= {
  def mappingsFor(organization: String, names: List[String], location: String, revision: (String) => String = identity): Seq[(File, URL)] =
    for {
      entry: Attributed[File] <- (fullClasspath in Compile).value
      module: ModuleID <- entry.get(moduleID.key)
      if module.organization == organization
      if names.exists(module.name.startsWith)
    } yield entry.data -> url(location.format(revision(module.revision)))

  val mappings: Seq[(File, URL)] =
    mappingsFor("org.scala-lang", List("scala-library"), "http://scala-lang.org/api/%s/") ++
      mappingsFor("com.typesafe.akka", List("akka-actor"), "http://doc.akka.io/api/akka/%s/") ++
      mappingsFor("com.typesafe.play", List("play-iteratees", "play-json"), "http://playframework.com/documentation/%s/api/scala/index.html", _.replaceAll("[\\d]$", "x"))

  mappings.toMap
}

(这里包括scala-library是多余的,但仅用于说明目的。)

如果你执行mappings foreach println,你会得到类似的输出(注意我的依赖项中没有Akka):

(/Users/michaelahlers/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.11.7.jar,http://scala-lang.org/api/2.11.7/)
(/Users/michaelahlers/.ivy2/cache/com.typesafe.play/play-iteratees_2.11/jars/play-iteratees_2.11-2.4.6.jar,http://playframework.com/documentation/2.4.x/api/scala/)
(/Users/michaelahlers/.ivy2/cache/com.typesafe.play/play-json_2.11/jars/play-json_2.11-2.4.6.jar,http://playframework.com/documentation/2.4.x/api/scala/)

这种方法:

  1. 允许与模块标识符无匹配或多次匹配。
  2. 简明扼要地支持多个模块链接相同的文档。
    • 或者Nil提供给names,组织的所有模块。
  3. 将模块作为版本权限。
    • 但是,您可以根据需要映射版本。
      • 与Play的库一样, x 用于补丁号。
  4. 这些改进允许您创建一个单独的SBT文件(称为scaladocMappings.sbt),该文件可以在一个位置维护,并可以轻松复制并粘贴到任何项目中。

答案 2 :(得分:2)

除了我的上一个建议,sbt-api-mappings plugin ThoughtWorks显示了很多承诺。从长远来看,这是一个比每个维护自己的映射集的项目更具可持续性的路线。