如何让 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
,它允许您:
注意:这个sbt.boot.properties
文件的灵感来自:
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]
(我评论了其他所有内容:local
,maven-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=<…>
) 放入其中,它们将被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 存储库中找不到文件,尽管它在那里