Maven耳朵插件 - 不使用清洁时的“双倍”伪影

2022-09-03 02:20:35

在通过 Maven 耳朵插件构建耳朵时,我体验到不使用耳朵的应用可能会导致不一致的结果:如果我更改依赖项的版本,依赖项现在会在耳朵中出现两次,在旧版本中和新版本中。如果我在jar名称中没有版本号的耳朵,我只得到一个jar,但旧版本没有被正确替换。packageclean

我看了源代码

http://svn.apache.org/viewvc/maven/plugins/tags/maven-ear-plugin-2.10.1/src/main/java/org/apache/maven/plugin/ear/EarMojo.java?view=markup

特别是来自436的行很有趣:检查是否更新目标中的文件,但显然只检查绝对路径和上次修改的日期。

总结:我是否正确,更改依赖项(或其版本)总是需要在构建之前调用?还是我错过了一些情报?cleanpackage


答案 1

是的。。。大多数情况下,在更改依赖项或任何其他生成配置时,您应该调用,否则以前的生成元素可能会与新的生成发生冲突(此处的情况似乎就是如此)。一般来说,为了确保以前的构建元素不会与新的构建发生冲突,您应该事先调用 - 配置更改与否。cleanclean

但也有例外:如果您确定以前的构建元素不会影响您的新构建,则可以跳过 。但是,大多数情况下,您无法知道,或者跳过根本不可能不引起此类碰撞。我在下面详细解释。cleanclean


当您使用 Maven 构建项目时,它将在文件夹下生成文件和其他元素(默认情况下)。然后,这些元素用于在阶段中创建工件(在本例中为 EAR)。${project.build.directory}targetpackage

如果不在生成后调用,则下面的所有元素在下次生成期间仍将存在,并可能影响它。Maven插件如何区分并知道哪些元素来自旧版本或新版本?文件时间戳显然是不够的,除非使用某种晦涩的机制来识别哪些文件来自哪个版本,否则很难做到。cleantarget

如果我更改依赖项的版本,则依赖项现在会在旧版本和新版本中在耳朵中出现两次。

这可能是因为你的构建副本依赖关系和你的打包插件将整个目录包含在生成的工件中(在你的例子中,是EAR)。例如,如果您使用不同的版本运行生成两次:target

  • 第一个构建:生成于,您的插件包含 EAR 中的所有文件。一切都很好。mydep-1.0.jartarget/classes/mydeptarget/classes/mydep
  • 第二个生成:已生成,但仍在 .包含整个目录,并且两个版本最终都位于 EAR 中。mydep-2.0.jarmydep-1.0.jartarget/classes/mydeptarget/classes/mydep

如果我在jar名称中没有版本号的耳朵,我只得到一个jar,但旧版本没有被正确替换。

这是因为某些用于优化的插件如果看到结果已经存在,则不会重新编译或重新执行操作。在您的情况下,正如您所指出的,EAR插件可能会保留文件的“旧”版本,因为它已经存在,实际上应该使用具有相同名称的最新版本来替换它。这可能是因为您没有指定版本:

  • 在第一种情况下,存在并创建了一个新的,但两者都包含在您的 EAR 中mydep-0.1.jarmydep-0.2.jar
  • 现在,如果没有版本,您就拥有了没有被最新版本覆盖的版本,因为“它已经存在”,因此“旧”文件保留在原位并包含在EAR中。mydep.jar

结论:Maven插件无法100%确定地区分元素是否来自以前的版本或新版本。更新生成配置时,应始终调用以确保新旧生成元素之间不会发生冲突。即使没有构建配置更改,也可能需要调用 - 但这是另一回事。cleanclean

我建议在运行构建时始终调用,除非没有冲突的可能性,并且它提供了一个真正的价值,例如时间增益,因为重建整个项目太长或其他原因证明它是合理的。clean

编辑:根据@JF迈尔对来源的要求,Running Maven指南根据目标和相关不一致风险提供建议:clean

输出不一致

大多数插件都经过优化,可以知道它们是否必须执行任务。在某些情况下,输出可能会受到先前构建的污染,最终结果不是您预期的。在极少数情况下,您可以调用阶段,这意味着:删除输出目录。您也可以将其称为:首先清理输出目录,然后构建项目并验证结果。cleanmvn clean verify


答案 2

通过编译最新版本的 maven-ear-plugin(3.0.0,比 2.10.2 更新,本身比官方 2.12.1 更新)来查看问题是否仍然存在)

正如您在最新代码 EarMojo 中看到的那样.java,该函数已从 2.10.1 实现更改为 2.10.1,并且可能更可靠。copyModules()


推荐