与 Make 一样,Ant 非常擅长在您停止时确定从哪里继续。除非更新源,否则该<javac>
任务不会重新编译代码。默认情况下,该<copy>
任务不会重新复制文件。但是,如果您将构建分解为多个文件,然后使用<ant>
任务而不是使用您的depends
参数<target>
,您将破坏这个系统。
假设您有独立的项目A、B、C和D。你build.xml
所做的就是在每一个中调用正确的目标。假设每个人都构建了一个 jar 文件。由于 Java 错误,该过程在项目C上中断。开发商修好了。你build.xml
再次运行你的,它会再次调用项目A和B。但是,由于这些项目已经建成,他们不应该做任何事情。您会看到对A和B的调用,但什么都不会发生。
即使在项目C中,构建过程也会从它停止的地方开始。也就是说,如果您没有做任何事情来破坏 Ant 计算其构建的能力。
破解 Ant 的方法有很多。例如,不要在构建过程中删除文件。如果目标文件不再存在,Ant 就无法使用时间戳来确定要做什么。
有时,流程需要一些帮助来避免构建。Ant 有一个内置<uptodate>
任务,但我发现它<outofdate>
更容易使用。例如,假设项目A生成项目B使用的 jar 文件。如果 jar 中使用的类文件和资源早于 jar 上的时间戳,您可能希望使用这些任务之一不复制该 jar。
否则,如果您只是盲目地将 jar 复制到 Project B,Project B将看到类文件所依赖的文件已更新。因此,项目B将重新编译所有内容。然后复制所有内容,并重建它正在构建的任何罐子或战争。我遇到了直接更新 Java 类文件的第三方任务的问题,并且不得不使用监视文件来确保我没有运行两次编译,尤其是处理类文件的任务。
顺便说一句,不要对 Ant 所说的正在执行的目标感到不安。Ant 将执行这些目标,但构成这些目标的任务将不会运行,除非更新某些内容。
更新:使用<outofdate>
来自 Ant-Contrib
假设在您的主项目文件中,您有以下目标:
<target name="build"
description="Builds every sub project">
<ant antfile=${project.a.dir}/build.xml target="build"/>
<ant antfile=${project.b.dir}/build.xml target="build"/>
<ant antfile=${project.c.dir}/build.xml target="build"/>
<ant antfile=${project.d.dir}/build.xml target="build"/>
使用<outofdate>
:
<target name="build"
description="Builds every sub project">
<outofdate>
<sourcefiles>
<fileset dir="${project.a.srcdir}"/>
</sourcefiles>
<targetfiles>
<fileset dir="${project.a.dir}/target">
<include name="*.jar"/>
</fileset>
</targetfiles>
<sequential>
<ant antfile=${project.a.dir}/build.xml
target="build"/>
</sequential>
</outofdate>
<outofdate>
<sourcefiles>
<fileset dir="${project.b.srcdir}"/>
</sourcefiles>
<targetfiles>
<fileset dir="${project.a.dir}/target">
<include name="*.jar"/>
</fileset>
</targetfiles>
<sequential>
<echo>CALLING PROJECT: ${project.b.dir}</echo>
<ant antfile=${project.b.dir}/build.xml
target="build"/>
</sequential>
</outofdate>
<etc, etc, etc/>
如果设置正确,您可能可以在 Ant-Contrib<for>
循环中完成整个操作,因此您不必为每个子项目都这样做。
我不知道这是否更快。该<outofdate>
任务仍然需要遍历所有文件并进行日期比较,但至少您没有看到它调用了子项目文件中的所有目标。