Maven 构建失败涉及依赖 JAR 中的 MANIFEST.MF 类路径
Maven build failure involving MANIFEST.MF classpath in dependency JARs
首先,我是 Whosebug 的长期用户(和受益者),但这是我的第一个问题。我已经对这个主题进行了大量搜索,但是我找到的大多数文章都在谈论生成 JAR 文件,而不是使用 Maven Central 存储库中的第 3 方 JAR,我真的没有能力修复它。我见过的几个解决方案并不是真的可以接受。
问题是在 Maven 中央存储库中找到的大多数 jaxb JAR 都包含指向依赖项的类路径条目(在 MANIFEST.MF 文件中),并且这些依赖项是用相对路径指定的——通常假设该依赖项 bar.jar 存在于与 foo.jar.
相同的目录中
例如,如果您将所有 JAR 依赖项都放在一个 lib 目录中,这很好。但是:
- Maven 想要维护自己的本地存储库,因此每个打包的 JAR 都位于自己的目录中(每个版本都位于单独的子目录中)。
- Maven JAR 通常以文件名中嵌入的版本信息命名,而 MANIFEST.MF 中的类路径条目仅使用基本文件名(无版本)指定依赖项。
最终结果是这样的错误消息:
[ERROR] bad path element
"C:\Users\rpoole\.m2\repository\com\sun\xml\bind\jaxb-impl.2.11\jaxb-core.jar":
no such file or directory
一种解决方案是编写脚本或小型应用程序来遍历所有 JAR 并从嵌入式 MANIFEST.MF 文件中删除类路径信息。但这不是很干净,在进行实际构建之前需要额外的步骤。
另一个可能的解决方案是,一些较新发布的问题 JAR 版本据说已经解决了这个类路径问题,因此使用最新和最好的。不幸的是,我正在开发的这个应用程序是遗留的,并且正在为第 3 方开发,所以我无法更新特定版本以外的依赖项。到目前为止,我研究过的所有 jaxb JAR 似乎都有问题。
有没有办法告诉Maven忽略JAR中嵌入的类路径,只依赖Maven自己的依赖解析?我已经尝试过重新排序依赖项之类的方法,但这不起作用(或将构建问题从一个子项目转移到另一个子项目)。
一个额外的烦恼:我们有一个 "blessed" Maven 存储库似乎可以让构建毫无问题地完成,但到目前为止我一直无法弄清楚为什么构建这组特定的 JAR好的。我怀疑有人可能已经进入并手动调整了一些 JAR 或 POM,但是信息很少,而且 diff 工具并没有太大帮助。
无论如何,项目应该从头开始构建。
如果我可以在 pom.xml 中为正在中断的子项目指定诸如排除块之类的东西,但是为了处理 JAR 的嵌入式类路径而不是 Maven 自己的传递依赖项(由 [指定=54=]).
编辑: 显然,有些人认为这是不可能的,Maven 会忽略 Class-Path 条目 Manifest.MF。然而,这是一个已知问题,正如 this Whosebug article. There's also another good article 中所讨论的,它更好地解释了一些历史。
问题是我无法在构建过程中浏览 JAR 并编辑每个 JAR 上的 MANIFEST.MF 文件。这不是一种实用的方法,即使通过脚本自动执行也是如此。我需要一个真正适用于已经在生产中的代码的解决方案。这些问题 应该 在相关 JAR 的更高版本中得到修复,但我可能无法使用这些问题的更新版本。
此外,建议的修复方法之一是将 -Xlint:-path
添加到编译器参数,从而抑制错误消息。然而,对我来说,构建在另一个点上失败了,所以乍一看这似乎也不是一个好的解决方案。我会再试一次,因为根据 this,POM 文件中编译器参数的语法有点奇怪。
我讨厌回答我自己的问题,但我终于设法解决了这个问题。对于那些坚持认为 Maven 构建不可能受到 jar MANIFEST.MF 中的 Class-Path 条目影响的人,请阅读 Michael Bayne 的 this article。它很好地总结了问题和解决方案。提示:javac 确实关心 jars 中的嵌入式类路径。
诀窍是将 -Xlint:-path
添加到编译器参数中,尽管最初我对这个解决方案持怀疑态度。这样做会抑制错误的路径元素 warnings/errors,因此 Maven 不会过早地停止构建。我遇到的问题是找出将这些参数嵌入 pom.xml 的正确语法。这就是 this article 派上用场的地方。因此,编译器插件的配置必须看起来像这样才能被正确理解:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
<compilerArguments>
<Xlint/>
<Xlint:-path/>
</compilerArguments>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
请注意,此语法不是很好 XML(正如 Bayne 指出的那样),大多数 IDE 会将第二行 Xlint 标记为错误,但它适用于 Maven。使用一些 Maven 教程中给出的语法可能会导致参数根本不传递给编译器,或者只传递最后一个参数。
一旦解决了这个问题,您可能会发现其他构建问题(我确实发现了),但至少那些问题不会再对您隐藏了。
问题是您引用的 post 已经七年了..并且不要使用更新版本的 maven-compiler-plugin:
javac compiler 的参数可以像这样更好地完成:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<compilerArgs>
<arg>-Xlint</arg>
<arg>-Xlint:-path</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
首先,我是 Whosebug 的长期用户(和受益者),但这是我的第一个问题。我已经对这个主题进行了大量搜索,但是我找到的大多数文章都在谈论生成 JAR 文件,而不是使用 Maven Central 存储库中的第 3 方 JAR,我真的没有能力修复它。我见过的几个解决方案并不是真的可以接受。
问题是在 Maven 中央存储库中找到的大多数 jaxb JAR 都包含指向依赖项的类路径条目(在 MANIFEST.MF 文件中),并且这些依赖项是用相对路径指定的——通常假设该依赖项 bar.jar 存在于与 foo.jar.
相同的目录中例如,如果您将所有 JAR 依赖项都放在一个 lib 目录中,这很好。但是:
- Maven 想要维护自己的本地存储库,因此每个打包的 JAR 都位于自己的目录中(每个版本都位于单独的子目录中)。
- Maven JAR 通常以文件名中嵌入的版本信息命名,而 MANIFEST.MF 中的类路径条目仅使用基本文件名(无版本)指定依赖项。
最终结果是这样的错误消息:
[ERROR] bad path element "C:\Users\rpoole\.m2\repository\com\sun\xml\bind\jaxb-impl.2.11\jaxb-core.jar": no such file or directory
一种解决方案是编写脚本或小型应用程序来遍历所有 JAR 并从嵌入式 MANIFEST.MF 文件中删除类路径信息。但这不是很干净,在进行实际构建之前需要额外的步骤。
另一个可能的解决方案是,一些较新发布的问题 JAR 版本据说已经解决了这个类路径问题,因此使用最新和最好的。不幸的是,我正在开发的这个应用程序是遗留的,并且正在为第 3 方开发,所以我无法更新特定版本以外的依赖项。到目前为止,我研究过的所有 jaxb JAR 似乎都有问题。
有没有办法告诉Maven忽略JAR中嵌入的类路径,只依赖Maven自己的依赖解析?我已经尝试过重新排序依赖项之类的方法,但这不起作用(或将构建问题从一个子项目转移到另一个子项目)。
一个额外的烦恼:我们有一个 "blessed" Maven 存储库似乎可以让构建毫无问题地完成,但到目前为止我一直无法弄清楚为什么构建这组特定的 JAR好的。我怀疑有人可能已经进入并手动调整了一些 JAR 或 POM,但是信息很少,而且 diff 工具并没有太大帮助。
无论如何,项目应该从头开始构建。
如果我可以在 pom.xml 中为正在中断的子项目指定诸如排除块之类的东西,但是为了处理 JAR 的嵌入式类路径而不是 Maven 自己的传递依赖项(由 [指定=54=]).
编辑: 显然,有些人认为这是不可能的,Maven 会忽略 Class-Path 条目 Manifest.MF。然而,这是一个已知问题,正如 this Whosebug article. There's also another good article 中所讨论的,它更好地解释了一些历史。
问题是我无法在构建过程中浏览 JAR 并编辑每个 JAR 上的 MANIFEST.MF 文件。这不是一种实用的方法,即使通过脚本自动执行也是如此。我需要一个真正适用于已经在生产中的代码的解决方案。这些问题 应该 在相关 JAR 的更高版本中得到修复,但我可能无法使用这些问题的更新版本。
此外,建议的修复方法之一是将 -Xlint:-path
添加到编译器参数,从而抑制错误消息。然而,对我来说,构建在另一个点上失败了,所以乍一看这似乎也不是一个好的解决方案。我会再试一次,因为根据 this,POM 文件中编译器参数的语法有点奇怪。
我讨厌回答我自己的问题,但我终于设法解决了这个问题。对于那些坚持认为 Maven 构建不可能受到 jar MANIFEST.MF 中的 Class-Path 条目影响的人,请阅读 Michael Bayne 的 this article。它很好地总结了问题和解决方案。提示:javac 确实关心 jars 中的嵌入式类路径。
诀窍是将 -Xlint:-path
添加到编译器参数中,尽管最初我对这个解决方案持怀疑态度。这样做会抑制错误的路径元素 warnings/errors,因此 Maven 不会过早地停止构建。我遇到的问题是找出将这些参数嵌入 pom.xml 的正确语法。这就是 this article 派上用场的地方。因此,编译器插件的配置必须看起来像这样才能被正确理解:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
<compilerArguments>
<Xlint/>
<Xlint:-path/>
</compilerArguments>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
请注意,此语法不是很好 XML(正如 Bayne 指出的那样),大多数 IDE 会将第二行 Xlint 标记为错误,但它适用于 Maven。使用一些 Maven 教程中给出的语法可能会导致参数根本不传递给编译器,或者只传递最后一个参数。
一旦解决了这个问题,您可能会发现其他构建问题(我确实发现了),但至少那些问题不会再对您隐藏了。
问题是您引用的 post 已经七年了..并且不要使用更新版本的 maven-compiler-plugin:
javac compiler 的参数可以像这样更好地完成:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<compilerArgs>
<arg>-Xlint</arg>
<arg>-Xlint:-path</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>