【问题标题】:Gemfile.lock equivalent in Maven and gradleMaven 和 gradle 中的 Gemfile.lock 等效项
【发布时间】:2014-11-19 12:28:58
【问题描述】:

作为 Maven(客户端)和 IvyResolver(Gradle 使用),Bundler 解决了在配置文件(Gemfile for bundler)上声明的库依赖关系。然而,在那之后,Bundler 将依赖解析保存在 Gemfile.lock 上。它允许其他开发人员使用完全相同的库。

例如,Maven 使用确定器通过不明确的方式来解决依赖关系解析中的冲突。例如,将版本指定为 ...

<version>1.0.1</version>

不保证将使用该版本。并将版本指定为 ...

<version>[1.0.0,2.0.0)</version>

几乎不给我们任何保证。

是的,我可以手动编写

列出的所有版本
mvn dependency:resolve

但是,有没有自动的方法可以做到这一点?

非常清楚:在 Maven 或 Gradle 中有没有与 Gemfile.lock 等效的东西?


Java开发者,如果对Gemfile.lock、Bundler不熟悉,请查看:

http://bundler.io/v1.3/rationale.html

下面我复制的重要部分:

将您的代码检查到版本控制中

在开发您的应用程序一段时间后,签入 应用程序连同 Gemfile 和 Gemfile.lock 快照。现在, 您的存储库记录了所有 gem 的确切版本 你最后一次使用你确定的应用程序 工作。请记住,虽然您的 Gemfile 仅列出了三个 gem (具有不同程度的版本严格性),您的应用程序取决于 在几十颗宝石上,一旦你考虑到所有的 您所依赖的宝石的隐含要求。

这很重要:Gemfile.lock 使您的应用程序成为一个单一的 你自己的代码和它最后运行的第三方代码的包 时间你肯定知道一切正常。指定确切 您在 Gemfile 中依赖的第三方代码的版本会 不提供相同的保证,因为 gems 通常会声明一个范围 它们的依赖项的版本。

下次您在同一台机器上运行 bundle install 时,bundler 将 看到它已经拥有你需要的所有依赖项,然后跳过 安装过程。

“你说的不对。Maven可以保证版本”

是的,没错。如果你在 pom.xml 中声明了一个版本,maven 会使用它。但是,如果它在父 pom 中声明,则此保证将消失。

依赖中介——这决定了当遇到工件的多个版本时将使用哪个版本的依赖。目前,Maven 2.0 仅支持使用“最近定义”,这意味着它将使用依赖树中与您的项目最接近的依赖版本。您始终可以通过在项目的 POM 中明确声明来保证版本。请注意,如果两个依赖版本在依赖树中的深度相同,则在 Maven 2.0.8 之前没有定义哪个会获胜,但从 Maven 2.0.9 开始,声明中的顺序很重要:第一个声明获胜。

“最近的定义”意味着使用的版本将是依赖树中最接近您的项目的版本,例如。如果 A、B 和 C 的依赖项定义为 A -> B -> C -> D 2.0 和 A -> E -> D 1.0,则在构建 A 时将使用 D 1.0,因为从 A 到 D 的路径通过E 更短。您可以在 A 中显式添加对 D 2.0 的依赖项以强制使用 D 2.0

哦,看起来这与 DRY 原理相反。

【问题讨论】:

  • 什么时候不能保证使用那个版本&lt;version&gt;1.0.1&lt;/version&gt;
  • @khmarbaise,请阅读我对小发明答案的评论。

标签: maven gradle


【解决方案1】:

nebula.gradle-dependency-lock 插件就是这样做的。

PS:Gradle 不再使用 Ivy(如果这就是 IvyResolver 的意思)。

【讨论】:

  • o.O 非常干净的解决方案。
  • 很高兴听到现在 Gradle 4.8+ 及更高版本我们将拥有此功能内置的依赖锁定功能。查看最新的 4.8 版本说明。
【解决方案2】:

锁定依赖项的解决方案是使用&lt;dependencyManagement&gt; section of the current pom 或其父项,并且永远不要在你的pom 的&lt;dependencies&gt; 部分声明&lt;version&gt;s。

您可以使用Pedanic Pom Enforcer plugin 强制执行此行为(这样只有父项目才能声明依赖版本)。您还可以使用 enforcer plugin to completely ban all transitive dependencies 或各种子集(我什至不认为 gradle 或 bundle 具有这种级别的可配置性)。有些人真的很喜欢这种行为,因为您可以这样做,这样您就可以声明每个依赖项,这使您意识到您的应用程序/库可能是如何膨胀/耦合的。

是的,这不是 DRY,因为您基本上必须声明包两次(一次在 dependencyManagement 中,第二次在 dependencies 中没有版本)。如果您决定禁止所有传递,情况会更糟。您可以通过使用imports (ie bom:bill of material pom files) 和/或父 pom 来缓解 DRY 问题。像我自己这样的公司有一个主父 pom,每个项目都在使用每个依赖项(因此锁定了跨项目的库版本)。请记住,父 pom 或导入的 pom 也可以进行版本控制!

至于 gem lock 文件的行为,实际上并没有任何类似的东西......错误它只是不像 KISS 那样(据说我已经被 Gem.lock 严重烧毁并且更喜欢 maven/gradle 方式.. . 每个都有其优点)。您可以根据maven dependency plugin 编写一个插件(即将分析的依赖项转储到文件中)。

【讨论】:

    【解决方案3】:

    你在这里不正确。如果您明确说明

    <version>1.0.1</version>
    

    在您的 pom 中,保证此版本将用于可能使用不同版本的传递依赖项。

    【讨论】:

    • 1) 你在这里不正确。 maven.apache.org/enforcer/enforcer-rules/versionRanges.html 除非发生冲突,否则它将解析为 1.0.1。 “1.0 的默认 Maven 含义是所有 (,),但建议使用 1.0。显然这不适用于此处强制执行版本,因此已将其重新定义为最低版本。” 2) 抱歉,但这不是我的问题。
    • 对不起,你错了。您正在查看错误的文档。执行器插件不是您修复依赖项所需的。正确的文档是 docs.codehaus.org/display/MAVEN/…,如果您查看“强制版本”部分,您会发现我是对的,这就是您的需要。
    • 在该页面中... >> 1.0 的“软”要求(只是一个建议 - 如果它匹配所有范围,则有助于选择正确的版本)但是,再次......它不是回答问题。我不想使用非常特定的版本手动编写所有依赖项。你能再读一遍这个问题吗,我已经编辑以避免混淆。对不起。
    • 你正在阅读的部分是关于传递依赖,这就是为什么我明确告诉你阅读“强制版本”部分。手动修复每个直接依赖项是使用 maven 的正确方法。不管你喜不喜欢。
    • 相信我,这就是存在“硬性要求”的原因。你应该阅读冲突解决部分来理解。但是,我不敢相信手动修复每个依赖项是使用 maven 的唯一方法。我希望依赖插件可以做到这一点。 maven.apache.org/plugins/maven-dependency-plugin
    猜你喜欢
    • 2016-09-24
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 1970-01-01
    • 2015-05-20
    • 2018-06-14
    • 1970-01-01
    • 2011-06-04
    相关资源
    最近更新 更多