1

我希望这能找到一位具有同时使用不同 JDK 版本运行 ANT 经验的 ANT 构建大师!

我继承了一组相当古老的库和 ANT 构建文件,这些文件目前在 Java 6/7 下工作。在尝试使该系统现代化以利用 Java 8 或任何未来的 JDK 升级时,我一直在研究一种重构这些构建文件以使用 Java 8 的方法。

当前的构建系统具有以下特点:

  • 蚂蚁 1.7.0 和 Java 1.7.0_55
  • 通过 ANT APT 任务使用已弃用的 APT 工具
  • 通过 ANT WSGEN 任务使用 wsgen(jaxws 相关库)(例如 classname="com.sun.tools.ws.ant.WsGen")
  • 构建文件有效地混合了代码生成和编译来创建我们想要的输出。

APT 工具在 Java 1.7 中已被弃用,需要在 1.8 及更高版本中使用 JAVAC!

在尝试用 JAVAC 替换 APT 的用法时,我发现不仅该工具被删除,而且与 APT 工具相关的众多包/类/接口也被删除。我已经在多个问答中看到了这里讨论的这个主题,但是大多数提出的解决方案都不是初学者。

我确实发现的一个有希望的建议是将代码生成(APT 的使用)与编译(JAVAC)分开,以驻留在不同的 ANT 构建文件中。将构建文件分成“主”构建文件和“代码生成”构建文件后,这似乎工作得很好。

例子:

    <property name="apt.output.file" value="codegen.apt.${java.version}.log" /> <!-- A different log file will exist when I run the "main" ant build file using Java 7 vs 8 for comparison purposes. -->
    <exec executable="${exec.ant.cmd}" osfamily="unix" failonerror="true" output="${apt.output.file}" >
        <arg line="${ant.apt.cmd.line.options}" />
        <env key="JAVA_HOME" value="${exec.java.home}"/> <!-- Java 1.7 -->
        <env key="ANT_HOME" value="${ant.home.path}"/> <!-- Ant 1.7.0 -->
        <env key="PATH" value="${exec.java.home}/bin" /> <!-- Reset PATH to be certain -->
        <!-- The various properties are defined in the build file, and would be fairly unsurprising. -->
    </exec>

现在“codegen”片段是独立的,这让我可以:

  • 使用 Java 8 运行“主”ANT 构建文件。
  • 对于“codegen”部分,使用上面的 EXEC 来指定 ANT/JAVA 版本来生成 *.java 代码。

对于那些处于类似情况的人来说,好消息是这似乎对 APT 很有效。我将我的 JAVA_HOME & PATH 更改为指向 Java 8,它似乎工作正常(假设 APT 仅限于 *.java 源代码生成,没有编译)。

现在这是问题所在,我希望有人可能对此有所了解。我发现 APT 工具也被用来创建一个 ANT 构建文件(wsgen-build.xml)。所述文件定义了 WSGEN 任务,然后多次使用它:

<project name="some-wsgen-fragment" default="wsgenall">
<target name="wsgenall">
    <taskdef name="wsgen" classname="com.sun.tools.ws.ant.WsGen" >
        <classpath>
            <pathelement path="${jaxws.home}/lib/jaxws-tools.jar" />
        </classpath>
    </taskdef>
    <echo message="wsgen for SomeWebServiceImpl" />
    <wsgen destdir="${classes.server.gen.dir}" sourcedestdir="${something.gen.dir}" sei="com.something.or.other.SomeWebServiceImpl">
        <classpath>
            <pathelement path="${classes.server.gen.dir}" />
            <path refid="classpath.all" />
        </classpath>
    </wsgen>
    ... Repeated usages of wsgen exactly as above, with different classes

与 APT 任务类似,“主”构建文件调用 EXEC 以运行具有适当参数的“旧”ANT,以在其工作的相同环境下调用此生成的构建文件。

在 Java 1.7 和 ANT 1.7.0 下,这可以正常工作。

当我将 Java 更改为 1.8 时,我将 JAVA_HOME 的 JDK 和“java.target”更改为 1.8,我收到以下神秘错误:

  [echo] wsgen for SomeWebServiceImpl
  Finding class com.something.or.other.SomeWebServiceImpl
  [antcall] Exiting codegen-buildfile.xml.

BUILD FAILED
codegen-buildfile.xml:58: The following error occurred while executing this line:
wsgen-build.xml:9: Requires JDK 5.0 or later. Please download it from http://java.sun.com/j2se/1.5/
    at org.apache.tools.ant.ProjectHelper.addLocationToBuildException(ProjectHelper.java:541)
    at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:418)
    at org.apache.tools.ant.taskdefs.CallTarget.execute(CallTarget.java:105)

对我来说,这个问题“感觉”如下:

为什么运行 Java 8 的 ANT 会干扰运行 Java 7 的 ANT,如何解决?

一些问答让我想到了这个问题:

您是否尝试过使用 ANT -v -d 来解决这个问题? 是的,我正在基于用于“主”构建文件的 ${java.version} 生成一个日志文件。我为 Java 8 生成一个文件,为 Java 7 生成一个文件,并对两者进行区分。在我遇到上面提到的错误之前,两者(Java 7 与 Java 8)之间没有环境/属性/设置差异。加载的订单类有细微的变化,但就是这样。

当您在 Java 7 和 Java 8 之间进行更改时,您是否确保更改不会影响您的 EXEC 任务? 上面引用的日志文件的差异验证了这一点,但是当我调用 EXEC 时,上面第一个示例中的属性被有效地硬编码,使用 ENV 标记来确保环境变量也相同,无论使用的 Java 版本如何在“主”构建文件中。

肯定有一些环境变量差异导致了这个问题吗? 我正在记录许多试图诊断问题的变量。到目前为止,“codegen”ANT 构建文件的所有内容都相同,无论“main”ANT 是在 Java 7 还是 8 中运行:ANT_HOME、JAVA_HOME、PATH、ant.version、java.version、java.vm.version、 java.class.path,java.ext.dirs。详细的 ANT 日志也证明了这一点,它们之间没有属性/环境/类路径问题。

我无法从您的 EXEC 示例中看出,但是您使用的是完整路径吗?也许 PATH 变量是一个问题? 虽然未显示,但我指定了 ANT 和 JAVA 的完整路径,因为我需要准确指定 ANT/JDK 以确保运行所需的特定版本。

您如何使用有问题的 wsgen 任务 (wsgen-build.xml) 调用生成的构建文件? 根据上面的示例,“主”构建文件在“codegen”构建文件上调用 EXEC。唯一的区别是不同的构建目标,一个目标用于 APT,另一个用于 WSGEN 片段。在“codegen”构建文件中的上述 WSGEN 目标中,当前导入了 wsgen-build.xml,并通过 ANTCALL 调用了目标。我也试过只使用 ANT 任务,两者都有相同的结果。

您可以从命令外壳运行您的 EXEC 命令吗? 是的,如果我在命令行上运行该步骤,它是否有效取决于 Java 7 或 8 是否设置为 JAVA_HOME 并且首先出现在 PATH 中。例如,如果我将 JAVA_HOME 更新为 Java 8,则会收到以下错误:java.lang.NoClassDefFoundError: com/sun/mirror/apt/AnnotationProcessorFactory。这是正确的,因为该类不再存在于 Java 8 中(但确实存在于 7 中)。

您是否尝试过使用脚本或批处理文件而不是在 ANT 可执行文件上使用 EXEC? 是的,导致了同样的错误。我尝试使用一个简单的 .bat 文件来设置必要的环境变量并从 shell 调用命令。

您使用的是什么操作系统,您是否尝试过不同的机器/操作系统来查看这是否是特定于环境的? 我有一个 Win7 和一个 RHEL 7 环境,这个问题发生在两个环境中,我使用 osfamily 属性对每个平台的 EXEC 命令进行条件化。

Ant 1.7.0 已经很老了,你试过更新的 Ant 吗? 使用 Ant 1.9.4 也会出现同样的问题。1.9.4 Ant 仅针对“main”构建文件运行,“codegen”构建文件将使用 1.7.0,因为我通过 EXEC 任务明确设置了它。我确实尝试了 1.9.4,即使是“codegen”ant 构建文件,但它对错误没有任何影响。

如果您设法通读了全文,先生或女士,我向您致敬!感谢您提供的任何见解/建议!

4

0 回答 0