简体   繁体   English

Maven 构建失败,涉及依赖 JAR 中的 MANIFEST.MF 类路径

[英]Maven build failure involving MANIFEST.MF classpath in dependency JARs

First off, I'm a long time user (and beneficiary) of StackOverflow, but this is my first question.首先,我是 StackOverflow 的长期用户(和受益者),但这是我的第一个问题。 I've done plenty of searching on this topic, but most of the articles I've turned up talk about generating JAR files, not working with 3rd party JARs from the Maven Central repo which I don't really have the power to fix.我已经对这个主题进行了大量搜索,但是我找到的大多数文章都在谈论生成 JAR 文件,而不是使用来自 Maven Central 存储库的 3rd 方 JAR,我真的没有能力修复它。 The few solutions I've seen floating around aren't really acceptable.我看到的少数解决方案并不是真的可以接受。

The problem is that most of the jaxb JARs found in the Maven Central repository contain classpath entries (in the MANIFEST.MF file) that point to dependencies, and those dependencies are specified with relative paths -- typically assuming that dependency bar.jar exists in the same directory as foo.jar.问题是在 Maven 中央存储库中找到的大多数 jaxb JAR 都包含指向依赖项的类路径条目(在 MANIFEST.MF 文件中),并且这些依赖项是用相对路径指定的——通常假设依赖项 bar.jar 存在于与 foo.jar 相同的目录。

This is fine if you have all your JAR dependencies in a single lib directory, for example.例如,如果您在单个 lib 目录中拥有所有 JAR 依赖项,则这很好。 But:但:

  • Maven wants to maintain its own local repository, so every single packaged JAR lives in its own directory (with each version in a separate subdirectory). Maven 想要维护自己的本地存储库,因此每个打包的 JAR 都位于自己的目录中(每个版本都位于单独的子目录中)。
  • Maven JARs are typically named with the version info embedded in the filename, whereas the classpath entry in MANIFEST.MF specifies the dependency with just the base filename (no version). Maven JAR 通常使用嵌入在文件名中的版本信息命名,而 MANIFEST.MF 中的类路径条目仅使用基本文件名(无版本)指定依赖项。

The net result is an error message like this:最终结果是这样的错误消息:

[ERROR] bad path element "C:\\Users\\rpoole\\.m2\\repository\\com\\sun\\xml\\bind\\jaxb-impl\\2.2.11\\jaxb-core.jar": no such file or directory [错误] 错误的路径元素“C:\\Users\\rpoole\\.m2\\repository\\com\\sun\\xml\\bind\\jaxb-impl\\2.2.11\\jaxb-core.jar”:没有这样的文件或目录

One solution is to write a script or small app to go through all the JARs and strip out the classpath info from the embedded MANIFEST.MF file.一种解决方案是编写一个脚本或小应用程序来遍历所有 JAR 并从嵌入的 MANIFEST.MF 文件中去除类路径信息。 But that is not very clean, and requires an extra step before doing the actual build.但这不是很干净,在进行实际构建之前需要一个额外的步骤。

Another potential solution is that some newer published versions of the JARs in question have supposedly fixed this classpath problem, so therefore use the latest and greatest.另一个潜在的解决方案是,一些较新的 JAR 发布版本据说已经解决了这个类路径问题,因此请使用最新和最好的。 Unfortunately, this app I'm working on is legacy, and is being developed for a 3rd party, so I can't update the dependencies beyond a certain version.不幸的是,我正在开发的这个应用程序是遗留的,并且是为 3rd 方开发的,所以我无法更新特定版本以外的依赖项。 So far, all the jaxb JARs that I have poked into seem to have issues.到目前为止,我研究过的所有 jaxb JAR 似乎都有问题。

Is there a way to tell Maven to ignore the embedded classpath in the JAR and only rely on Maven's own dependency resolution?有没有办法告诉 Maven 忽略 JAR 中嵌入的类路径而只依赖 Maven 自己的依赖项解析? I've tried things like reordering dependencies, but that doesn't work (or moves the build problem from one subproject to another).我尝试过重新排序依赖项之类的方法,但这不起作用(或将构建问题从一个子项目转移到另一个子项目)。

One additional annoyance: There is a "blessed" Maven repo we have that seems to let the build complete with no problem, but so far I've been unable to figure out why this particular set of JARs builds OK.一个额外的烦恼:我们有一个“祝福”的 Maven 存储库,它似乎可以让构建毫无问题地完成,但到目前为止,我一直无法弄清楚为什么这组特定的 JAR 构建正常。 I suspect someone may have gone in and tweaked some JARs or POMs manually, but there's scant information, and diff tools aren't really helping much.我怀疑有人可能已经进入并手动调整了一些 JAR 或 POM,但信息很少,而且差异工具并没有多大帮助。

Regardless, the project should build from scratch.无论如何,该项目应该从头开始构建。

What would be nice is if I could specify something like an exclusion block in the pom.xml for the subproject that's breaking, but for dealing with a JAR's embedded classpath instead of Maven's own transitive dependencies (specified by groupId/artifactId).如果我可以在 pom.xml 中为正在中断的子项目指定一个排除块之类的东西,但是为了处理 JAR 的嵌入式类路径而不是 Maven 自己的传递依赖项(由 groupId/artifactId 指定),那会很好。

Edit: Apparently, some people believe that this is impossible, and that Maven ignores the Class-Path entry in Manifest.MF.编辑:显然,有些人认为这是不可能的,并且 Maven 忽略了 Manifest.MF 中的 Class-Path 条目。 However, this is a known issue, as discussed in this StackOverflow article .但是,这是一个已知问题,如StackOverflow 文章 中所述 There's also another good article which explains some of the history of this a bit better.还有另一篇好文章更好地解释了一些历史。

The problem is that I can't go through the JARs and edit the MANIFEST.MF files on each as part of the build process.问题是我无法通过 JAR 并在构建过程中编辑每个 JAR 文件上的 MANIFEST.MF 文件。 That's just not a practical approach, even if automated by script.即使通过脚本自动化,这也不是一种实用的方法。 I need a solution that actually will work for code that is already in production.我需要一个实际上适用于已经在生产中的代码的解决方案。 These issues were supposedly fixed in later versions of the JARs in question, but I may not be able to use newer versions of those.这些问题应该在相关 JAR 的更高版本中得到解决,但我可能无法使用这些问题的较新版本。

Additionally, one of the proposed fixes is to add -Xlint:-path to the compiler args, which suppresses the error message.此外,建议的修复方法之一是将-Xlint:-path添加到编译器参数中,从而抑制错误消息。 However, the build simply fails at another point for me, so at first blush this does not appear to be a good solution either.但是,对我来说,构建只是在另一点上失败了,所以乍一看,这似乎也不是一个好的解决方案。 I'll be trying this again because according to this , the syntax for compiler arguments inside POM files is a bit wonky.我将再次尝试这个,因为根据这个,POM 文件中编译器参数的语法有点不稳定。

I hate answering my own question, but I finally did manage to get past this problem.我讨厌回答我自己的问题,但我终于设法解决了这个问题。 For those who keep insisting that Maven builds can't possibly be affected by the Class-Path entry in a jar's MANIFEST.MF, please read this article by Michael Bayne.对于那些坚持认为 Maven 构建不可能受 jar 的 MANIFEST.MF 中的 Class-Path 条目影响的人,请阅读 Michael Bayne 的这篇文章 It summarizes the problem and the solution rather nicely.它很好地总结了问题和解决方案。 Hint: javac certainly does care about the embedded classpath in jars.提示:javac 当然关心 jars 中嵌入的类路径。

The trick is to add -Xlint:-path to the compiler arguments, although I was dubious of this solution initially.诀窍是将-Xlint:-path添加到编译器参数中,尽管我最初对这个解决方案持怀疑态度。 Doing this will suppress the bad path element warnings/errors, and therefore Maven won't prematurely halt the build.这样做将抑制坏路径元素警告/错误,因此 Maven 不会过早停止构建。 The problem I had was figuring out the correct syntax for embedding these arguments in the pom.xml.我遇到的问题是找出在 pom.xml 中嵌入这些参数的正确语法。 That's where this article comes in handy.这就是这篇文章派上用场的地方。 Therefore, the compiler plugin's configuration has to look like this to be understood properly:因此,编译器插件的配置必须如下所示才能正确理解:

<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>

Note that this syntax is not very good XML (as Bayne points out), and most IDEs will flag the second Xlint line as an error, but it will work with Maven.请注意,这种语法不是很好的 XML(正如 Bayne 指出的那样),大多数 IDE 会将第二行 Xlint 标记为错误,但它可以与 Maven 一起使用。 Using the syntax given in some Maven tutorials may result in the arguments not being passed to the compiler at all, or only the last argument being passed.使用某些 Maven 教程中给出的语法可能会导致参数根本没有传递给编译器,或者只传递最后一个参数。

Once this problem is taken care of, you may discover other build problems (I certainly did), but at least those problems won't be hidden from you any longer.一旦解决了这个问题,您可能会发现其他构建问题(我确实这样做了),但至少这些问题不会再被您隐藏了。

The problem is that you are referencing a post which is seven years old..and don't use more recent versions of the maven-compiler-plugin :问题是您正在引用一篇已有七年历史的帖子......并且不要使用更新版本的maven-compiler-plugin

The arguments to the javac compiler can better done like this: javac 编译器的参数可以像这样更好地完成:

<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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM