在公共依赖项中的 -post-jar 中多次添加自定义清单

Custom manifest added multiple times in -post-jar in a common dependency

我有一个多模块原生 Netbeans Java EE 项目。在其中我有一个 Java Class Library 项目,该项目被多个其他项目使用,这些项目又被打包到根 .ear 项目中。

我正在使用库的 build.xml:

将 "build timestamp" 和 "build user" 属性添加到自定义清单
<target name="-post-jar">   
    <jar destfile="${dist.jar}" update="true">
        <manifest>

当我"clean and build"根项目时,引用库的每个项目调用:

<ant antfile="${call.script}" target="jar">

我的 -post-jar 目标被多次调用。这不是问题,但有时 <jar> 任务的第二次调用会因 Unable to rename old file 而失败(可能是由于 Netbeans 在后台扫描文件,但我不能确定)。

Ant 的输出中有重复的 Building jarUpdating jar 消息对。但是,如果我删除我的 -post-jar 目标,第二次调用 jar 目标不会执行任何操作,因为它认为 jar 是最新的并且我只看到一个 Building jar 消息。

如何将更新的 jar 标记为最新,以便 jar 目标的第二次调用不执行任何操作?

有一个 github repo 证明了这个问题。

我还没有找到一种方法不是每次都重新生成清单,但我找到了一种方法使生成的文件看起来与压缩文件相同(我们知道当内容相同时 <jar> 任务不会重新打包。

我现在更新 -pre-jar 中的源文件,而不是更新 -post-jar 中的压缩清单。通过这种方式,清单的最终版本被压缩,并且由于其内容在构建期间不会更改,因此后续 <jar> 调用不会更新任何内容。

值得一提的是,在添加属性Main-ClassProfile等之前,Netbeans的build-impl.xml会创建一个empy清单模板,如果用户没有提供有效的manifest.file= 属性 中的路径。添加发生在 -pre-jar 之后,但是在 init 目标期间会更早地检查用户提供的清单是否存在,并将结果保存到 manifest.available 属性.

我的清单模板不是静态文件。它包含 "build timestamp" 和 "build user" 属性。因此该文件在 init 目标期间不存在,因此我不得不在 build.xml:

的开头添加以下行
<property name="manifest.available" value="true"/><!-- It will be available by the time we need it -->

其次,manifest.file 仍然需要设置,我将其设置为 project.properties(该设置还没有 UI,我想知道它在存在的情况下会如何表现路径中的变量)

manifest.file=${build.dir}/manifest.tmp

接下来,我覆盖 -pre-jar 目标中的清单模板:

<tstamp>
    <format property="current.time" pattern="HH:mm:ss" locale="de,DE"/>
</tstamp>

<target name="-pre-jar" >
        <manifest file="${manifest.file}">
            <attribute name="MyApp-built-time" value="${current.time}"/>
            <attribute name="MyApp-built-by" value="${user.name}"/>
        </manifest> 

之后,新问题变得明显:每次调用的时间戳都不一样

<ant antfile="mylib/build.xml" target="jar">

在多模块项目中,Ant 必须使用清单中的新时间戳重新打包 jar。我通过在每个项目的 build.xml 中定义时间戳 属性 来解决这个问题。尽管由于 inheritall="false" 而无法继承属性,但 Netbeans 允许克服以下问题:

<property name="transfer.current.time" value="${current.time}"/>

此机制在 Java 个 EE 项目中被破坏,但解决方法很简单:

<presetdef name="ant">
    <!-- workaround transfer.* not working in Java EE projects -->
    <ant>
        <propertyset>
            <propertyref prefix="transfer."/>
            <mapper from="transfer.*" to="*" type="glob"/>
        </propertyset>
    </ant>
</presetdef>