Ant Deprecations & Migration
|
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, released on 6 September 2026, and was checked on 2026-10-16 on JDK 26
(and, where it says so, on JDK 17) on macOS. It is the upgrade guide of the Ant section: what an old build file
needs when it is moved from Ant 1.9 to 1.10, which tasks are deprecated, which have stopped working because the JDK removed what
they wrapped, what has no maintained replacement, and what to do when the better answer is to leave Ant. Every example
was run in a scratch directory with the Ant 1.10.18 distribution; the output is shown as Ant printed it, with the scratch
directory shortened to .. Where something could not be run (a task that needs a third-party library or an old server),
the text says "not run here".
Ant’s own policy explains the shape of this page. The project’s task design guidelines open with "Don’t break existing
builds": a change that breaks a build file in the wild is a bug, so tasks are not deleted because they are old. A task
disappears only when the thing it wraps has disappeared from the JDK or from the world, and an old task that still works
prints a DEPRECATED warning for years instead. That is why most of the list below is a list of warnings, and why the short
list of real removals follows the JDK, not Ant. The release-by-release history, with dates, is on
Versions & Release History; this page
turns it into actions. The running scenario is the tidepool toolkit described on the
section landing page.
Upgrading from Ant 1.9 to 1.10
Ant 1.10.0 was branched from 1.9.7 and has one rule that overrides all others: it needs Java 8 or later to run. The 1.9 line stayed on Java 5 to the end and reached end of life on 19 June 2024, so a build that still runs on 1.9 is on an unmaintained Ant. For the other lines the Ant FAQ and installation manual give the same table, kept here in short form:
| Ant line | Java needed to run it | Notes |
|---|---|---|
1.10.x |
8 or later |
Current. The more recent the JDK, the more tasks work, but each JDK removes something (below). |
1.9.x |
5 or later |
End of life since 19 June 2024; last release 1.9.16. |
1.8.x, 1.7.x, 1.6.x |
1.4, 1.3, 1.2 |
Historical. |
The Java version needed to run Ant is not the Java version a build targets: javac can compile for an older release
with release, as shown on Compiling Java. A project
that runs Ant 1.10.18 on JDK 26 and compiles for Java 17 is a normal setup, and it is the one this page used.
The list below holds what the Ant WHATSNEW file calls "changes that could break older environments", and the other
entries that a 1.9 build is likely to hit. The release column says when the change arrived; for the dates see the versions
page.
| Release | Change | What to do |
|---|---|---|
1.10.0 |
Java 8 minimum. The |
Drop |
1.10.2 |
|
Use a |
1.10.3 |
|
Nothing to change; see the testing page. |
1.10.4 |
|
Set |
1.10.6 |
|
Use |
1.10.13 |
|
Set it to |
1.10.14 |
On Java 18 and later Ant no longer uses a |
Fork ( |
1.10.16 |
|
|
1.10.18 |
The |
Set the attribute explicitly if a download really must write outside its target; expect |
The ftp and scp items for 1.10.18 are in the WHATSNEW file in the Apache GitHub repository, under "Changes that could
break older environments". The WHATSNEW inside the 1.10.18 binary archive that was downloaded for this page
does not have that block (its 1.10.18 section lists only the tstamp, propertyfile, record and jakarta.mail items),
so the archive’s copy is not enough on its own. Read the GitHub copy and the security page when upgrading to 1.10.18. The
ant.apache.org/WHATSNEW address itself is a 404 at the time of writing. The GitHub copy also holds a section for a
1.10.19 that is not released yet (a BCEL update); when it ships, this list will need a line.
Source: Apache Ant WHATSNEW (GitHub); Ant manual: system requirements; Ant FAQ: which Java version is required; Apache Ant security reports
Two of these can be seen directly. ant.java.version is the plain feature number (26, not 1.26); comparing it as a
number is easier than parsing it, and the javaversion condition (see
Conditions & Control Flow) does the
comparison for you:
$ ant -q -f script.xml props
[echo] ant.version=Apache Ant(TM) version 1.10.18 compiled on September 3 2026 ant.java.version=26 java.version=26
BUILD SUCCESSFUL
Total time: 0 seconds
(The same build file printed ant.java.version=17 and java.version=17.0.14 on JDK 17.) And the wildcard in delete
is now an inert literal name: with a.bak and b.bak in stage, <delete file="stage/*.bak"/> succeeded and deleted
nothing, whereas the fileset form removes them:
<target name="wildcard-delete">
<delete file="stage/*.bak"/>
</target>
<target name="fileset-delete">
<delete verbose="true">
<fileset dir="stage" includes="*.bak"/>
</delete>
</target>
$ ls stage
a.bak b.bak data stations.csv
$ ant -f removed.xml wildcard-delete
Buildfile: ./removed.xml
wildcard-delete:
BUILD SUCCESSFUL
Total time: 0 seconds
$ ls stage
a.bak b.bak data stations.csv
$ ant -f removed.xml fileset-delete
Buildfile: ./removed.xml
fileset-delete:
[delete] Deleting ./stage/a.bak
[delete] Deleting ./stage/b.bak
BUILD SUCCESSFUL
Total time: 0 seconds
$ ls stage
data stations.csv
A silent no-op is the dangerous kind of change. Build files that relied on the wildcard and are moved to 1.10 do not fail;
they stop cleaning. Search old build files for file=" with an asterisk after the upgrade.
Deprecated tasks and what replaces them
The Ant manual marks these tasks "deprecated". They still run; copydir, copyfile, deltree, rename and renameext also print a
warning in every run, as the log below shows.
| Task | Replacement | Notes |
|---|---|---|
|
|
Deprecated since Ant 1.2. |
|
|
Deprecated since Ant 1.2. |
|
|
Deprecated since Ant 1.2. |
|
|
The warning prints the replacement. |
|
|
|
|
|
Not the JDK’s |
|
|
Deprecated in 1.10.2 and broken on Java 9 and later. |
|
The JSP compiler of the servlet container |
The manual says the task was only tested with Tomcat 4.x and recommends compiling with the container’s own task, or deploying the JSPs and testing them; see Running Programs for the Ant |
|
|
The task is the same; the manual says |
|
Another listener |
Deprecated in 1.10.2 because log4j 1.x is unmaintained. |
The first group is the one most old build files contain. This build uses all five on the tidepool data directory:
<?xml version="1.0" encoding="UTF-8"?>
<project name="tidepool-old" default="stage" basedir=".">
<target name="clean">
<deltree dir="stage"/>
</target>
<target name="stage" depends="clean">
<mkdir dir="stage/data"/>
<copydir src="data" dest="stage/data"/>
<copyfile src="data/stations.csv" dest="stage/stations-copy.csv"/>
<rename src="stage/stations-copy.csv" dest="stage/stations.csv"/>
<touch file="stage/a.tmp"/>
<touch file="stage/b.tmp"/>
<renameext srcDir="stage" fromExtension=".tmp" toExtension=".bak"/>
</target>
</project>
ant -f old.xml
Buildfile: ./old.xml
clean:
[deltree] DEPRECATED - The deltree task is deprecated. Use delete instead.
stage:
[mkdir] Created dir: ./stage/data
[copydir] DEPRECATED - The copydir task is deprecated. Use copy instead.
[copydir] Copying 1 file to ./stage/data
[copyfile] DEPRECATED - The copyfile task is deprecated. Use copy instead.
[rename] DEPRECATED - The rename task is deprecated. Use move instead.
[touch] Creating ./stage/a.tmp
[touch] Creating ./stage/b.tmp
[renameext] DEPRECATED - The renameext task is deprecated. Use move instead.
[renameext] Replace this with:
[renameext] <move todir="./stage" overwrite="false">
[renameext] <fileset dir="./stage" />
[renameext] <mapper type="glob"
[renameext] from="*.tmp"
[renameext] to="*.bak" />
[renameext] </move>
[renameext] using the same patterns on <fileset> as you've used here
[renameext] Moving 2 files to ./stage
BUILD SUCCESSFUL
Total time: 0 seconds
Two details. The task name in the build file is renameext, while the manual page is called renameextensions; the build
file with the long name would fail with an undefined-task error. And renameext prints a ready-to-paste replacement, which
the others do not. The migrated version is shorter and has no warnings:
<?xml version="1.0" encoding="UTF-8"?>
<project name="tidepool-new" default="stage" basedir=".">
<target name="clean">
<delete dir="stage"/>
</target>
<target name="stage" depends="clean">
<mkdir dir="stage/data"/>
<copy todir="stage/data">
<fileset dir="data"/>
</copy>
<copy file="data/stations.csv" tofile="stage/stations.csv"/>
<touch file="stage/a.tmp"/>
<touch file="stage/b.tmp"/>
<move todir="stage">
<fileset dir="stage" includes="*.tmp"/>
<mapper type="glob" from="*.tmp" to="*.bak"/>
</move>
</target>
</project>
Buildfile: ./new.xml
clean:
[delete] Deleting directory ./stage
stage:
[mkdir] Created dir: ./stage/data
[copy] Copying 1 file to ./stage/data
[copy] Copying 1 file to ./stage
[touch] Creating ./stage/a.tmp
[touch] Creating ./stage/b.tmp
[move] Moving 2 files to ./stage
BUILD SUCCESSFUL
Total time: 0 seconds
Both builds left a.bak, b.bak, data and stations.csv in stage. (The copy task also replaced the two-step
copyfile plus rename, because tofile names the target directly.) The Ant distribution ships etc/ stylesheets for
checking and rewriting build files, as the installation manual says, but the list in 1.10.18 contains only the reporting
stylesheets (junit-frames.xsl, log.xsl and similar); there is no deprecation migrator among them, so the table above is
the checklist. All of these tasks are described on
File Operations.
Tasks that no longer work
A task can stop working without Ant changing, because the JDK removed what it wrapped. Each failure below was produced on JDK 26; the ones marked also ran on JDK 17.
| Task | Breaks on | Use instead |
|---|---|---|
|
Java 10 (removed from the JDK; deprecated in 9). Also JDK 17. |
|
|
Java 15 (removed; deprecated in 13). Also JDK 17. |
Dynamic proxies; or set the |
|
Removed from Ant in 1.10.0 (the tool left Java 8). |
Annotation processing in |
|
Java 9 (Java Advanced Imaging internals). |
|
|
Java 15 (the Nashorn engine was removed). |
Add a JSR 223 engine, such as GraalVM JavaScript, to Ant’s classpath; or use another language. |
|
Java 18 (the SecurityManager is disallowed by default). |
Fork the |
|
Ant 1.10.2 (see above). |
A |
javah and rmic
<target name="javah" depends="compile">
<javah class="io.tidepool.Native" destdir="build/headers" classpath="build/classes"/>
</target>
<target name="javac-native-headers">
<delete dir="build/classes"/>
<delete dir="build/headers"/>
<mkdir dir="build/classes"/>
<mkdir dir="build/headers"/>
<javac srcdir="src" destdir="build/classes" nativeheaderdir="build/headers"
release="17" includeantruntime="false"/>
</target>
<target name="rmic" depends="compile">
<rmic base="build/classes" includes="io/tidepool/Native.class"/>
</target>
(The class Native declares one native method, ticks().)
$ ant -f removed.xml javah
Buildfile: ./removed.xml
compile:
javah:
BUILD FAILED
./removed.xml:9: javah does not exist under Java 10 and higher, use the javac task with nativeHeaderDir instead
$ ant -f removed.xml javac-native-headers
…
[javac] Compiling 2 source files to ./build/classes
BUILD SUCCESSFUL
$ ls build/headers
io_tidepool_Native.h
$ ant -f removed.xml rmic
…
BUILD FAILED
./removed.xml:22: rmic does not exist under Java 15 and higher, use rmic of an older JDK and explicitly set the executable attribute
The replacement for javah is a single attribute on a task the build already has, and the generated header contains the JNI
declaration for ticks. For rmic there is no JDK replacement: Java RMI has not needed generated stubs since Java 5, so
the usual migration is to delete the task. On JDK 17 the rmic build printed RMI Compiling 1 class to … and then the
same failure message. Both messages are Ant’s own, not the JDK’s, and name the fix.
script and JavaScript
script with language="javascript" was a standard way to write a bit of logic in a build file when Java shipped Nashorn.
Java 15 removed it (JEP 372), and Ant says so in its error:
<target name="js">
<script language="javascript"><![CDATA[
project.setProperty("greeting", "hello from javascript");
]]></script>
<echo>${greeting}</echo>
</target>
$ ant -f script.xml js
Buildfile: ./script.xml
js:
Java 15 has removed Nashorn, you must provide an engine for running JavaScript yourself. GraalVM JavaScript currently is the preferred option.
BUILD FAILED
./script.xml:4: Unable to create javax script engine for javascript
Ant 1.10.9 added support for GraalVM JavaScript; the engine and its dependencies have to be put on Ant’s classpath (with
-lib or in ANT_HOME/lib), because Ant does not ship them. Putting one on the classpath was not done here. See
Scripting for the engines and the alternatives (a
macrodef, a custom task), which are usually a better answer than an extra runtime.
permissions and System.exit()
The permissions type used a Java SecurityManager to sandbox an in-process java task. Java 17 deprecated the
SecurityManager for removal (JEP 411) and Java 18 disallows it by default, so from Ant 1.10.14 the type does nothing on those
JDKs. The first run below tries it; the second is the other consequence, a task that calls System.exit(3) in Ant’s own
JVM:
<target name="perm" depends="compile">
<java classname="io.tidepool.Exiter" classpath="build/classes" fork="false">
<permissions>
<grant class="java.lang.RuntimePermission" name="exitVM"/>
</permissions>
</java>
<echo>after</echo>
</target>
<target name="exit-unforked" depends="compile">
<java classname="io.tidepool.Exiter" classpath="build/classes" fork="false"/>
<echo>still alive after System.exit</echo>
</target>
<target name="exit-forked" depends="compile">
<java classname="io.tidepool.Exiter" classpath="build/classes" fork="true"
resultproperty="rc" failonerror="false"/>
<echo>still alive, exit code ${rc}</echo>
</target>
(Exiter.main prints about to call System.exit(3) and calls it.)
$ ant -f script.xml perm
…
perm:
[java] Use of <permissions> or org.apache.tools.ant.types.Permissions is disallowed in current Java runtime version
[java] at org.apache.tools.ant.types.Permissions.setSecurityManager(Permissions.java:122)
[java] at org.apache.tools.ant.taskdefs.ExecuteJava.run(ExecuteJava.java:217)
…
[java] Java Result: -1
[echo] after
BUILD SUCCESSFUL
$ ant -f removed.xml exit-unforked
Buildfile: ./removed.xml
compile:
exit-unforked:
[java] about to call System.exit(3)
$ echo $?
3
$ ant -f removed.xml exit-forked
…
[java] Java Result: 3
[echo] still alive, exit code 3
BUILD SUCCESSFUL
The in-process exit killed Ant: no BUILD SUCCESSFUL or BUILD FAILED line, no still alive message, and Ant’s own
exit code was the program’s. The permissions run is worse in a quieter way: the program was not run and the build still
reported success (the stack trace is printed, Java Result: -1 is logged, and failonerror was not set). Both are fixed
the same way: fork="true", which gives the program its own JVM and lets Ant read the exit code. The task is described on
Running Programs.
New JDKs, old compiler flags
Not an Ant change, but the first thing a JDK upgrade shows in an Ant log. The source and target attributes of javac
become obsolete as the JDK moves on, and the release attribute is the supported replacement. These three targets compile
the same sources on JDK 26:
<javac srcdir="src" destdir="build/c1" source="8" target="8" includeantruntime="false"/>
<javac srcdir="src" destdir="build/c2" release="8" includeantruntime="false"/>
<javac srcdir="src" destdir="build/c3" release="17" includeantruntime="false"/>
### source="8" target="8"
[javac] Compiling 2 source files to ./build/c1
[javac] warning: [options] bootstrap class path is not set in conjunction with -source 8
[javac] not setting the bootstrap class path may lead to class files that cannot run on JDK 8
[javac] --release 8 is recommended instead of -source 8 -target 8 because it sets the bootstrap class path automatically
[javac] warning: [options] source value 8 is obsolete and will be removed in a future release
[javac] warning: [options] target value 8 is obsolete and will be removed in a future release
[javac] warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
[javac] 4 warnings
### release="8"
[javac] Compiling 2 source files to ./build/c2
[javac] warning: [options] source value 8 is obsolete and will be removed in a future release
[javac] warning: [options] target value 8 is obsolete and will be removed in a future release
[javac] warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
[javac] 3 warnings
### release="17"
[javac] Compiling 2 source files to ./build/c3
Three lessons. source/target also leave the bootstrap class path alone, so the code may use JDK 26 methods that do not
exist on Java 8 and still compile (the release form prevents that). The warnings are JDK warnings; they do not change the
exit code. And the cure for the noise is to raise the target to a supported release, not to silence the lint. The javac
task is the subject of Compiling Java.
Tasks that survive but are legacy
These tasks are in the 1.10.18 manual, work as far as their external tool does, and are not deprecated. Most of them wrap products that few teams still run, so the practical question is not "what replaces the task?" but "should this build still talk to that product?". None was run here: they need the external tool or server.
| Tasks | Status |
|---|---|
|
CVS client tasks. They need the |
|
Microsoft Visual SourceSafe, SourceOffSite and ClearCase. Each needs the vendor’s command-line client. Treat as end-of-life products. |
|
The EJB tasks. The manual says development of these tasks is effectively frozen and that EJB 3.0 made the whole process obsolete. The application servers they list are from the early 2000s. |
|
Compiler-generator tasks that need their libraries. |
.NET tasks ( |
Already gone: the .NET tasks were deprecated in Ant 1.7.0 and removed in 1.8.0 (the stand-alone .NET Antlib took over), the Perforce tasks were removed in 1.9.0 (replaced by the vendor’s own), and the others in 1.7.0 because their libraries no longer exist. Old build files that name them fail with "task undefined". |
The EJB manual page, the cvs page and the vss page are the pages to cite when deciding. For a build that must keep
talking to such a system, the way to keep the tasks is to leave the library and the vendor’s client where they are; for one
that does not, deleting the target is the migration.
Source: Apache Ant manual: EJB tasks; Apache Ant manual: Cvs; Apache Ant manual: Microsoft Visual SourceSafe tasks; Apache Ant WHATSNEW: 1.7.0, 1.8.0, 1.9.0
junit: not deprecated, but not for JUnit 5
The junit task is not deprecated in 1.10.18. Its manual page says it was tested with JUnit 3.0 to 3.8.2 and also works with
JUnit 4.x, and it needs junit.jar and ant-junit.jar on Ant’s classpath. For JUnit 5 and later, the junitlauncher task
(added in 1.10.3) runs tests through the JUnit Platform, including JUnit 4 tests through the Vintage engine. A build that
adopts JUnit 5 therefore replaces junit with junitlauncher; one that stays on JUnit 4 can keep junit. Both are covered
with runnable examples on
Testing with JUnit & junitlauncher.
Replacing Ant-Contrib
Old build files often declare the Ant-Contrib task library for <if>, <foreach>, <for> and a few property tasks. The
Ant site lists Ant-Contrib on its projects page, but it is dormant and not hosted by Apache, and a new build should not add
it. Most of what it provided exists in Ant itself, some of it since Ant 1.9.1 or earlier. The loops are explained, with
runnable examples, on
Conditions & Control Flow; this build
shows the two commonest replacements side by side with the Ant-Contrib line they replace (the Ant-Contrib lines are in
comments; the library was not downloaded):
<?xml version="1.0" encoding="UTF-8"?>
<project name="contrib-replacements" default="all" basedir="."
xmlns:if="ant:if" xmlns:unless="ant:unless">
<!-- Ant-Contrib: <if><equals arg1="${env}" arg2="prod"/><then>...</then><else>...</else></if> -->
<target name="conditional">
<condition property="is.prod">
<equals arg1="${env}" arg2="prod"/>
</condition>
<echo if:set="is.prod">production settings</echo>
<echo unless:set="is.prod">development settings</echo>
</target>
<!-- Ant-Contrib: <foreach list="SF,BOS,HNL" param="id" target="report"/> -->
<macrodef name="report-station">
<attribute name="id"/>
<sequential>
<echo>station @{id}</echo>
</sequential>
</macrodef>
<target name="loop">
<report-station id="SF"/>
<report-station id="BOS"/>
<report-station id="HNL"/>
</target>
<target name="all" depends="conditional,loop"/>
</project>
$ ant -q -f contrib.xml conditional
[echo] development settings
BUILD SUCCESSFUL
Total time: 0 seconds
$ ant -q -Denv=prod -f contrib.xml conditional
[echo] production settings
BUILD SUCCESSFUL
Total time: 0 seconds
$ ant -q -f contrib.xml loop
[echo] station SF
[echo] station BOS
[echo] station HNL
BUILD SUCCESSFUL
Total time: 0 seconds
| Ant-Contrib | Closest core Ant |
|---|---|
|
|
|
|
|
No direct equivalent: Ant properties are immutable by design. |
|
No direct equivalent. |
|
|
Build-file style that ages well
Ant has no build-file checker beyond its own parser, so the checklist is what the project’s own documents teach. Two of them are old and still worth reading, with a caveat about their age: Ant in Anger was last updated on 16 March 2005, and its advice (define standard targets, keep a clean directory layout, do not make the build a scripting language) is sound, but its examples predate the packaging, dependency and Java changes above. The task design guidelines are current and say what the project promises about compatibility. For a 1.10.18 build file the practical rules are:
-
Use
release, notsourceandtarget, injavac, and setincludeantruntime="false". -
Replace deprecated task names (above) and wildcard
deletecalls. -
Fork anything that may call
System.exit(); do not usepermissions. -
Put third-party task libraries behind
taskdefwith an explicit classpath, or in-lib, not inANT_HOME/lib(see Installation). -
Keep dependencies out of the repository with Ivy (Ivy Overview) or the Maven Resolver Ant Tasks.
-
Prefer
importandmacrodefto copy-pasted targets (Multi-File Builds and Macros & Presets). -
After every JDK or Ant upgrade, run the build once and read every
DEPRECATEDandwarning:line; they are the changes above arriving one at a time.
Moving to Maven or Gradle
Sometimes the right answer to a pile of deprecations is another tool. The question of whether to move is on
Comparing Ant, Maven & Gradle; the how,
with a complete tidepool migration in each direction and checks that the results match, is on
Migrating Between Tools (Ant to Maven, Ant to
Gradle, and Ivy to the Resolver Ant Tasks). This section adds the part that belongs to Ant: both tools can run an existing
Ant build as it is, so the migration can start before the first target is rewritten. The two examples use the legacy
old.xml above (renamed build.xml) and its deprecated tasks.
Gradle: ant.importBuild
Gradle embeds Ant. ant.importBuild turns every target of a build file into a Gradle task, and the optional closure renames
them. The Gradle manual describes this under "Ant integration" and in its Ant migration guide.
// Every Ant target of build.xml becomes a Gradle task, renamed with an "ant-" prefix.
ant.importBuild("build.xml") { antTargetName ->
"ant-$antTargetName"
}
tasks.register("stageData") {
group = "tidepool"
description = "Stages the data files through the imported Ant build"
dependsOn("ant-stage")
}
// Every Ant target of build.xml becomes a Gradle task, renamed with an "ant-" prefix.
ant.importBuild('build.xml') { antTargetName ->
"ant-${antTargetName}".toString()
}
tasks.register('stageData') {
group = 'tidepool'
description = 'Stages the data files through the imported Ant build'
dependsOn 'ant-stage'
}
Both versions were run with the Gradle 9.8.1 distribution (gradle; with a wrapper the command is ./gradlew), with
settings.gradle.kts or settings.gradle holding only rootProject.name.
gradle --console=plain stageData
> Task :ant-clean
> Task :ant-stage
[ant:renameext] DEPRECATED - The renameext task is deprecated. Use move instead.
> Task :stageData
BUILD SUCCESSFUL in 259ms
2 actionable tasks: 2 executed
Gradle shows Ant’s output at its own log levels, so at the default level only the warning-level line is shown (Gradle’s
ant-clean task printed nothing, although deltree also warned). With --info all the messages of the original run
appear, with the prefix [ant:<task>]:
> Task :ant-clean
[ant:deltree] DEPRECATED - The deltree task is deprecated. Use delete instead.
[ant:deltree] Deleting: ./stage
> Task :ant-stage
[ant:mkdir] Created dir: ./stage/data
[ant:copydir] DEPRECATED - The copydir task is deprecated. Use copy instead.
[ant:copydir] Copying 1 file to ./stage/data
…
[ant:renameext] Moving 2 files to ./stage
The task list also shows the imported targets under "Other tasks" (ant-clean, ant-stage). The Groovy build produced the
same output. Gradle bundles its own Ant: gradle --version on 9.8.1 reports Ant 1.10.17, which is not the Ant installed
on the machine (1.10.18), so Ant features newer than the bundled one are unavailable, and extra Ant task libraries have to be
added to Gradle’s ant classpath. The step-by-step version of this migration, replacing one imported target at a time and
moving the Ivy dependencies, is on
Migrating Between Tools; the Gradle side is
described on Gradle: Ant Integration.
Maven: maven-antrun-plugin
Maven has no importBuild, but maven-antrun-plugin runs Ant tasks, including the ant task that calls a target of an
existing build file, from a phase of the lifecycle. The pom below (a pom-packaging project, since there is nothing to
compile) calls the stage target of the legacy build during process-resources:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.tidepool</groupId>
<artifactId>tidepool-ant-bridge</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>stage-data</id>
<phase>process-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<echo>Running inside Ant ${ant.version}</echo>
<ant antfile="${project.basedir}/build.xml" dir="${project.basedir}" target="stage"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
mvn -B -ntp process-resources
[INFO] --- antrun:3.2.0:run (stage-data) @ tidepool-ant-bridge ---
[INFO] Executing tasks
[WARNING] [echo] Running inside Ant Apache Ant(TM) version 1.10.15 compiled on August 25 2024
[INFO] [deltree] DEPRECATED - The deltree task is deprecated. Use delete instead.
[INFO] [mkdir] Created dir: ./stage/data
[INFO] [copydir] DEPRECATED - The copydir task is deprecated. Use copy instead.
[INFO] [copydir] Copying 1 file to ./stage/data
[INFO] [copyfile] DEPRECATED - The copyfile task is deprecated. Use copy instead.
[INFO] [rename] DEPRECATED - The rename task is deprecated. Use move instead.
[INFO] [touch] Creating ./stage/a.tmp
[INFO] [touch] Creating ./stage/b.tmp
[WARNING] [renameext] DEPRECATED - The renameext task is deprecated. Use move instead.
[INFO] [renameext] Replace this with:
…
[INFO] [renameext] Moving 2 files to ./stage
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
(Run with Maven 3.10.0 on JDK 26.) The same files ended up in stage. Notice the line Running inside Ant …: the plugin
ran Ant 1.10.15, the version the plugin depends on, so across the three runs of this page three different Ants executed the
same build file, 1.10.18 (standalone), 1.10.17 (Gradle 9.8.1) and 1.10.15 (maven-antrun-plugin 3.2.0). That is fine for
core tasks, and a surprise for anything newer. Extra Ant libraries (JSch, the JUnit launcher) have to be added as
dependencies of the plugin. Maven’s side of the bridge, including this plugin’s configuration, is on
Plugins & Their Configuration.
Source: Maven AntRun Plugin: usage
Which way
-
Move the dependencies first if the pain is the
lib/directory: Ivy or the Maven Resolver Ant Tasks change nothing else. -
Go to Maven when the project is a library or an application that fits the standard layout and lifecycle, and the team wants conventions and a plugin ecosystem;
maven-antrun-plugincarries what has not yet been rewritten. -
Go to Gradle when the build has many custom steps, several modules or a need for incremental builds and caching; the
importBuildpath lets the Ant targets be replaced one by one. -
Stay on Ant when the build is small, stable and understood. Ant 1.10.18 is maintained, runs on Java 8 and later, and a few warnings in the log are not a reason to rewrite.
Where the books are outdated
The Ant books on the reading list were written for Ant 1.6 to 1.8, so their advice needs these corrections for 1.10.18. Specific book pages are not quoted here:
-
They use
copydir,copyfile,deltreeandrenameandjavacwithsourceandtargetwhere the manual now recommendscopy,delete,moveandrelease. -
They use
javah,rmic,aptand theimagetask as live examples; none works on a current JDK. -
They embed JavaScript in
scripton the assumption that the JDK has an engine; that ended with Java 15. -
They teach the
junittask as the way to test; for JUnit 5 it isjunitlauncher. -
They use Ant-Contrib for control flow; core Ant has the replacements above.
-
Their dependency chapters stop at a
lib/directory or Ivy; the Maven Resolver Ant Tasks postdate them. -
Their advice on build-file style (the appendix on style, the task guidelines, "Ant in Anger") is mostly still right, and its Java and tooling assumptions are not.
References
-
Apache Ant: Overview of Ant tasks
-
Apache Ant: WHATSNEW (GitHub)
-
Apache Ant: Installing Ant, system requirements
-
Apache Ant: News and release dates
-
Apache Ant: Security reports
-
Apache Ant: Task design guidelines
-
Apache Ant: Ant in Anger
-
Apache Ant: FAQ
-
Apache Ant: Projects, including Ant-Contrib
-
Apache Ant manual: If and Unless on all tasks
-
Gradle User Manual: Using Ant from Gradle
-
Gradle User Manual: Migrating builds from Apache Ant
-
Apache Maven: AntRun Plugin