I have an ant
build script that builds many android
projects.
I am building all the projects in a specific order given to me by a property in a text file.
The ant
build script calls each project's own build.xml
file to build that project.
If a project fails to build, how could i have ant
continue to build from where it stopped because of the error?
Basically if i am building projects A
, B
, C
, D
and E
. And the build process fails at C
, what could i do to have the build process continue at C
, when the developer starts the build again?
Also, the build process would need to rebuild stuff that was changed by the developer. For instance, the problem in C
was because of an issue in A
, and C
depends on A
. So, it would need to rebuild A
, skip B
, and rebuild C
and continue. o.O
Looking for ideas or if there is already something that does this.
Thanks!
Ant, like Make, is pretty good at figuring out where to continue when you left off. The <javac>
task won't recompile code unless the source is updated. The <copy>
task won't recopy a file by default. However, if you break up your build into multiple files, and then use <ant>
tasks instead of using the depends
parameter of your <target>
, you will break this system.
Let's say you have independent projects A, B, C, and D. All your build.xml
does is call the correct target in each one. Let's say each builds a jar file. And the process broke on project C because of a Java error. The developer fixed it. You run your build.xml
again, and it will call projects A and B again. However, since these projects have already been built, they shouldn't be doing anything. You'll see the calls to A and B, but nothing will happen.
Even in project C, the build process will start where it left off. That is, if you didn't do anything to break Ant's ability to figure out its build.
There are many ways to break Ant. For example, don't delete files during the build process. If the target files are no longer there, Ant can't use timestamps to figure out what to do.
Sometimes, a process needs a little help for build avoidance. Ant has a built in <uptodate>
task, but I find the <outofdate>
much easier to use. For example, let's say that Project A produces a jar file that Project B uses. You might want to use one of these tasks not to copy that jar if the classfiles and resources used in the jar are older than the timestamp on the jar.
Otherwise, if you just blindly copied the jar to Project B, Project B will see that a file the classfiles depend upon has been updated. Thus, Project B will recompile everything. Then copy everything, and rebuild whatever jar or war it was building. I had a problem with a third party task that updated the Java classfiles directly, and had to use monitoring files to make sure I didn't run the compile twice or especially the task that munges the classfiles.
By the way, don't get upset at the targets Ant is saying it's executing. Ant will execute those targets, but the tasks that make up those targets won't run unless something was updated.
<outofdate>
From Ant-ContribLet's say in your Master project file, you have the following target:
<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"/>
Use <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/>
If things are setup correctly, you could probably do the whole thing in an Ant-Contrib <for>
loop, so you don't have to do this for each sub-project.
I don't know if this is any faster. The <outofdate>
task still has to go through all of the files and do a date comparison, but at least you don't see it calling all the targets in your sub-project file.