如何让 sbt 使用本地 Maven 代理存储库(Nexus)?

Posted

技术标签:

【中文标题】如何让 sbt 使用本地 Maven 代理存储库(Nexus)?【英文标题】:how do I get sbt to use a local maven proxy repository (Nexus)? 【发布时间】:2011-04-15 18:27:25 【问题描述】:

我有一个 sbt (Scala) 项目,该项目目前从网络上提取工件。我们希望转向可以缓存工件的企业标准化 Nexus 存储库。从 Nexus 文档中,我了解如何为 Maven 项目执行此操作。但是 sbt 显然使用了不同的方法。 (我知道 Ivy 以某种方式参与其中,但我从未使用过它,也不明白它是如何工作的。)

我如何告诉 sbt 和/或底层 Ivy 使用公司 Nexus 存储库系统来处理所有依赖项?我想要使​​用某种项目级配置文件的答案,以便我们的源存储库的新克隆将自动使用代理。 (即,在点目录中处理每个用户的配置文件是不可行的。)

谢谢!

【问题讨论】:

@VonC 我对带有[maven] 标签的问题进行了一些批量更新,并认为这个问题更多的是关于 Nexus 而不是 Maven(-2)。但是,如果您认为它是相关的,请随时相应地回滚/更新,我在这方面可能走得太快了。 是的,maven 可能不是主要标签,但肯定是关于 maven repos。我把它回滚了。 顺便说一句,它被证实:它在家里和工作中都像宣传的那样工作。我已经编辑了我的问题来说明这一点,并添加了一些存储库定义供您检查。 【参考方案1】:

您只需要定义一个属性文件sbt.boot.properties,它允许您:

重新定义 ivy 缓存位置(我需要它,因为否则它将成为我们 roaming Windows profile 的一部分,我们商店的磁盘空间受到严重限制。请参阅 Issue 74) 定义您想要的任何其他 Maven 存储库 C:\HOMEWARE\apps\sbt-0.74\sbt.boot.properties [斯卡拉] 版本:2.7.7 # 分类器:来源、javadoc [应用程序] 组织:org.scala-tools.sbt 名称:sbt 版本:读取(sbt.version) 类:sbt.xMain 组件:xsbti 跨版本:真 分类器:来源、javadoc [存储库] 当地的 my-nexus:http://my.nexus/nexus/content/repositories/scala-tools/,[组织]/[模块]/[修订]/[类型]s/[工件](-[分类器])。 [分机] 本地行家 # sbt-db: http://databinder.net/repo/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext] # Maven 中心 # scala-tools-releases # scala-tools-snapshots [开机] 目录:项目/启动 属性:项目/build.properties prompt-create: 项目不存在,新建项目? 提示填充:真 快速选项:真 [日志] 级别:调试 [应用程序属性] project.name: quick=set(test), new=prompt(Name)[p], fill=prompt(Name) project.organization: new=prompt(Organization)[org.vonc] project.version: quick=set(1.0), new=prompt(Version)[1.0], fill=prompt(Version)[1.0] build.scala.versions: quick=set(2.8.0.RC2), new=prompt(Scala 版本)[2.8.0.RC2], fill=prompt(Scala 版本)[2.8.0.RC2] sbt.version: quick=set(0.7.4), new=prompt(sbt version)[0.7.4], fill=prompt(sbt version)[0.7.4] project.scratch:快速=设置(真) 项目初始化:快速=设置(真),新=设置(真) [常春藤] 缓存目录:C:\HOMEWARE\projects\.ivy2\cache

注意:这个sbt.boot.properties 文件的灵感来自:

"Generalized Launcher" page of the sbt project中提到的那个。 在sbt-0.74 中找到的那个!

我已经评论了任何外部 Maven 存储库定义,并添加了对我自己的 Nexus Maven 存储库的引用。

启动器可以通过以下方式之一按优先级升序配置:

替换jar中的/sbt/sbt.boot.properties文件。 将名为sbt.boot.properties 的配置文件放在类路径中。将其放在不带 /sbt 前缀的类路径根目录中。 在命令行上指定备用配置的位置。这可以通过以下方式完成: 将位置指定为系统属性sbt.boot.properties 或作为启动器的第一个参数,前缀为“@”。

系统属性的优先级较低。 相对路径的解析为:

第一次尝试针对当前工作目录, 然后针对用户的主目录, 然后针对包含启动器 jar 的目录。

如果这些尝试均未成功,则会生成错误。


定义一个 sbt.bat 包装器(以确保指定 您的 sbt.boot.properties),例如:

C:\HOMEWARE>more C:\HOMEWARE\bin\sbt.BAT
@echo off
set t=%~dp0
set adp0=%t:C:\="%"

set SBT_DIR=%adp0%..\apps\sbt-0.74
dir C:\%SBT_DIR%\sbt-launch-0.7.4.jar
# if needed, add your proxy settings
set PROXY_OPTIONS=-Dhttp.proxyHost=my.proxy -Dhttp.proxyPort=80xx -Dhttp.proxyUser=auser -Dhttp.proxyPassword=yyyy
set JAVA_OPTIONS=-XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m -Xmx512M -cp C:\HOMEWARE\apps\sbt-0.74\sbt-launch-0.7.4
set SBT_BOOT_PROPERTIES=-Dsbt.boot.properties="sbt.boot.properties"
cmd /C C:\HOMEWARE\apps\jdk4eclipse\bin\java.exe %PROXY_OPTIONS% %JAVA_OPTIONS% %SBT_BOOT_PROPERTIES% -jar C:\HOMEWARE\apps\sbt-0.74\sbt-launch-0.7.4.jar %*

您的 sbt 将从以下位置下载工件:

你的 Nexus 您的本地 Maven 存储库。

刚刚在家里用我运行的旧 Nexus 开源 1.6、java 1.6、sbt07.4 进行了测试

C:\Prog\Java\jdk1.6.0_18\jre\bin\java  -Xmx512M -Dsbt.boot.properties=sbt.boot.properties - jar "c:\Prog\Scala\sbt\sbt-launch-0.7.4.jar"  

这给了:

[success] Build completed successfully.
C:\Prog\Scala\tests\pp>sbt
Getting Scala 2.8.0 ...
downloading http://localhost:8081/nexus/content/repositories/scala/org/scala-lang/scala-compiler/2.8.0/scala-compiler-2.
8.0.jar ...
        [SUCCESSFUL ] org.scala-lang#scala-compiler;2.8.0!scala-compiler.jar (311ms)
downloading http://localhost:8081/nexus/content/repositories/scala/org/scala-lang/scala-library/2.8.0/scala-library-2.8.
0.jar ...
        [SUCCESSFUL ] org.scala-lang#scala-library;2.8.0!scala-library.jar (185ms)
:: retrieving :: org.scala-tools.sbt#boot-scala
        confs: [default]
        2 artifacts copied, 0 already retrieved (14484kB/167ms)
[info] Building project test 0.1 against Scala 2.8.0
[info]    using sbt.DefaultProject with sbt 0.7.4 and Scala 2.7.7

如果我在 sbt.boot.properties 文件中尝试一个有趣的值:

C:\Prog\Scala\tests\pp>sbt
Getting Scala 2.9.7 ...

:: problems summary ::
:::: WARNINGS
                module not found: org.scala-lang#scala-compiler;2.9.7
        ==== nexus: tried
          http://localhost:8081/nexus/content/repositories/scala/org/scala-lang/scala-compiler/2.9.7/scala-compiler-2.9.7.pom
          -- artifact org.scala-lang#scala-compiler;2.9.7!scala-compiler.jar:
          http://localhost:8081/nexus/content/repositories/scala/org/scala-lang/scala-compiler/2.9.7/scala-compiler-2.9.7.jar

所以它确实限制了我定义的两个 repo:

[repositories]
nexus:  http://localhost:8081/nexus/content/repositories/scala
nexus2: http://localhost:8081/nexus/content/repositories/scala, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext]

(我评论了其他所有内容:localmaven-local,...)

如果我评论 所有 存储库并在 sbt.boot.properties 中为 scala 版本添加一个有趣的值 (2.7.9),我会得到(就像 OP 一样)

C:\Prog\Scala\tests\pp>sbt
Error during sbt execution: No repositories defined.

如果我把 2.7.7 (同时仍然有 all repo 评论),是的,它不会产生错误:

C:\Prog\Scala\tests\pp>sbt
[info] Building project test 0.1 against Scala 2.8.0
[info]    using sbt.DefaultProject with sbt 0.7.4 and Scala 2.7.7

但这只是因为它在我之前的尝试中已经下载了 scala2.8.0。 如果我从我的 project/boot 目录中删除该库,那么它将引发异常:

[info]    using sbt.DefaultProject with sbt 0.7.4 and Scala 2.7.7
> C:\Prog\Scala\tests\pp>sbt
Error during sbt execution: No repositories defined.
        at xsbt.boot.Pre$.error(Pre.scala:18)
        at xsbt.boot.Update.addResolvers(Update.scala:197)
...
        at xsbt.boot.Boot$.main(Boot.scala:15)
        at xsbt.boot.Boot.main(Boot.scala)
Error loading project: Error during sbt execution: No repositories defined.

【讨论】:

感谢您非常完整的回复!但这对我不起作用。我创建了一个 sbt.boot.properties 文件,它只列出了三个存储库:local、maven-local 和指向我们本地 Nexus 存储库的 my-nexus。 sbt 是一个包含以下内容的脚本:java -Xmx1024M -Dsbt.boot.properties="sbt.boot.properties" -jar dirname $0/sbt-launch.jar "$@" 如果我从我的 .ivy2 缓存中删除一个包(比如 Squeryl),然后执行“sbt update”,它似乎是从公众中提取的互联网,无需接触我们的 Nexus 安装。如何/为什么? @Harlan:为什么?因为它没有考虑到您的sbt.boot.properties。您是否在sbt-launch-0.7.4.jar 旁边创建它(意思是在您的类路径中)?想一想,我没有看到您的 java 命令中明确定义了任何类路径。 肯定是在加载 sbt.boot.properties。使用上面显示的命令,如果我在该文件中将 Scala 版本更改为 2.9.7,它会徒劳地尝试获取 2.9.7。所以这不是类路径问题。但是sbt update 正在从 scala-tools.org 中提取,即使只定义了 local 和 my-nexus。 @Harlan:您是否尝试定义 no 存储库?或者定义一些明显错误的东西?我仍然很难相信您的特定财产文件已被考虑在内。 这很奇怪。如果我将 scala 版本设置为 2.9.7,并注释掉所有存储库,那么它会抱怨“sbt 执行期间出错:未定义存储库”。但是,如果我将 scala 版本设置为 2.7.7,并注释掉所有存储库,它就会抱怨并且似乎忽略了存储库列表!【参考方案2】:

好的,在 sbt 邮件列表上的 Mark Harrah 的帮助下,我有一个可行的答案。

我的构建类现在如下所示(加上一些其他 repos):

import sbt._

//By extending DefaultWebProject, we get Jetty support
class OurApplication(info: ProjectInfo) extends DefaultWebProject(info) 

  // This skips adding the default repositories and only uses the ones you added
  // explicitly. --Mark Harrah
  override def repositories = Set("OurNexus" at "http://our.nexus.server:9001/nexus/content/groups/public/") 
  override def ivyRepositories = Seq(Resolver.defaultLocal(None)) ++ repositories

  /* Squeryl */
  val squeryl = "org.squeryl" % "squeryl_2.8.0.RC3" % "0.9.4beta5"

  /* DATE4J */
  val date4j = "hirondelle.date4j" % "date4j" % "1.0" from "http://www.date4j.net/date4j.jar"

  // etc

现在,如果我从机器的.ivy2/cache 目录中删除 Squeryl 树,sbt 会尝试使用适当的 URL 从 Nexus 树中抓取它。问题解决了!

【讨论】:

Play 2 Final 和 SBT 0.11.2 现在已经过时了。【参考方案3】:

好吧,这困扰了我一段时间,所以我发现一个人在 github 上为 maven 编写了一个 SBT 插件,名为 maven-sbt,所以你所要做的就是将它包含在你的插件项目中,并让你的项目与maven.MavenDependencies 以及您的所有操作(例如更新和本地发布)都可以与本地 maven 一起使用。这样做的好处是,如果您像我一样,您的组织都是 maven。所以,你所有的库都在你本地的 maven repo 中,但是如果由于某种原因你首先使用 sbt 构建,那么你也开始在 ivy 中获得一堆或罐子。多么浪费空间和时间,因为您仍然需要为您的 Maven 构建获取它们。

也就是说,我希望它被内置到 sbt 中,所以我不需要将它添加到每个项目中。也许至少作为处理器。他在我读到的一件事中提到他想将其添加到 0.9 但我一直找不到。

【讨论】:

【参考方案4】:

第 1 步:按照Detailed Topics: Proxy Repositories 的说明进行操作,我已将其总结并添加到以下内容:

    (如果您使用 Artifactory,则可以跳过此步骤。)在您的公司 Maven 存储库上创建一个完全独立的 Maven 代理存储库(或组),以代理 ivy-style 存储库,例如这两个重要的存储库:

    http://repo.typesafe.com/typesafe/ivy-releases/ http://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/

    这是必需的,因为某些存储库管理器无法处理混合在一起的 Ivy 风格和 Maven 风格的存储库。

    创建一个文件repositories,列出您的主要公司存储库以及您在第 1 步中创建的任何额外存储库,格式如下:

    [repositories]
      my-maven-proxy-releases: http://repo.example.com/maven-releases/
      my-ivy-proxy-releases: http://repo.example.com/ivy-releases/, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]
    

    要么将该文件保存在主目录内的.sbt 目录中,要么在 sbt 命令行中指定它:

    sbt -Dsbt.repository.config=<path-to-your-repo-file>
    

对于那些使用旧版本 sbt 的人来说是个好消息:尽管至少在 sbt 0.12.0 启动器 jar 中,旧 sbt 版本的启动属性文件不包含所需的行 (提到repository.config),如果您编辑这些文件以添加所需的行并将它们重新打包到 sbt 0.12.0 启动器 jar 中,它仍然适用于那些版本的 sbt!这是因为该功能是在启动器中实现的,而不是在 sbt 本身中实现的。并且 sbt 0.12.0 启动器声称能够启动所有版本的 sbt,直接回到 0.7!

第 2 步:为确保未使用外部存储库,请从解析器中删除默认存储库。这可以通过以下两种方式之一完成:

    添加上面详细主题页面中提到的命令行选项-Dsbt.override.build.repos=true。这将导致您在文件中指定的存储库覆盖在任何 sbt 文件中指定的任何存储库。不过,这可能仅适用于 sbt 0.12 及更高版本 - 我还没有尝试过。 在您的构建文件中使用fullResolvers := Seq( 解析器),而不是resolvers ++=resolvers := 或您以前使用的任何东西。

【讨论】:

我正在使用 Scala 2.10、Artifactory 3、sbt 12.3 并且使用此处和此处引用的文档中的说明没有运气。在那里找到 typeo 后,我知道它的阅读存储库。我已经通过 -D 在启动器上设置了属性。 SBT 的行为就像它没有忽略默认解析器,因为它说它应该使用 -Dsbt.override.build.repos=true。我可以尝试上面的第 2 点,但听起来它不应该是必要的? @Robin Green:非常感谢,这个问题把我逼疯了,你的解决方案对我有用。 如果你想为每个项目配置这个(如原始问题中所问)并且不想在每个sbt 运行中添加命令行选项,你可以创建一个名为“. sbtopts”在你的“build.sbt”旁边。将选项 (-Dsbt.override.build.repos=true -Dsbt.repository.config=&lt;…&gt;) 放入其中,它们将被sbt 可执行文件拾取。【参考方案5】:

编辑 sbt_home/conf "sbtconfig.txt" 中的配置文件

添加两行

-Dsbt.override.build.repos=true
-Dsbt.repository.config="C:/Program Files (x86)/sbt/conf/repo.properties"

repo.properties 内容是

[repositories]
    local
    public: http://222.vvfox.com/public  <-fix this ,write your local nexus group url

【讨论】:

【参考方案6】:

我收到此错误是因为我在 ~/.sbt/repositories 中有一个空白文件。将存储库添加到文件和删除文件都解决了这个问题。

【讨论】:

以上是关于如何让 sbt 使用本地 Maven 代理存储库(Nexus)?的主要内容,如果未能解决你的问题,请参考以下文章

SBT 在本地 maven 存储库中找不到文件,尽管它在那里

将 SBT 项目发布到本地目录

使用 maven 存储库作为本地常春藤缓存

使用基于文件的存储库离线使用 SBT

如何让 Grails 从 Maven 存储库中获取最新的本地 jars?

sbteclipse:创建 build.sbt 和 plugins.sbt