删除文件时重建ant

时间:2013-06-26 14:59:35

标签: ant rebuild

我正在使用Ant构建项目,并希望在源更改时重新编译。除了一个案例之外,这主要与标准的javac-task一起自动运行:

删除源文件但未进行其他更改时,不会重新编译任何内容。

即使这会使项目无法在没有错误的情况下进行干净编译,但由于留下了类文件,构建仍然会成功。

每次都做一个干净的构建不是一个选择,因为我们有137个依赖模块需要很长时间才能构建。此外,我们不希望在完全清理后重试每个失败的CI构建,看它是否会起作用。

这似乎是一个非常基本的东西应该由javac-task支持,但我没有看到任何看起来有用的属性。在尝试了我能想到的任何其他事情之后,我无法做到正确:

找出是否有遗留类:

<difference id="targets.todelete">
  <union>
    <mappedresources>
      <fileset dir="${src.java.dir}" includes="**/*.java" />
      <globmapper from="*.java" to="*.class" />
    </mappedresources>
  </union>
  <union>
    <fileset dir="${build.java.dir}" includes="**/*.class" />
  </union>
</difference>

以上不起作用,差异实际上似乎更像是一个联盟。如果java文件具有相应的类文件,则差异中的类文件将有两个条目。

这是另一次尝试:

<fileset id="del" dir="${src.java.dir}" includes="**/*.java" casesensitive="false" defaultexcludes="false">
  <different targetdir="${build.java.dir}" ignoreFileTimes="true">
    <globmapper from="*.java" to="*.class" />
  </different>
</fileset>

我试图找到所有不同的文件,但结果或多或少与上面相同。

当我在没有映射器的情况下尝试使用部分重叠的源文件集时,它确实按预期工作。这使我怀疑与资源差异有关的任何事情都不能很好地与映射文件一起使用。

有没有人知道如何以任何其他方式实现我的目标?

更新 这是正确处理内部类的工作解决方案。 我需要多个源目录,这会使事情变得更复杂。

<!-- find class files with without corresponding source files -->
<fileset id="src1" dir="${src.java.dir}" includes="**/*.java" />
<fileset id="src2" dir="${build.generated.java.dir}" includes="**/*.java" erroronmissingdir="no" />
<fileset id="src3" dir="${generated.java.dir}" includes="**/*.java" erroronmissingdir="no" />

<fileset id="build" dir="${build.java.dir}" includes="**/*.class" erroronmissingdir="no" />
<difference id="targets.todelete">
  <resourcelist>
    <string>${toString:src1};${toString:src2};${toString:src3}</string>
    <filterchain>
      <tokenfilter>
        <replacestring from=";" to="${line.separator}" />
        <replacestring from=".java" to=".class" />
      </tokenfilter>
      <ignoreblank/>
      <prefixlines prefix="${build.java.dir}/" />
    </filterchain>
  </resourcelist>
  <resourcelist>
    <string>${toString:build}</string>
    <filterchain>
      <tokenfilter>
        <replacestring from=";" to="${line.separator}" />
        <!-- map inner classes back to their java files -->
        <replaceregex pattern="\$.*(.class)" replace="\1" flags="gi"/>
      </tokenfilter>
      <prefixlines prefix="${build.java.dir}/" />
    </filterchain>
  </resourcelist>
</difference>

<if>
  <not>
    <length string="${toString:targets.todelete}" trim="true" length="0" />
  </not>
  <then>
    <echo>Source files were deleted, cleaning output to force re-build!</echo>
    <delete dir="${build.java.dir}" />
    <delete dir="${build.test.java.dir}" />
    <delete dir="${cobertura_html_report.dir}" />
  </then>
</if>

1 个答案:

答案 0 :(得分:1)

问题是difference资源集合根据绝对路径而不是相对路径来区分差异。并且没有办法让Ant将映射器应用于完整的绝对路径。它只适用于资源名称。

解决方案是将文件集序列化为字符串列表,对该字符串列表进行适当的更改,然后将它们解释为差异文件。

这是建议的build.xml片段,它应该计算正确的类文件列表:

<fileset id="src" dir="${src.java.dir}" includes="**/*.java"/>

<fileset id="build" dir="${build.java.dir}" includes="**/*.class"/>

<difference id="targets.todelete">
    <resourcelist>
        <string>${toString:src}</string>
        <filterchain>
            <tokenfilter>
                <replacestring from=";" to="${line.separator}" />
                <replacestring from=".java" to=".class" />
            </tokenfilter>
            <prefixlines prefix="${build.java.dir}" />
        </filterchain>
    </resourcelist>
    <resourcelist>
        <string>${toString:build}</string>
        <filterchain>
            <tokenfilter>
                <replacestring from=";" to="${line.separator}" />
            </tokenfilter>
            <prefixlines prefix="${build.java.dir}" />
        </filterchain>
    </resourcelist>
</difference>