Dry run mode for Ant (ant -n, ant --dry-run)
January 31, 2013 [Java, Tech, Test Driven]I am working on the problem of writing Ant build files in a test-driven way. One thing I found myself needing was a "dry run" mode, like many Unix tools have. For example, make has the -n or --dry-run option, which shows what it would have done, but doesn't really do it.
Today I found a partial solution to this problem, so that you can at least see which dependencies will be run when you run a particular ant target.
It's an horrific hack, but it's the best I can do at the moment.
We write some code in a <script> tag to hack all the targets in our project (at runtime). We modify the targets so they all have an "unless" attribute, set to a property name of "DRY-RUN". Then we set the "DRY-RUN" property, and execute our target.
Ant prints out the names of all the targets in the dependency chain, even if they are not executed because of an unless attribute.
Note: this code makes use of the Ant <script> script tag, which is an Ant 1.8+ feature. Using JavaScript inside this tag seems to be supported in Oracle, OpenJDK and IBM versions of Java, but is not guaranteed.
<?xml version="1.0" encoding="UTF-8"?> <project default="build"> <target name="targetA"/> <target name="targetB" depends="targetA"> <echo message="DON'T RUN ME"/> </target> <target name="targetC" depends="targetB"/> <target name="build" depends="targetB"/> <target name="dry-run"> <do-dry-run target="build"/> </target> <macrodef name="do-dry-run"> <attribute name="target"/> <sequential> <script language="javascript"><![CDATA[ var targs = project.getTargets().elements(); while( targs.hasMoreElements() ) { var targ = targs.nextElement(); targ.setUnless( "DRY.RUN" ); } project.setProperty( "DRY.RUN", "1" ); project.executeTarget( "@{target}" ); ]]></script> </sequential> </macrodef> </project>
Running this build file normally, the tasks in the targets execute, so we can see that the <echo> happens:
$ ant Buildfile: build.xml targetA: targetB: [echo] DON'T RUN ME build: BUILD SUCCESSFUL Total time: 0 seconds
But when we run the dry-run target, only the target names are printed, and the <echo> task (and any other tasks) don't:
$ ant dry-run Buildfile: build.xml dry-run: targetA: targetB: build: BUILD SUCCESSFUL Total time: 0 seconds
A lot of pain, for a partial implementation of very simple functionality that you'd expect to be a built-in feature? I couldn't possibly comment.