Running Ant
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This page is written against Apache Ant 1.10.18 (the 1.10.x line runs on JDK 8 and later). Every example was run on JDK 26
on 2026-10-16 with the Ant 1.10.18 distribution unpacked in a scratch directory and the ant launch script on the PATH. The
build file is the small build.xml for the tidepool-model library, one module of the scenario used across this section; paths
in console output were shortened to /work/tidepool-model. The tool is installed on
Installation; the build file itself is explained on
Build File Structure.
The shape of the command
ant [options] [target [target2 [target3] ...]]
The ant script (ant on Unix, ant.bat or ant.cmd on Windows) finds Java, builds a minimal class path and starts
org.apache.tools.ant.launch.Launcher, which in turn starts Ant proper. Everything after the options is a list of targets.
With no targets, Ant runs the default target named on the <project> element; with no -f option it looks for build.xml
in the current directory. The command is the same in a terminal and in continuous integration (see
CI & IDE Integration).
The examples below use this build file. It has a default target, descriptions, a deliberately failing target and a target that reads from the console, which together exercise the options.
<?xml version="1.0" encoding="UTF-8"?>
<project name="tidepool-model" default="jar" basedir=".">
<description>Tide height model library.</description>
<property name="src.dir" location="src/main/java"/>
<property name="build.dir" location="build"/>
<property name="classes.dir" location="${build.dir}/classes"/>
<property name="greeting" value="built with Ant ${ant.version}"/>
<target name="clean" description="delete the build directory">
<delete dir="${build.dir}"/>
</target>
<target name="compile" description="compile the sources">
<mkdir dir="${classes.dir}"/>
<javac srcdir="${src.dir}" destdir="${classes.dir}" release="21" includeantruntime="false"/>
</target>
<target name="jar" depends="compile" description="package the JAR">
<jar destfile="${build.dir}/tidepool-model.jar" basedir="${classes.dir}"/>
<echo message="${greeting}"/>
</target>
<target name="broken" description="fails on purpose">
<fail message="deliberate failure"/>
</target>
<target name="after-broken" depends="broken"/>
<target name="independent" description="does not depend on broken">
<echo>independent target ran</echo>
</target>
<target name="props" description="show where properties come from">
<echo>greeting=${greeting} tmpdir=${ant.tmpdir} version=${project.version}</echo>
</target>
<target name="ask" description="read a value from the console">
<input message="Station id?" addproperty="station" defaultvalue="SF"/>
<echo>station=${station}</echo>
</target>
</project>
Running ant with no arguments compiles and packages, because jar is the default target and depends on compile:
$ ant
Buildfile: /work/tidepool-model/build.xml
compile:
[mkdir] Created dir: /work/tidepool-model/build/classes
[javac] Compiling 1 source file to /work/tidepool-model/build/classes
jar:
[jar] Building jar: /work/tidepool-model/build/tidepool-model.jar
[echo] built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026
BUILD SUCCESSFUL
Total time: 0 seconds
Source: Apache Ant manual: Command Line
Options at a glance
ant -help prints the list of options. The output below is the one printed by 1.10.18, including the three script options that
only the Unix wrapper accepts.
$ ant -help
ant [script options] [options] [target [target2 [target3] ..]]
Script Options:
--help, --h print this message and ant help
--noconfig suppress sourcing of /etc/ant.conf,
$HOME/.ant/ant.conf, and $HOME/.antrc
configuration files
--usejikes enable use of jikes by default, unless
set explicitly in configuration files
--execdebug print ant exec line generated by this
launch script
ant [options] [target [target2 [target3] ...]]
Options:
-help, -h print this message and exit
-projecthelp, -p print project help information and exit
-version print the version information and exit
-diagnostics print information that might be helpful to
diagnose or report problems and exit
-quiet, -q be extra quiet
-silent, -S print nothing but task outputs and build failures
-verbose, -v be extra verbose
-debug, -d print debugging information
-emacs, -e produce logging information without adornments
-lib <path> specifies a path to search for jars and classes
-logfile <file> use given file for log
-l <file> ''
-logger <classname> the class which is to perform logging
-listener <classname> add an instance of class as a project listener
-noinput do not allow interactive input
-buildfile <file> use given buildfile
-file <file> ''
-f <file> ''
-D<property>=<value> use value for given property
-keep-going, -k execute all targets that do not depend
on failed target(s)
-propertyfile <name> load all properties from file with -D
properties taking precedence
-inputhandler <class> the class which will handle input requests
-find <file> (s)earch for buildfile towards the root of
-s <file> the filesystem and use it
-nice number A niceness value for the main thread:
1 (lowest) to 10 (highest); 5 is the default
-nouserlib Run ant without using the jar files from
${user.home}/.ant/lib
-noclasspath Run ant without using CLASSPATH
-autoproxy Java1.5+: use the OS proxy settings
-main <class> override Ant's normal entry point
The sections that follow group the options by what they do. Neither Maven nor Gradle has an equivalent single-letter zoo: the Maven options are on Running Maven (CLI) and the Gradle ones on Command-Line Interface.
Information options
-version prints the version and exits. -help (or -h) prints the table above. -diagnostics prints a report meant to be
pasted into a bug report: the Ant version, the jars in ANT_HOME/lib and in ${user.home}/.ant/lib, which optional tasks are
unavailable because a library is missing, the XML parser and XSLT processor in use, the system properties, the temporary
directory and the proxy settings.
$ ant -version
Apache Ant(TM) version 1.10.18 compiled on September 3 2026
The start of the diagnostics report, and the "Tasks availability" section that explains most "task not found" surprises, look like this (the full report is a few hundred lines; the elisions are marked):
$ ant -diagnostics
------- Ant diagnostics report -------
Apache Ant(TM) version 1.10.18 compiled on September 3 2026
-------------------------------------------
Implementation Version
-------------------------------------------
core tasks : 1.10.18 in file:/opt/apache-ant-1.10.18/lib/ant.jar
[...]
-------------------------------------------
USER_HOME/.ant/lib jar listing
-------------------------------------------
user.home: /home/user
No such directory.
-------------------------------------------
Tasks availability
-------------------------------------------
sshsession : Missing dependency com.jcraft.jsch.Logger
scp : Missing dependency com.jcraft.jsch.Logger
image : Missing dependency javax.media.jai.PlanarImage
jdepend : Missing dependency jdepend.textui.JDepend
xz : Missing dependency org.tukaani.xz.FilterOptions
sshexec : Missing dependency com.jcraft.jsch.Logger
ftp : Missing dependency org.apache.commons.net.ftp.FTPConnectionClosedException
A task being missing/unavailable should only matter if you are trying to use it
[...]
The user.home line was replaced by a placeholder here; the report is otherwise unedited. The jars to add to fix each missing
dependency are in the optional-library table on
Installation.
-projecthelp (-p) lists the targets of the build file and exits without running anything. A target with a description
attribute is listed under "Main targets"; targets without one are "Other targets" and are shown only when there are no main
targets or when -verbose or -debug is also given. The project <description> is printed first.
$ ant -projecthelp
Buildfile: /work/tidepool-model/build.xml
Tide height model library.
Main targets:
ask read a value from the console
broken fails on purpose
clean delete the build directory
compile compile the sources
independent does not depend on broken
jar package the JAR
props show where properties come from
Default target: jar
Adding -v also lists after-broken under "Other targets", because it has no description. This is why a build file meant to
be used by others gives a description to every target that is a public entry point and none to internal ones; see
Targets & Extension Points.
Source: Apache Ant manual: Command Line
Choosing the build file
-buildfile <file> (also -file and -f) names the build file. If the argument is a directory, Ant uses the build.xml in
it. The default is build.xml in the current directory. The file name is arbitrary; the examples run noasc.xml, a one-target
file, and the project directory itself:
$ ant -f noasc.xml
Buildfile: /work/tidepool-model/noasc.xml
hi:
[echo] hi from noasc
BUILD SUCCESSFUL
Total time: 0 seconds
A file that does not exist is not an Ant error with a stack trace; it is a short message and exit code 1:
$ ant -f nofile.xml
Buildfile: nofile.xml does not exist!
Build failed
-find [file] (also -s) searches for the build file in the current directory, then in its parent, and so on up to the root
of the file system. By default it looks for build.xml. This is how a build can be started from any subdirectory of a
single-build-file project. The catch, stated in the
manual, is that if more options follow -find, the file name argument is required even when it is build.xml, because the
next word would otherwise be consumed as the name. From a subdirectory two levels below the project:
$ ant -find build.xml -q jar
[echo] built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026
BUILD SUCCESSFUL
Total time: 0 seconds
$ ant -s -q jar
Searching for -q ...
Could not locate a build file!
$ ant -q jar
Buildfile: build.xml does not exist!
Build failed
The second command is the classic mistake: -s swallowed -q as the file name to search for. The third shows plain ant not
looking upwards. The same rule applies to -find inside ANT_ARGS, described below.
Ant sets the basedir of the project to the directory containing the build file unless the basedir attribute says
otherwise, so relative paths in the build file are relative to the build file, not to the current directory. That is why the
same build behaves identically when started with -f ../other/build.xml from elsewhere.
Source: Apache Ant manual: Command Line
Selecting targets
Targets are listed after the options and run in order, each one after the targets it depends on, and each target at most once
per invocation. ant clean jar runs clean, then compile and jar. A target name that does not exist fails the build
before anything runs:
$ ant nosuch
Buildfile: /work/tidepool-model/build.xml
BUILD FAILED
Target "nosuch" does not exist in the project "tidepool-model".
Total time: 0 seconds
A failing task stops the build at the first failure. The error line names the build file and the line of the failing task
(build.xml:25, the <fail>):
$ ant broken
Buildfile: /work/tidepool-model/build.xml
broken:
BUILD FAILED
/work/tidepool-model/build.xml:25: deliberate failure
Total time: 0 seconds
-keep-going (-k) changes that: after a target fails, Ant carries on with the other requested targets that do not depend on
the failed one. It still ends with BUILD FAILED and exit code 1.
$ ant -k after-broken independent
Buildfile: /work/tidepool-model/build.xml
broken:
Target 'broken' failed with message 'deliberate failure'.
Cannot execute 'after-broken' - 'broken' failed or was not executed.
independent:
[echo] independent target ran
BUILD FAILED
/work/tidepool-model/build.xml:25: deliberate failure
Total time: 0 seconds
-k is useful on a continuous integration server that should report as many independent failures as possible in one run,
and in a build with several unrelated test targets. For target conditions (if, unless) and the lifecycle-like
extension points, see Targets & Extension Points.
Source: Apache Ant manual: Command Line
Defining properties
-D<property>=<value> sets a property. Properties set on the command line are user properties: they cannot be overridden
by a <property> task in the build file, because properties in Ant are immutable once set and the command line sets them
first. That is how a build file’s defaults (<property name="greeting" .../>) are overridden from outside. The props target
prints a few:
$ ant -Dgreeting=hello props
Buildfile: /work/tidepool-model/build.xml
props:
[echo] greeting=hello tmpdir=${ant.tmpdir} version=${project.version}
BUILD SUCCESSFUL
Total time: 0 seconds
An unset property is not an error: the text ${ant.tmpdir} is left as is, which is the most common reason for a path like
${build.dir}/classes appearing literally in a directory listing. ant -v adds a line for each one that is used and unset
(Property "ant.tmpdir" has not been set). Environment variables can be passed with -DMYVAR=$MYVAR (Unix) or
-DMYVAR=%MYVAR% (Windows), or read inside the build file with <property environment="env"/>; how properties are
resolved is on Properties.
-propertyfile <name> loads every property in a file as if each had been given with -D, so they too are user properties.
When both are present the -D value wins. With this release.properties:
project.version=1.2.0
greeting=from the property file
$ ant -propertyfile release.properties props
Buildfile: /work/tidepool-model/build.xml
props:
[echo] greeting=from the property file tmpdir=${ant.tmpdir} version=1.2.0
BUILD SUCCESSFUL
Total time: 0 seconds
$ ant -propertyfile release.properties -Dgreeting=cli props
Buildfile: /work/tidepool-model/build.xml
props:
[echo] greeting=cli tmpdir=${ant.tmpdir} version=1.2.0
BUILD SUCCESSFUL
Total time: 0 seconds
The Maven counterpart is -Dkey=value (system properties read by plugins) and the Gradle one is -Pname=value for project
properties and -D for JVM system properties; see
Comparing Ant, Maven & Gradle.
Source: Apache Ant manual: Command Line
Controlling the output
Four options change the amount of logging, in order of increasing volume: -silent (-S) prints only task output and build
failures, -quiet (-q) prints less than normal, the default, -verbose (-v) and -debug (-d). The messages Ant
prints are produced at the levels error, warn, info, verbose and debug; tasks choose a level for each message (the
<echo> task has a level attribute), and the option decides how many levels reach the screen.
$ ant -q clean jar
[echo] built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026
BUILD SUCCESSFUL
Total time: 0 seconds
$ ant -S clean jar
Buildfile: /work/tidepool-model/build.xml
built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026
-S is the option to use when a script captures Ant’s output: little but what the tasks print remains (here the <echo> text,
with no [echo] prefix, after the Buildfile: line that 1.10.18 still prints).
-verbose shows, for this build, the version, the Java and OS detected, how the build file was found, the parsing of the
build file, the base directory, the build sequence and every unset property that is used. -debug adds a message for each
property set, each class loaded and each task configured. Both are the first thing to try when a build does something
unexpected; the build sequence line is a quick way to see which targets will run and in which order.
$ ant -v props
Apache Ant(TM) version 1.10.18 compiled on September 3 2026
Trying the default build file: build.xml
Buildfile: /work/tidepool-model/build.xml
Detected Java version: 26 in: /Library/Java/JavaVirtualMachines/jdk-26.jdk/Contents/Home
Detected OS: Mac OS X
parsing buildfile /work/tidepool-model/build.xml with URI = file:/work/tidepool-model/build.xml
Project base dir set to: /work/tidepool-model
parsing buildfile jar:file:/opt/apache-ant-1.10.18/lib/ant.jar!/org/apache/tools/ant/antlib.xml with URI = jar:file:/opt/apache-ant-1.10.18/lib/ant.jar!/org/apache/tools/ant/antlib.xml from a zip file
Build sequence for target(s) `props' is [props]
Complete build sequence is [props, broken, after-broken, compile, jar, ask, independent, clean, ]
props:
Property "ant.tmpdir" has not been set
Property "project.version" has not been set
[echo] greeting=built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026 tmpdir=${ant.tmpdir} version=${project.version}
BUILD SUCCESSFUL
Total time: 0 seconds
-emacs (-e) removes the [task] prefix and the indentation so that each message starts at column 0. It was designed for
editors that parse compiler messages from the log and for tools that dislike the leading spaces:
$ ant -e clean jar
Buildfile: /work/tidepool-model/build.xml
clean:
Deleting directory /work/tidepool-model/build
compile:
Created dir: /work/tidepool-model/build/classes
Compiling 1 source file to /work/tidepool-model/build/classes
jar:
Building jar: /work/tidepool-model/build/tidepool-model.jar
built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026
BUILD SUCCESSFUL
Total time: 0 seconds
-logfile <file> (also -l) sends the output to a file instead of the console. Nothing is printed to the terminal, and the
file receives exactly what the console would have shown at the chosen level:
$ ant -logfile build.log -q jar
$ cat build.log
[echo] built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026
BUILD SUCCESSFUL
Total time: 0 seconds
Source: Apache Ant manual: Command Line
Loggers, listeners and input handlers
A logger formats and prints the build’s messages; a listener is notified of build events (target started, task finished,
message logged) and may do anything. -logger <classname> replaces the default logger (org.apache.tools.ant.DefaultLogger)
and there can be only one. -listener <classname> adds a listener, and there can be several. Ant ships several in
org.apache.tools.ant.listener (for example TimestampedLogger, AnsiColorLogger, MailLogger, BigProjectLogger,
ProfileLogger) and org.apache.tools.ant (XmlLogger, NoBannerLogger); -logger takes the first kind:
$ ant -logger org.apache.tools.ant.listener.TimestampedLogger -q jar
[echo] built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026
BUILD SUCCESSFUL - at 16/10/26, 11:34
Total time: 0 seconds
Passing a logger class to -listener is the classic mistake. Loggers are also listeners, but a logger given to -listener
is never handed an output stream (that is done for the logger chosen with -logger), and the build ends with a stack trace
after the "BUILD SUCCESSFUL" line and exit code 1:
$ ant -listener org.apache.tools.ant.listener.TimestampedLogger -q jar
[echo] built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026
BUILD SUCCESSFUL
Total time: 0 seconds
Caught an exception while logging the end of the build. Exception was:
java.lang.NullPointerException: Cannot invoke "java.io.PrintStream.println(String)" because "stream" is null
at org.apache.tools.ant.DefaultLogger.printMessage(DefaultLogger.java:325)
at org.apache.tools.ant.DefaultLogger.buildFinished(DefaultLogger.java:184)
at org.apache.tools.ant.Project.fireBuildFinished(Project.java:2116)
at org.apache.tools.ant.Main.runBuild(Main.java:830)
at org.apache.tools.ant.Main.startAnt(Main.java:223)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:284)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:101)
Writing your own logger or listener is covered on Listeners, Loggers & Input Handlers, which also lists every provided class.
-noinput tells Ant that nobody is at the keyboard, so tasks such as <input> must not wait. With -noinput the ask target
fails at once instead of hanging a CI job:
$ ant -noinput ask
Buildfile: /work/tidepool-model/build.xml
ask:
[input] Station id? [SF]
BUILD FAILED
/work/tidepool-model/build.xml:38: Failed to read input from Console.
Total time: 0 seconds
Without the option, a piped answer is read from the standard input:
$ echo 'X' | ant ask
Buildfile: /work/tidepool-model/build.xml
ask:
[input] Station id? [SF]
[echo] station=X
BUILD SUCCESSFUL
Total time: 0 seconds
-inputhandler <class> chooses the class that answers the <input> task. The provided PropertyFileInputHandler reads the
answers from a Java properties file, using the prompt text as the key. The file is named by the Java system property
ant.input.properties, not by an Ant property, so it is passed through ANT_OPTS; the same build with -D on the Ant command
line fails (the property exists for Ant, but the handler reads the JVM’s):
$ ant -Dant.input.properties=answers.properties -inputhandler org.apache.tools.ant.input.PropertyFileInputHandler ask
Buildfile: /work/tidepool-model/build.xml
ask:
BUILD FAILED
/work/tidepool-model/build.xml:38: System property ant.input.properties for PropertyFileInputHandler not set
With answers.properties containing the escaped key Station\ id?=BOS:
$ ANT_OPTS="-Dant.input.properties=answers.properties" ant -inputhandler org.apache.tools.ant.input.PropertyFileInputHandler ask
Buildfile: /work/tidepool-model/build.xml
ask:
[echo] station=BOS
BUILD SUCCESSFUL
Total time: 0 seconds
If the key is missing the build fails with Unable to find input for 'Station id?'. The <input> task itself is on
Utility Tasks.
Source: Apache Ant manual: InputHandler
Library directories and -lib
Since Ant 1.6 the jars that Ant itself, its optional tasks and third-party tasks run on come from library directories, not from
the CLASSPATH. Two directories are scanned by default, ANT_HOME/lib and ${user.home}/.ant/lib; the first is shared by every
user of the installation and the second is private to one user, so an administrator can lock the installation down while a
developer still adds, say, the JSch jar for <scp>. More can be added with -lib <path>, a path of jars and directories
(: or ; separated as the platform requires, or the option repeated). The order in which they are searched is:
-
jars from the
-liboptions, in the order given; -
jars from
${user.home}/.ant/lib, unless-nouserlibis set; -
jars from
ANT_HOME/lib.
The CLASSPATH environment variable is converted into one more -lib option, because the launcher starts Ant itself with a
minimal class path. Ant is happy with an empty CLASSPATH; -noclasspath enforces that, and -nouserlib skips the user
directory. The documentation recommends never setting CLASSPATH for Ant: most class path problems reported against Ant (and
many quoting problems) come from it. Typical uses:
ant -lib /home/ant/extras
ant -lib one.jar -lib another.jar
ant -nouserlib -noclasspath # run with exactly the jars in ANT_HOME/lib
A directory that does not exist is ignored without a message, so a typo in -lib surfaces later as an unknown task or missing
class rather than at the option itself:
$ ant -lib /nonexistent -q props
[echo] greeting=built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026 tmpdir=${ant.tmpdir} version=${project.version}
BUILD SUCCESSFUL
Total time: 0 seconds
The proper way for a project to bring its own task jars is to load them from the build file with a <taskdef> and a class
path, or from an antlib (see Antlibs & Namespaces);
-lib is for jars that must be on Ant’s own class loader. Downloading the libraries for the optional tasks is described on
Installation; resolving a project’s own dependencies is the
job of Ivy or the Maven Resolver Ant Tasks (see
Ivy Overview and
Maven Resolver Ant Tasks).
Other options
-
-nice <number>sets the priority of the thread that runs the build, from 1 (lowest) to 10 (highest); 5 is the default. It is accepted and has no visible output, and is mostly useful on a shared build server. -
-autoproxymakes Ant use the operating system’s proxy settings; the-diagnosticsreport shows what the JVM found ("Direct connection" in the run above). Explicit proxy configuration is in the<setproxy>task andANT_OPTS="-Dhttp.proxyHost=<host> -Dhttp.proxyPort=<port>". -
-main <class>replaces Ant’s entry point (org.apache.tools.ant.Main) with a class implementingAntMain. It is how an embedding tool or a wrapper changes startup behaviour. The manual’s example of changing the exit behaviour is to subclassMain, overrideexit(int)and start Ant with-libpointing at the class; this was not run here.
Files read by the wrapper script
On Unix the ant script sources (reads and evaluates) /etc/ant.conf, $HOME/.ant/ant.conf and $HOME/.antrc before it does
anything else; on Windows the batch file runs %HOME%\antrc_pre.bat first and %HOME%\antrc_post.bat last. They are the place
to set variables that only Ant should see, such as JAVA_HOME for a different JDK or ANT_OPTS. The --noconfig script
option suppresses them. A one-line .antrc in a scratch home directory:
$ cat fakehome/.antrc
echo "antrc sourced" >&2; ANT_OPTS="-Dfrom.antrc=yes"
$ HOME=$PWD/fakehome ant -q props
antrc sourced
[echo] greeting=built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026 tmpdir=${ant.tmpdir} version=${project.version}
BUILD SUCCESSFUL
Total time: 0 seconds
$ HOME=$PWD/fakehome ant --noconfig -q props
[echo] greeting=built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026 tmpdir=${ant.tmpdir} version=${project.version}
BUILD SUCCESSFUL
Total time: 0 seconds
A hidden .antrc is a classic reason why the same build behaves differently for two developers; --noconfig and
--execdebug (below) are the way to find out.
Source: Apache Ant manual: Files
Environment variables
The wrapper scripts use these variables when they are set. The installation variables JAVA_HOME and ANT_HOME are described
on Installation; Ant 1.10.x finds ANT_HOME from the script’s
own location, so only JAVA_HOME is normally needed.
| Variable | Purpose |
|---|---|
|
Full path of the Java executable, to use a JVM other than |
|
Arguments for the JVM that runs Ant: heap size ( |
|
Ant command-line arguments added to every invocation: for example a different logger, a listener or |
--execdebug prints the Java command the script is about to run, which shows precisely how the variables were applied:
$ ANT_OPTS="-Dfoo=bar -Xmx64m" ant --execdebug props
arg : props
quoted_arg: "props"
exec "$JAVACMD" -Dfoo=bar -Xmx64m -classpath "$LOCALCLASSPATH" -Dant.home="$ANT_HOME" -Dant.library.dir="$ANT_LIB" org.apache.tools.ant.launch.Launcher -cp "$CLASSPATH" "props"
Buildfile: /work/tidepool-model/build.xml
props:
[echo] greeting=built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026 tmpdir=${ant.tmpdir} version=${project.version}
BUILD SUCCESSFUL
Total time: 0 seconds
ANT_ARGS prepends options to every run, which is a convenient way to set a team-wide default and a surprising one for a
build that behaves differently on a machine that has it set:
$ ANT_ARGS="-q -Dgreeting=fromenv" ant props
[echo] greeting=fromenv tmpdir=${ant.tmpdir} version=${project.version}
BUILD SUCCESSFUL
Total time: 0 seconds
A wrong JAVACMD produces the script’s own message, not an Ant one, and exit code 1:
$ JAVACMD=/nonexistent/java ant props
We cannot run Java, please ensure you have Java installed.
We have tried to execute /nonexistent/java but failed.
If you have installed Java in a unusual place you can set JAVA_HOME
to the directory containing the Java installation.
Java system properties and the temporary directory
Some of Ant’s core classes read Java system properties. They are set with ANT_OPTS (or java -Dname=value when starting Ant by
hand), because they must reach the JVM, not Ant’s own property table. A few of them are listed here; the manual has the full
table.
| Property | Meaning |
|---|---|
|
Default |
|
Default compiler adapter for |
|
Class that invokes targets (default |
|
Read-only: full file name of the build file, and per project, of every imported file. |
|
File read by |
|
Class that parses build files (default |
|
Value used as "now" by |
|
Since Ant 1.10.9: set to |
Properties starting with ant. or org.apache.tools.ant. are reserved: the manual asks build files to avoid inventing names in
those prefixes because future releases may add them.
Temporary directory. Tasks that need temporary files use java.io.tmpdir by default, and tmp directories shared between users
can leak sensitive information or let an attacker inject source files into the build. Since Ant 1.10.8 the Ant property
ant.tmpdir takes precedence over java.io.tmpdir when set, and, unlike the JVM property, can be set from the command line
or from the build file. Since Ant 1.10.9, when ant.tmpdir is not set, Ant creates a build-specific directory under
java.io.tmpdir, accessible only to the current user where the file system allows it. The manual recommends pointing
ant.tmpdir at a directory owned by the user running Ant with 0700 permissions. Tasks that are not shipped with Ant ignore
ant.tmpdir unless they were adapted to the 1.10.8 API.
$ ant -Dant.tmpdir=/tmp/antwork props
Buildfile: /work/tidepool-model/build.xml
props:
[echo] greeting=built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026 tmpdir=/tmp/antwork version=${project.version}
BUILD SUCCESSFUL
Total time: 0 seconds
Running Ant through Java
The scripts are a convenience. Ant can be started from any process with a JVM, which is how an IDE or a build server does it when it does not use the scripts. There are two entry points:
-
org.apache.tools.ant.launch.Launcher(inant-launcher.jar) is what the script runs. It sets up the library directories and so supports-lib; it needs-Dant.home=<installation>so that it can findlib. -
org.apache.tools.ant.Mainis the traditional entry point. It supports no-lib: every jar must be on theCLASSPATH, at a minimumant.jarandant-launcher.jar, an XML parser (the JDK has one) and what the tasks need.
$ java -cp "$ANT_HOME/lib/ant-launcher.jar" -Dant.home="$ANT_HOME" org.apache.tools.ant.launch.Launcher -q props
[echo] greeting=built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026 tmpdir=${ant.tmpdir} version=${project.version}
BUILD SUCCESSFUL
Total time: 0 seconds
$ java -cp "$ANT_HOME/lib/ant.jar:$ANT_HOME/lib/ant-launcher.jar" org.apache.tools.ant.Main -q props
[echo] greeting=built with Ant Apache Ant(TM) version 1.10.18 compiled on September 3 2026 tmpdir=${ant.tmpdir} version=${project.version}
BUILD SUCCESSFUL
Total time: 0 seconds
Handing -lib to Main is rejected, with an explanation of the common cause (a mismatch between the script and Ant itself, for
instance a newer ant script on the PATH with an older ANT_HOME):
$ java -cp "$ANT_HOME/lib/ant.jar:$ANT_HOME/lib/ant-launcher.jar" org.apache.tools.ant.Main -lib x -q props
Ant's Main method is being handed an option -lib that is only for the launcher class.
This can be caused by a version mismatch between the ant script/.bat file and Ant itself.
Starting Ant from Java code, with a Project object and a build listener, is on
Embedding Ant. Calling another build from a build file is
the <ant> and <subant> tasks, on
Multi-File Builds: import, include & subant.
Exit codes
The start-up scripts return the exit code of the Java process: 0 for a successful build and a non-zero value, in practice 1,
for a failed one. That covers every case shown above: a failed task (ant broken), an unknown target, a missing build file,
-k with a failure, an unusable JAVACMD, and a logging exception as in the -listener mistake. A CI job needs nothing more
than that status: the failure of the job follows the failure of the command. To change the exit behaviour, the manual suggests
subclassing org.apache.tools.ant.Main, overriding exit(int) (for example to not exit the JVM when Ant is run inside another
program) and starting Ant with -lib pointing at that class (not run here). The <fail> task has a status attribute for a build that
wants a specific exit code.
Source: Apache Ant manual: return code
Practical recipes
-
A quiet, scriptable build:
ant -S -noinput target. -
A diagnosable build:
ant -v -logfile build.log target, keeping the log as a CI artifact. -
A reproducible command line for a release:
ant -propertyfile release.properties -Dant.tmpdir=build/tmp dist. -
Starting from a sub-project:
ant -find build.xml jar. -
Find which build file or option set is in play:
ant -v,ant --execdebug, and a look atANT_ARGS,ANT_OPTSand the.antrcfiles.
The same ideas under Maven and Gradle are on Running Maven (CLI) and Command-Line Interface; the tool-independent view is on Build Automation Fundamentals. The properties that a build reads are the subject of Properties.