【问题标题】:Can I use sbt's `apiMappings` setting for managed dependencies?我可以将 sbt 的 `apiMappings` 设置用于托管依赖项吗?
【发布时间】:2013-11-16 04:48:17
【问题描述】:

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

apiMappings 设置应该有助于解决这个问题,但它的类型为Map[File, URL],因此旨在为非托管依赖项设置文档 url。托管依赖项被声明为 sbt.ModuleID 的实例,并且不能直接插入到该映射中。

我能否以某种方式填充apiMappings 设置,以将 URL 与托管依赖项相关联?

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

注意:这与https://stackoverflow.com/questions/18747265/sbt-scaladoc-configuration-for-the-standard-library/18747266 有关,但该问题因链接到标准库的 scaladoc 而有所不同,标准库有一个众所周知的File scalaInstance.value.libraryJar,但在本例中并非如此。

【问题讨论】:

    标签: sbt scaladoc


    【解决方案1】:

    我设法通过执行以下操作来引用 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。

    【讨论】:

    • 我现在手头没有我的构建文件,但总的来说,这看起来像是我在问这个问题后拼凑起来的解决方案,如果可能更简单的话。谢谢!
    【解决方案2】:

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

    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 用于补丁编号。

    这些改进允许您创建一个单独的 SBT 文件(称为 scaladocMappings.sbt),该文件可以在一个位置进行维护,并且可以轻松复制并粘贴到任何项目中。

    【讨论】:

      【解决方案3】:

      除了我的最后一个建议之外,ThoughtWorkssbt-api-mappings plugin 显示了很多希望。从长远来看,这比每个项目都维护自己的一组映射更可持续。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-07-25
        • 2019-04-11
        • 2014-08-27
        • 2013-12-03
        • 2014-02-16
        • 2015-05-24
        • 2016-03-05
        相关资源
        最近更新 更多