继续ANT在构建错误后停止的位置

时间:2012-10-25 20:28:41

标签: java android ant build build-process

我有一个ant构建脚本,可以构建许多android个项目。

我正按照文本文件中的属性给我的特定顺序构建所有项目。

ant构建脚本调用每个项目自己的build.xml文件来构建该项目。

如果某个项目无法构建,我怎能让ant继续构建它因错误而停止的位置?

基本上,如果我正在构建项目ABCDE。并且构建过程在C处失败,当开发人员再次启动构建时,我可以做些什么来使构建过程在C继续?

此外,构建过程需要重建开发人员更改的内容。例如,C中的问题是由于A中的问题,C取决于A。因此,需要重建A,跳过B,然后重建C并继续。 o.O

寻找想法或者是否已经有了这样做。

谢谢!

2 个答案:

答案 0 :(得分:2)

Ant,就像Make一样,非常擅长在你离开时找出继续的地方。除非更新源,否则<javac>任务不会重新编译代码。默认情况下,<copy>任务不会重新复制文件。但是,如果您将构建分解为多个文件,然后使用<ant>任务而不是使用depends的{​​{1}}参数,则会破坏此系统。

假设您有独立项目 A B C D 。您<target>所做的就是在每个build.xml中调用正确的目标。假设每个都构建一个jar文件。由于Java错误,该过程在项目 C 上破坏了。开发人员修复了它。您再次运行build.xml,它将再次调用项目 A B 。但是,由于这些项目已经建成,它们不应该做任何事情。您会看到对 A B 的调用,但不会发生任何事情。

即使在项目 C 中,构建过程也会从停止的位置开始。也就是说,如果你没有采取任何措施来破坏Ant的构建能力。

有许多方法可以打破Ant。例如,不要在构建过程中删除文件。如果目标文件不再存在,Ant就无法使用时间戳来确定要执行的操作。

有时,一个过程需要一些帮助来避免构建。 Ant有一个内置的<uptodate>任务,但我发现<outofdate>更容易使用。例如,假设Project A 生成Project B 使用的jar文件。如果jar中使用的类文件和资源早于jar上的时间戳,您可能希望使用其中一个任务来复制该jar。

否则,如果你只是盲目地将jar复制到Project B ,Project B 将会看到classfiles所依赖的文件已经更新。因此,Project B 将重新编译所有内容。然后复制一切,重建它正在建造的任何罐子或战争。我遇到了third party task直接更新Java类文件的问题,并且必须使用监视文件来确保我没有运行编译两次,或者特别是那个使用类文件的任务。

顺便说一下,不要对目标蚂蚁说它正在执行的人感到沮丧。 Ant将执行这些目标,但构成这些目标的任务将不会运行,除非更新某些内容。


更新:使用来自Ant-Contrib的<outofdate>

假设在您的主项目文件中,您有以下目标:

<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>任务仍然必须遍历所有文件并进行日期比较,但至少您没有看到它调用子项目文件中的所有目标。

答案 1 :(得分:1)

尽可能尝试使您的个人项目构建idempotent(即,如果您重新运行构建,并且自上次以来没有任何更改,那么它不必重建所有内容)。像javaccopy这样的标准任务已经像这样工作,例如javac只重新编译比其对应的.java更新的.class个文件。对于不进行自己的依赖性检查的情况,您可以使用uptodate任务自行进行检查。 manual page for uptodate中有一些示例说明了如何执行此操作。

这个想法是让每个构建完成它必须做的最小工作,以便使所有内容都更新。如果你能做到这一点那么重建C会导致AB再次运行并不重要,因为如果它们实际上没有任何东西它们会很快完成要做。