Running Maven (CLI)
|
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 Maven 3.10.0. Every example was run on JDK 26 on 2026-10-16 on macOS, in a scratch copy of the
tidepool project (described below), with Maven 3.10.0 unless the text names another version. Where behaviour differs, the same
command was also run on Maven 3.9.16 and on Maven 4.0.0-rc-7 (a release candidate, not a final release) and the difference is stated.
Console output is shown as printed, except that the scratch directory was shortened to <tidepool> and that long output was cut
with grep or head or with an explicit ellipsis line, each time with a remark. The auto-discovered-prefixes INFO lines that
Maven 3.10.0 prints at the start of a module build, and blank INFO lines, were also removed from most listings.
The mvn command is small: a list of options followed by the things to run. Almost everything a developer types is a phase
(mvn verify) or a goal (mvn dependency:tree), and most of the rest is one of a couple of dozen options. This page covers what the
arguments mean and then every option, grouped by what it is for. What a lifecycle is (phases, bindings, execution ids) is on
Build Lifecycle; where the defaults for options come from
(MAVEN_OPTS, MAVEN_ARGS, .mvn/maven.config) is on
Configuring Maven; the effect of -pl and -T on a larger
project is on Multi-Module Builds & the Reactor.
Ant’s and Gradle’s equivalents are at the end.
The synopsis
The official page gives the syntax as follows:
mvn [options] [<goal(s)>] [<phase(s)>]
Source: Maven: Running Apache Maven
The built-in help prints the same line and the option list (the 3.10.0 list is reproduced, with notes, in the option reference below):
mvn -h | head -2
usage: mvn [options] [<goal(s)>] [<phase(s)>]
(The first line of the output is empty.)
Three facts about that line drive everything else:
-
Options take effect for the whole run. They are not per-goal. Properties given with
-Dare visible to every plugin in the build. They are conventionally written first, but Maven also accepted them after the goals in the runs below (mvn test -Dtest=HeightTest). -
You may name several things, and they run left to right, in one Maven invocation and one reactor.
mvn clean packageis thecleanphase of the clean lifecycle followed by thepackagephase of the default lifecycle;mvn clean install siteadds a third lifecycle. The JVM starts once, the POMs are read once, and the plugins are loaded once, which is why this is much faster than three separatemvncommands. -
Whether an argument is a phase or a goal is decided by the argument’s shape, not by a flag. The next section explains the rule.
The process exit code is 0 when the build succeeded and 1 when it failed; the -fn option (below) is the only way to get 0 out of
a failed build. CI servers and shell scripts rely on this.
The scratch project
The examples use a copy of the running tidepool project with five projects: the parent tidepool-parent (packaging pom) and the
modules tidepool-model, tidepool-engine, tidepool-cli and tidepool-data. The reactor order is the order of the dependencies
(engine needs model, cli needs engine, data needs nothing); the parent declares every plugin version in pluginManagement.
Three things were added to the parent POM for this page, so that there is something for the options to act on (they, and the test
class below, are this page’s own lab setup, not examples from the Maven documentation):
<properties>
...
<greeting>from-the-pom</greeting>
</properties>
...
<profiles>
<profile>
<id>fast</id>
<properties>
<skipTests>true</skipTests>
</properties>
</profile>
</profiles>
(The ellipses stand for the other properties and the dependency and plugin management, which do not matter here.) And
tidepool-engine has one extra test that fails only when asked to, so that the failure options have something to fail on:
class FailSwitchTest {
@Test
void failsWhenAskedTo() {
assertFalse(Boolean.getBoolean("failEngine"), "failEngine was set");
}
}
Running mvn -B -ntp clean package on the whole project, as a baseline, ends with:
[INFO] Reactor Summary for tidepool-parent 1.0.0-SNAPSHOT:
[INFO]
[INFO] tidepool-parent .................................... SUCCESS [ 0.095 s]
[INFO] tidepool-model ..................................... SUCCESS [ 1.101 s]
[INFO] tidepool-engine .................................... SUCCESS [ 0.682 s]
[INFO] tidepool-cli ....................................... SUCCESS [ 0.332 s]
[INFO] tidepool-data ...................................... SUCCESS [ 0.255 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
(Only the end of the output is shown. The -B and -ntp options are explained in Controlling the output.)
Phases, goals and fully qualified goals
Each argument that is not an option is one of four things.
| Shape | What it is | Example |
|---|---|---|
a bare word |
A lifecycle phase. Maven runs every earlier phase of that lifecycle, then the phase itself. |
|
|
A plugin goal, found through the plugin’s short prefix. Only that goal runs, nothing before it. |
|
|
The same, with the plugin version chosen on the command line. Supported since Maven 3.9.0. |
|
|
A goal of a plugin named by full coordinates, which needs no prefix lookup. |
|
The difference between the first row and the others is the one most worth understanding. A phase is a request for an outcome
("have the tests run"); a goal is a request for one action. In tidepool-model, on a clean checkout:
cd tidepool-model
mvn -B -ntp clean
[INFO] Scanning for projects...
[INFO] ---------------------< io.tidepool:tidepool-model >---------------------
[INFO] Building tidepool-model 1.0.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] --- clean:3.5.0:clean (default-clean) @ tidepool-model ---
[INFO] Deleting <tidepool>/tidepool-model/target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
(The last three lines of the build footer were cut.) The phase clean is bound to the goal clean:clean, so that goal ran, and its
execution id is default-clean. Now ask for goals instead:
mvn -B -ntp resources:resources compiler:compile
[INFO] --- resources:3.5.0:resources (default-cli) @ tidepool-model ---
[INFO] skip non existing resourceDirectory <tidepool>/tidepool-model/src/main/resources
[INFO] --- compiler:3.16.0:compile (default-cli) @ tidepool-model ---
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 4 source files with javac [debug release 21] to target/classes
[INFO] BUILD SUCCESS
(Only the lines that show the plugin executions and the result were kept.) Two goals ran, in the order given, and nothing else: no
validate, no process-resources phase, no tests. The execution id is now default-cli, which is the id Maven gives to a goal
invoked from the command line. It matters when a POM configures an execution with that id, and it is the reason a <configuration>
placed inside an <execution> with a different id does not apply to a goal typed on the command line (see
Plugins & Their Configuration).
The version in the output, 3.16.0, was not typed: the parent’s pluginManagement supplied it. Without that, Maven would pick the
plugin version itself, from the plugin’s metadata, which is why a repeatable build pins every plugin. The other two shapes pin it
explicitly, and both gave the same execution:
mvn -B -ntp compiler:3.16.0:compile
mvn -B -ntp org.apache.maven.plugins:maven-compiler-plugin:3.16.0:compile
[INFO] --- compiler:3.16.0:compile (default-cli) @ tidepool-model ---
[INFO] Nothing to compile - all classes are up to date.
[INFO] BUILD SUCCESS
(The output of the two commands was identical in these lines and is shown once.) The prefix:version:goal form is a Maven 3.9.0
feature. Maven 3.8 and older do not know it; the full coordinates form works everywhere. Phases and goals can be mixed in one
command, with the goals running in sequence at the position where they are typed:
mvn -B -ntp clean compiler:compile jar:jar
[INFO] --- clean:3.5.0:clean (default-clean) @ tidepool-model ---
[INFO] --- compiler:3.16.0:compile (default-cli) @ tidepool-model ---
[INFO] --- jar:3.5.1:jar (default-cli) @ tidepool-model ---
[INFO] BUILD SUCCESS
(Only the three plugin executions and the result were kept.) This is how a goal such as jar:jar is run without its lifecycle: it
packages whatever is in target/classes. It is also how mistakes happen: mvn jar:jar in a clean tree builds an empty JAR, because
the compile phase that would have filled target/classes was not requested.
How a prefix is found
compiler, dependency, jar and help are plugin prefixes. Maven resolves a prefix by looking, in order, at the plugins already
declared in the POM and its parents, and then at the pluginGroups of settings.xml, which by default contain
org.apache.maven.plugins and org.codehaus.mojo, using the repository metadata of those groups. A prefix that cannot be found
fails with a message that lists exactly where Maven looked:
mvn -B -ntp foo:bar
[ERROR] No plugin found for prefix 'foo' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (~/.m2/repository), central (https://repo.maven.apache.org/maven2)] -> [Help 1]
(Only the first error line is shown; it is followed by the standard hint lines.) The tilde stands for the home directory. Plugin
prefixes are explained, with the pluginGroups setting, in the Maven guide.
The three classic mistakes
A typo in a phase name is reported together with the full list of valid phases, which is the quickest way to see them all:
mvn -B -ntp compil
[ERROR] Unknown lifecycle phase "compil". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: pre-clean, clean, post-clean, validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-site, site, post-site, site-deploy. -> [Help 1]
(Only the first error line is shown.) The Maven help page behind [Help 1] is LifecyclePhaseNotFoundException. A real prefix with a
wrong goal name lists the goals the plugin does have:
mvn -B -ntp compiler:nothing
[ERROR] Could not find goal 'nothing' in plugin org.apache.maven.plugins:maven-compiler-plugin:3.16.0 among available goals compile, help, testCompile -> [Help 1]
(Again the first error line.) The third mistake comes from using an option on a release that does not have it. The -UA option of Maven 3.10 (below) does not exist on
Maven 3.9.16, and that release does not reject it as an unknown option: it reads -UA as -U followed by -A, and the
second letter is taken as a phase name:
# Maven 3.9.16
mvn -B -ntp -UA -N validate
[ERROR] Unknown lifecycle phase "A". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: pre-clean, clean, post-clean, validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-site, site, post-site, site-deploy. -> [Help 1]
(First error line only.)
Controlling the output
-B, -ntp and -V: build logs for machines
-B (--batch-mode) runs Maven non-interactively: it never prompts, it disables the coloured output, and it makes the output suitable for
a log file. It is the first option of every CI command. -ntp (--no-transfer-progress) suppresses the per-file download
progress that otherwise fills a CI log with Downloading from and Downloaded from lines; it does not hide failures. -V (--show-version) prints the version banner and then continues with the build, which is what you want
at the top of a CI log:
mvn -B -ntp -V -N validate
Apache Maven 3.10.0 (c43a36b8d67be7e0805a411bc0898af1a51f5472)
Maven home: <tools>/apache-maven-3.10.0
Java version: 26, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-26.jdk/Contents/Home
Default locale: es_ES, platform encoding: UTF-8, time zone: Europe/Madrid
OS name: "mac os x", version: "27.0.1", arch: "aarch64", family: "mac"
[INFO] Scanning for projects...
[INFO] --------------------< io.tidepool:tidepool-parent >---------------------
[INFO] Building tidepool-parent 1.0.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ pom ]---------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
(The banner is what mvn -v prints, here shown as printed except that the scratch path of the Maven installation is <tools> in the later listings, and the build footer
was cut. The 3.10.0 release notes list the time zone in the banner as new.) -v (--version), in lower case, prints the banner
and stops. The "Maven home" and "Java version" lines are the first thing to check when a CI build behaves differently from a laptop
build: they say which Maven and which JDK answered.
Source: Maven 3.10.0 release notes
-q, -e and -X: less, more, and everything
-q (--quiet) shows errors only. A successful build prints nothing at all, and the exit code carries the result:
mvn -q compiler:compile
echo "exit=$?"
exit=0
On failure it prints just the errors, including the failed test and the stack frame that failed it (this ran tidepool-engine with -DfailEngine=true, which makes
the extra test fail; the output was cut after the first lines of the Maven error):
mvn -q -DfailEngine=true -f tidepool-engine test
[ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.027 s <<< FAILURE! -- in io.tidepool.engine.FailSwitchTest
[ERROR] io.tidepool.engine.FailSwitchTest.failsWhenAskedTo -- Time elapsed: 0.016 s <<< FAILURE!
org.opentest4j.AssertionFailedError: failEngine was set ==> expected: <false> but was: <true>
at org.junit.jupiter.api.Assertions.assertFalse(Assertions.java:266)
at io.tidepool.engine.FailSwitchTest.failsWhenAskedTo(FailSwitchTest.java:10)
[ERROR] Failures:
[ERROR] FailSwitchTest.failsWhenAskedTo:10 failEngine was set ==> expected: <false> but was: <true>
[ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.6.0:test (default-test) on project tidepool-engine: There are test failures.
-e (--errors) adds the Java stack trace of the build failure, which is what you attach to an issue against a plugin. A build error that
is caused by a plugin exception, here an impossible compiler release (-Dmaven.compiler.release=99), prints a one-line message without -e,
and with -e:
mvn -B -ntp -e -Dmaven.compiler.release=99 compile
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.710 s
[INFO] Finished at: 2026-10-16T14:35:40+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.16.0:compile (default-compile) on project tidepool-model: Fatal error compiling: error: release version 99 not supported
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.16.0:compile (default-compile) on project tidepool-model: Fatal error compiling
at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:342)
at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:324)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:220)
...
Caused by: org.apache.maven.plugin.MojoExecutionException: Fatal error compiling
at org.apache.maven.plugin.compiler.AbstractCompilerMojo.executeReal (AbstractCompilerMojo.java:1291)
at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute (AbstractCompilerMojo.java:734)
(The stack was cut at the ellipsis line and after the first Caused by frames; the whole output of the run was 151 lines.) A failure of the kind "there are test failures" is a
MojoFailureException, which has no stack trace to show, so -e adds nothing there; use it when the cause is an exception, such as
a plugin crash, an unreadable file or a bad configuration.
-X (--debug) produces debug output: 397 lines for a single compiler:compile goal run with -B -ntp, against 18 without it. It includes where each
settings and toolchains file was read from, the lifecycle definitions, the complete class-realm setup (the Imported: lines), and for each
plugin execution the value of every parameter. The parameter dump is the most useful part: it answers "which value did the plugin
actually get", and (f) or (s) says whether Maven injected it into a field or through a setter:
mvn -B -ntp -X compiler:compile > x.txt
grep -E "Reading (global|user) (settings|toolchains)|^\[DEBUG\] Lifecycle|\(.\) (release|source|target) =" x.txt
[DEBUG] Reading global settings from <tools>/apache-maven-3.10.0/conf/settings.xml
[DEBUG] Reading user settings from ~/.m2/settings.xml
[DEBUG] Reading global toolchains from <tools>/apache-maven-3.10.0/conf/toolchains.xml
[DEBUG] Reading user toolchains from ~/.m2/toolchains.xml
[DEBUG] Lifecycle clean -> [pre-clean, clean, post-clean]
[DEBUG] Lifecycle default -> [validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, gen...
[DEBUG] Lifecycle site -> [pre-site, site, post-site, site-deploy]
[DEBUG] (s) release = 21
[DEBUG] (f) source = 1.8
[DEBUG] (s) target = 1.8
(Filtered with grep, and the long Lifecycle default line cut short.) The release = 21 line is the maven.compiler.release property of the
parent POM, reaching the plugin; source and target are the plugin’s own defaults, which release takes precedence over. The debug
log of the same run also shows, for example, that the maven-default-http-blocker mirror is applied to plain-HTTP repositories. In Maven 4 the same option is spelled --verbose and -X is kept as an alias; see
Maven 4.
-l and colour
-l file (--log-file) sends all output to a file instead of the console and disables the colour. The console stays empty and the exit code is
unchanged:
mvn -ntp -l build.log -N validate
echo "exit=$?"
head -4 build.log
exit=0
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------< io.tidepool:tidepool-parent >---------------------
[INFO] Building tidepool-parent 1.0.0-SNAPSHOT
Colour is off when the output is piped or redirected (measured below) and when -B or -l is given. To
force it back on (for a CI system that renders ANSI colours), use the system property style.color or the --color option, which takes
auto, always or never. The count below is the number of lines of the output that contain an ANSI escape character, measured with
grep -c on a piped run (so, without colour by default):
Command (-ntp -N validate) |
3.9.16 | 3.10.0 | 4.0.0-rc-7 |
|---|---|---|---|
(no colour option) |
0 |
0 |
0 |
|
12 |
12 |
12 |
|
12 |
12 |
12 |
|
0 |
0 |
0 |
|
0 |
0 |
0 |
|
0 |
0 |
0 |
Two things to take from the table. First, -B wins over the colour options: do not combine -B with a request for colour. Second, the
space-separated form --color always did not turn the colour on in any of the three releases; use --color=always or the property
-Dstyle.color=always. The reason was not investigated here.
Properties and profiles
-D: user properties
-Dname=value defines a user property. User properties have the highest precedence: they override a <properties> entry of the POM
and are visible to every plugin, so they are how a build is parameterised from the outside. -Dname with no value defines the
property as true, and a value with spaces needs quoting for the shell:
mvn -q -N help:evaluate -Dexpression=greeting -DforceStdout
mvn -q -N -Dgreeting=from-the-cli help:evaluate -Dexpression=greeting -DforceStdout
mvn -B -q -Dfoo help:evaluate -Dexpression=foo -DforceStdout
mvn -B -q "-Dfoo=a b" help:evaluate -Dexpression=foo -DforceStdout
from-the-pom
from-the-cli
true
a b
(The first two were run in the tidepool parent, the last two in a scratch POM without a foo property; help:evaluate is the quickest way to see what an expression resolves
to, and -DforceStdout prints only the value.) The first two lines show a POM property and the command-line override of it. Settings of
the JVM that Maven runs in (the heap size, -Dfile.encoding) belong in MAVEN_OPTS, which is on
Configuring Maven.
Properties that plugins read are documented per plugin. Three are used constantly, and they are different in a way people regularly confuse:
mvn -B -ntp -pl tidepool-model clean package -DskipTests
mvn -B -ntp -pl tidepool-model clean package -Dmaven.test.skip=true
## -DskipTests
[INFO] --- compiler:3.16.0:testCompile (default-testCompile) @ tidepool-model ---
[INFO] --- surefire:3.6.0:test (default-test) @ tidepool-model ---
[INFO] Tests are skipped.
## -Dmaven.test.skip=true
[INFO] --- compiler:3.16.0:testCompile (default-testCompile) @ tidepool-model ---
[INFO] Not compiling test sources
[INFO] --- surefire:3.6.0:test (default-test) @ tidepool-model ---
[INFO] Tests are skipped.
(The two outputs were produced by two separate runs, labelled with the ## lines added here, and filtered to the test-related lines.)
-DskipTests compiles the tests and does not run them; -Dmaven.test.skip=true does not even compile them (Not compiling test sources), so no test classes exist to package. Prefer -DskipTests unless the test sources do
not compile.
To run one test, -Dtest=HeightTest selects by class name (-Dtest=HeightTest#methodName selects a method). On a multi-module build the
pattern matches in one module only, and Surefire fails the other modules for finding nothing to run:
mvn -B -ntp -Dtest=HeightTest test
[INFO] Reactor Summary for tidepool-parent 1.0.0-SNAPSHOT:
[INFO] tidepool-cli ....................................... SKIPPED
[INFO] tidepool-data ...................................... SKIPPED
[INFO] tidepool-parent .................................... SUCCESS [ 0.001 s]
[INFO] tidepool-model ..................................... SUCCESS [ 1.268 s]
[ERROR] tidepool-engine .................................... FAILURE [ 0.292 s]
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.6.0:test (default-test) on project tidepool-engine: No tests matching pattern "HeightTest" were executed! (Set -Dsurefire.failIfNoSpecifiedTests=false to ignore this error.) -> [Help 1]
(Filtered to the reactor summary and the first error line.) Adding -Dsurefire.failIfNoSpecifiedTests=false makes the other modules skip quietly, and
the run succeeds with Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.018 s — in io.tidepool.model.HeightTest. The
alternative is to select the module with -pl, below. Surefire itself is on
Testing with Surefire.
-P: profiles
-P id1,id2 activates profiles by id. Profiles are covered in depth on
Profiles; for the command line the useful facts are these. The ids are
comma-separated with no spaces. Selecting a profile that does not exist is a warning, not an error, which is how a typo silently disables
a CI profile:
mvn -B -ntp -Pnope -N validate
[WARNING] The requested profile "nope" could not be activated because it does not exist.
(Printed twice, once while reading the POM and once at the start of the build; shown once.) The profile fast of the scratch project sets
skipTests:
mvn -B -ntp -N help:active-profiles -Pfast
mvn -B -ntp -Pfast -pl tidepool-engine test
The following profiles are active:
- fast (source: io.tidepool:tidepool-parent:1.0.0-SNAPSHOT)
[INFO] Tests are skipped.
[INFO] BUILD SUCCESS
(Two runs, filtered; help:active-profiles lists what is active and where the profile was defined.) A profile can also be deactivated
from the command line by prefixing the id with ! or -. Because ! is special to the shell and a leading - looks like an option,
the guide recommends quoting the first and writing -P=-id for the second. A profile marked activeByDefault is switched off when
another profile is selected with -P, which is a classic surprise; a scratch POM with the profiles lenient (activeByDefault) and ci shows it:
mvn -B -ntp help:active-profiles
mvn -B -ntp -Pci help:active-profiles
mvn -B -ntp -P '!lenient' help:active-profiles
mvn -B -ntp -P=-lenient,ci help:active-profiles
## (no option)
The following profiles are active:
- lenient (source: io.tidepool.demo:profiles:1)
## -Pci
The following profiles are active:
- ci (source: io.tidepool.demo:profiles:1)
## -P '!lenient'
The following profiles are active:
## -P=-lenient,ci
The following profiles are active:
- ci (source: io.tidepool.demo:profiles:1)
(The four runs, filtered to the profile lines and separated by ## lines added here.) The second run is the surprise: asking for ci
did not add to lenient, it replaced it.
Choosing what to build in a reactor
When the current project is an aggregator, Maven builds it and all its modules as one reactor, in dependency order. The options in this section choose a subset. The reactor and the module order are on Multi-Module Builds & the Reactor.
-f and -N: which POM, and no recursion
-f path (--file) runs against another POM; the path may be the POM file or the directory that contains it. It lets a script
build a project without cding into it:
cd /tmp
mvn -B -ntp -f <tidepool>/tidepool-model validate
mvn -B -ntp -f <tidepool>/tidepool-model/pom.xml validate
[INFO] Building tidepool-model 1.0.0-SNAPSHOT
[INFO] from pom.xml
[INFO] BUILD SUCCESS
[INFO] BUILD SUCCESS
(The first command printed the Building lines and its BUILD SUCCESS; the second printed only its own BUILD SUCCESS in the filter, with the same project built.)
-N (--non-recursive) builds the project in the current directory and does not descend into <modules>. It is the natural option for
goals that act on a single POM, for example help:evaluate above, and for installing a parent POM on its own:
mvn -B -ntp -N validate
[INFO] Building tidepool-parent 1.0.0-SNAPSHOT
[INFO] BUILD SUCCESS
(Filtered to two lines: only tidepool-parent was built.) In Maven 4 -N combined with -pl also stops at the selected aggregators; see
below.
-pl, -am and -amd: project lists
-pl (--projects) takes a comma-separated list of the reactor projects to build instead of all of them. A project can be written as a
directory relative to the aggregator (tidepool-cli, ./tidepool-cli), as :artifactId or as groupId:artifactId; all four forms
selected the module in a run:
mvn -B -ntp -pl :tidepool-model validate
mvn -B -ntp -pl io.tidepool:tidepool-engine validate
mvn -B -ntp -pl ./tidepool-cli validate
mvn -B -ntp -pl tidepool-cli validate
[INFO] Building tidepool-model 1.0.0-SNAPSHOT
[INFO] Building tidepool-engine 1.0.0-SNAPSHOT
[INFO] Building tidepool-cli 1.0.0-SNAPSHOT
[INFO] Building tidepool-cli 1.0.0-SNAPSHOT
(Each command printed one Building line followed by BUILD SUCCESS; only the build lines are shown.) A name that is not in the reactor
is an error, naming it:
[ERROR] Could not find the selected project in the reactor: nope -> [Help 1]
(From mvn -B -ntp -pl nope validate; first error line only.) A project can be excluded by prefixing it with ! (quoted in the shell):
-pl '!tidepool-data,!tidepool-cli' built the parent, tidepool-model and tidepool-engine only, as its summary shows:
[INFO] Reactor Summary for tidepool-parent 1.0.0-SNAPSHOT:
[INFO]
[INFO] tidepool-parent .................................... SUCCESS [ 0.001 s]
[INFO] tidepool-model ..................................... SUCCESS [ 0.495 s]
[INFO] tidepool-engine .................................... SUCCESS [ 0.302 s]
[INFO] BUILD SUCCESS
(The command was mvn -B -ntp -pl '!tidepool-data,!tidepool-cli' test-compile; the footer was cut.) The prefix ?, which makes a project optional
so that a missing one is not an error, is not available in 3.10.0 or 3.9.16, which answered Could not find the selected project in the
reactor: ?nope, but is accepted by Maven 4.0.0-rc-7 (run: -pl '?nope,tidepool-model' built tidepool-model and ignored ?nope).
The module you select usually needs other modules, which are not on your list, or the other way round. -am (--also-make) adds the modules
the selection depends on; -amd (--also-make-dependents) adds the modules that depend on it:
mvn -B -ntp -pl tidepool-cli -am test-compile
mvn -B -ntp -pl tidepool-engine -amd test-compile
[INFO] Reactor Build Order:
[INFO] Building tidepool-parent 1.0.0-SNAPSHOT [1/4]
[INFO] Building tidepool-model 1.0.0-SNAPSHOT [2/4]
[INFO] Building tidepool-engine 1.0.0-SNAPSHOT [3/4]
[INFO] Building tidepool-cli 1.0.0-SNAPSHOT [4/4]
[INFO] Reactor Summary for tidepool-engine 1.0.0-SNAPSHOT:
[INFO] tidepool-engine .................................... SUCCESS [ 1.045 s]
[INFO] tidepool-cli ....................................... SUCCESS [ 0.090 s]
[INFO] BUILD SUCCESS
(The first four Building lines are from the first command: -am added the parent, tidepool-model and tidepool-engine, everything
tidepool-cli needs. The summary is from the second: -amd added the modules that depend on tidepool-engine, here only tidepool-cli.
Without -am, a build of -pl tidepool-cli takes tidepool-engine from the local repository, or fails if it is not installed there.) The two
options can be combined to add both directions.
-rf: resume from a project
When a module in the middle of a long reactor fails, -rf :artifactId (--resume-from) restarts the build at that module, skipping the
earlier ones. Maven prints the exact suggestion at the end of a failed build, as shown in the failure section below. Resuming at
tidepool-engine skips tidepool-parent and tidepool-model, and the build continues in reactor order, so the later modules
(tidepool-cli and tidepool-data) are included:
mvn -B -ntp -rf :tidepool-engine validate
[INFO] Reactor Build Order:
[INFO] Building tidepool-engine 1.0.0-SNAPSHOT [1/3]
[INFO] Building tidepool-cli 1.0.0-SNAPSHOT [2/3]
[INFO] Building tidepool-data 1.0.0-SNAPSHOT [3/3]
[INFO] BUILD SUCCESS
(Filtered.) The earlier modules are not built, so their artifacts must be available: either in the local repository from a previous
install, or by building them in the same invocation. An unknown project is an error that lists the
projects of the reactor:
[ERROR] Could not find project to resume reactor build from: :nope vs io.tidepool:tidepool-parent, io.tidepool:tidepool-model, io.tidepool:tidepool-engine, io.tidepool:tidepool-cli, io.tidepool:tidepool-data -> [Help 1]
(From mvn -B -ntp -rf :nope validate.) Maven 4 adds -r (--resume), which reads the project to resume at from a file that the failed
build wrote; see below.
-T: parallel builds
-T (--threads) builds modules in parallel. -T 4 uses four threads and -T 1C one thread per CPU core (C is the number of cores,
and 2.5C is allowed). Maven announces the change of builder:
mvn -B -ntp -T 4 clean test
mvn -B -ntp -T 1C -N validate
[INFO] Reactor Build Order:
[INFO] Using the MultiThreadedBuilder implementation with a thread count of 4
[INFO] Building tidepool-parent 1.0.0-SNAPSHOT [1/5]
[INFO] Building tidepool-model 1.0.0-SNAPSHOT [2/5]
[INFO] Building tidepool-data 1.0.0-SNAPSHOT [3/5]
[INFO] Building tidepool-engine 1.0.0-SNAPSHOT [4/5]
[INFO] Building tidepool-cli 1.0.0-SNAPSHOT [5/5]
[INFO] BUILD SUCCESS
[INFO] Using the MultiThreadedBuilder implementation with a thread count of 10
(The first block is from the first command, filtered; the last line is from the second command on a machine with ten cores. The [n/5] numbers
are the order in which modules were started: tidepool-data has no dependencies, so the reactor started it alongside tidepool-model
instead of last.) -T appeared in Maven 3.0. A plugin must be thread-safe to be used safely in a parallel build; whether the plugins of a build are is not something this
page tested. The builder can also be chosen by id with -b (--builder): an unknown id
fails with The builder requested using id = nope cannot be found. Parallel builds, the mvnd daemon and the build cache are on
Build Performance: Cache, Parallel Builds & mvnd.
When a module fails
Maven’s default for a reactor is to stop at the first failure; the other modules are reported as skipped. Three options change this. With the
FailSwitchTest failing in tidepool-engine (-DfailEngine=true), here are the four policies on the same project. The
reactor order is parent, model, engine, cli, data:
| Option | What it does | Exit code |
|---|---|---|
none, or |
Stop at the first failure. The modules after it, |
1 |
|
Keep building every module that does not depend on the failed one. |
1 |
|
Never fail the build. |
0 |
The reactor summaries of the first two cases on Maven 3.10.0:
## default (and -ff)
[INFO] Reactor Summary for tidepool-parent 1.0.0-SNAPSHOT:
[INFO] tidepool-cli ....................................... SKIPPED
[INFO] tidepool-data ...................................... SKIPPED
[INFO] tidepool-parent .................................... SUCCESS [ 0.003 s]
[INFO] tidepool-model ..................................... SUCCESS [ 0.974 s]
[ERROR] tidepool-engine .................................... FAILURE [ 0.405 s]
[ERROR] BUILD FAILURE
## -fae
[INFO] Reactor Summary for tidepool-parent 1.0.0-SNAPSHOT:
[INFO]
[INFO] tidepool-cli ....................................... SKIPPED
[INFO] tidepool-parent .................................... SUCCESS [ 0.001 s]
[INFO] tidepool-model ..................................... SUCCESS [ 0.927 s]
[INFO] tidepool-data ...................................... SUCCESS [ 0.237 s]
[ERROR] tidepool-engine .................................... FAILURE [ 0.335 s]
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
(Two separate runs, the ## lines are labels added here; blank INFO lines and the build timing lines were removed from the first.) Note the order of the
summary: Maven 3.10.0 lists skipped modules first, then the successful ones in reactor order and the failures last at error level. This is
a change documented in the 3.10.0 release notes ("the reactor summary is complete again: every module is listed, including the skipped
ones, and failures are reported last"). Maven 3.9.16 printed the modules in plain reactor order, with each module’s status in place:
tidepool-parent, tidepool-model, tidepool-engine FAILURE, tidepool-cli SKIPPED, tidepool-data SKIPPED for the
default policy. A script that parses the summary must handle both.
Both failing runs ended with the same advice from Maven 3.10.0:
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn <args> -rf :tidepool-engine
The exit codes were measured: -fae and the default policy returned 1, -fn returned 0. -fn is rarely a good idea in CI, because a
green build can contain failed tests; it exists for tools that want to continue and decide later, and combined with
-Dmaven.test.failure.ignore=true (a Surefire property, not a Maven option; not run here) it is how some people "build everything and look at the reports".
A CI build usually wants -fae, so one run reports every independent failure, and still fails the job.
Offline mode and forcing updates
-o: offline
-o (--offline) stops Maven from using the network. Anything already in the local repository still works; anything missing is an
error, and it names the repository that Maven would have asked. With an empty local repository (the property maven.repo.local points
Maven at another one, here empty-repo):
mvn -B -ntp -o -Dmaven.repo.local=../empty-repo -pl tidepool-model clean
[WARNING] The POM for org.apache.maven.plugins:maven-clean-plugin:jar:3.5.0 is missing, no dependency information available
[ERROR] BUILD FAILURE
[ERROR] Plugin org.apache.maven.plugins:maven-clean-plugin:3.5.0 or one of its dependencies could not be resolved:
[ERROR] Cannot access central (https://repo.maven.apache.org/maven2) in offline mode and the artifact org.apache.maven.plugins:maven-clean-plugin:jar:3.5.0 has not been downloaded from it before.
(Filtered; the same command without -o downloaded the plugin and succeeded.) With a warm repository, -o works as expected: mvn -B -ntp -o -pl
tidepool-model test ended in BUILD SUCCESS. Offline mode is the cheap way to find out which dependencies a project needs in a
network-less environment, and the usual way to run a build in a container with a pre-filled repository. The dependency:go-offline goal
is the usual way to try to fill that repository beforehand (not run here). Offline mode can also be switched on with <offline>true</offline> in settings.xml.
-U, -UA and -UM: forcing updates (3.10)
Maven remembers what it could not find. If a dependency is missing from a remote repository, the failure is cached in the local repository,
and Maven does not ask again until the repository’s update interval (daily by default) has elapsed. Publishing the missing artifact does
not help until then. -U (--update-snapshots) forces Maven to check, and despite its name it also retries the cached failures of
releases, not just snapshots. Maven 3.10.0 adds two finer options:
-
-UA(--update-artifacts): force the check for missing artifacts, retrying cached retrieval errors; -
-UM(--update-metadata): force the update of repository metadata: plugin prefixes, version ranges and snapshot lists.
and the matching long options --artifacts-update-policy and --metadata-update-policy, each taking always, daily or never; -UA and -UM
override them with always. All of this is from the 3.10.0 release notes.
Source: Maven 3.10.0 release notes
To see the difference, a scratch project depends on io.tidepool.demo:late-lib:1.0, which is declared in a file:// repository named team. The
artifact is absent at first, then published into that repository, with a fresh local repository each time. The first build fails, as it should
(dependency:resolve stands for any goal that needs the dependency):
[ERROR] Could not find artifact io.tidepool.demo:late-lib:jar:1.0 in team (file://<work>/upd/remote)
After the artifact is published, the same command fails again, now from the cache and with a different message:
[ERROR] io.tidepool.demo:late-lib:jar:1.0 was not found in file://<work>/upd/remote during a previous attempt. This failure was cached in the local repository and resolution is not reattempted until the update interval of team has elapsed or updates are forced
And the options, each tried from that same cached-failure state:
| Command | Result |
|---|---|
|
|
|
|
|
|
|
|
(Each row is from a real run. The first three were run one after the other in the same cached-failure state, -UA last; -UM and the plain command were repeated in the second copy, with the same result, before -U.) Use -U when you do not know what changed, -UA when
you know a missing artifact is now there, and -UM when a plugin prefix or a version range or a -SNAPSHOT timestamp is stale. The ancient
-up and -cpu ("check plugin updates") options and -npu and -npr are accepted by 3.10.0 but documented as "Ineffective, only kept for
backward compatibility"; they do nothing, and they are not in the Maven 4.0.0-rc-7 option list. -nsu (--no-snapshot-updates) suppresses the check for updated snapshots (not run here).
Checksums are another cause of a failed download: -C (--strict-checksums) fails the build when a checksum does not match and -c (--lax-checksums) only
warns. These were not run here; the default is set by the repository’s checksumPolicy, and the two options override it for the run. -itr
(--ignore-transitive-repositories) ignores the remote repositories that dependencies declare in their own POMs, so only the repositories
of the build and the settings are used; it was not run here.
Alternate settings, toolchains and logs
-s (--settings) names the user settings.xml, -gs (--global-settings) the global one; -t (--toolchains) and -gt (--global-toolchains)
the same for toolchains.xml. They replace ~/.m2/settings.xml and the file under the Maven installation, which is how CI runs with a
generated settings file. A scratch settings file with a project-local repository (${user.dir} is the directory Maven was started in)
and <interactiveMode>false</interactiveMode>:
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0">
<localRepository>${user.dir}/.m2-ci</localRepository>
<interactiveMode>false</interactiveMode>
</settings>
mvn -B -ntp -s ../ci-settings.xml -N help:evaluate -Dexpression=settings.localRepository -DforceStdout
<tidepool>/.m2-ci
(Only the evaluated value is shown; the run also downloaded the Help plugin into the new repository.) A file that does not exist is an immediate error, before any build starts:
[ERROR] Error executing Maven.
[ERROR] The specified user settings file does not exist: <work>/nope.xml
[ERROR] The specified global settings file does not exist: <work>/nope.xml
[ERROR] The specified user toolchains file does not exist: <work>/nope.xml
(Three runs, -s, -gs and -t, with the first message each; <work> replaces the scratch directory. -gt was not run here.) What the
settings files contain is on settings.xml & Password Encryption;
toolchains are on Compiling & Toolchains. The
-emp and -ep options (--encrypt-master-password, --encrypt-password) encrypt a password for settings.xml; they prompt for the password and
were not run here, for that reason. Maven 4 lists an --enc launcher option for its encryption tool instead.
Option reference
The table lists every option printed by mvn -h on Maven 3.10.0, as printed (the argument placeholder is in angle brackets), with a note on what it
does and where it is covered. "Not run here" means that the option exists in the help text but was not exercised in an example.
| Option | Meaning | Covered |
|---|---|---|
|
If a project list is specified, also build the projects required by the list. |
Choosing what to build |
|
If a project list is specified, also build the projects that depend on the list. |
Choosing what to build |
|
The update policy for artifacts: |
Forcing updates |
|
Non-interactive mode; disables the colour. |
Controlling the output |
|
The id of the build strategy to use. |
-T |
|
Fail the build if checksums do not match. |
Not run here |
|
Warn if checksums do not match. |
Not run here |
|
Colour mode: |
-l and colour |
|
Ineffective, kept for backward compatibility. |
Forcing updates |
|
Define a user property. |
-D |
|
Produce execution error messages (stack traces). |
-q, -e and -X |
|
Encrypt the master security password. |
Not run here |
|
Encrypt a server password. |
Not run here |
|
Force the use of an alternate POM file, or a directory with a |
-f and -N |
|
Only fail the build afterwards; allow all non-impacted builds to continue. |
When a module fails |
|
Stop at the first failure in reactorized builds (the default). |
When a module fails |
|
Never fail the build, regardless of the project result. |
When a module fails |
|
Alternate path for the global settings file. |
Alternate settings |
|
Alternate path for the global toolchains file. |
Alternate settings |
|
Display help information. |
The synopsis |
|
Ignore the remote repositories introduced by transitive dependencies. |
Not run here |
|
Send all output to a log file (disables colour). |
-l and colour |
|
UNSUPPORTED: using it makes the invocation fail. |
Not run here |
|
The update policy for metadata; |
Forcing updates |
|
Do not recurse into sub-projects. |
-f and -N |
|
Ineffective, kept for backward compatibility. |
Forcing updates |
|
Ineffective, kept for backward compatibility. |
Forcing updates |
|
Suppress SNAPSHOT updates. |
Forcing updates |
|
Do not display transfer progress when downloading or uploading. |
-B, -ntp and -V |
|
Work offline. |
-o |
|
Comma-delimited list of profiles to activate. |
-P |
|
Comma-delimited list of reactor projects to build, by |
-pl, -am and -amd |
|
Quiet output: only show errors. |
-q, -e and -X |
|
"Ignored (Maven4 option)" in 3.10.0. |
Maven 4 |
|
Resume the reactor from the specified project. |
-rf |
|
Alternate path for the user settings file. |
Alternate settings |
|
Alternate path for the user toolchains file. |
Alternate settings |
|
Thread count, for instance |
-T |
|
Force a check for missing releases and updated snapshots on remote repositories. |
Forcing updates |
|
Force checks for missing artifacts (retries cached retrieval errors). New in 3.10. |
Forcing updates |
|
Force updates of repository metadata (plugin prefixes, version ranges and snapshots). New in 3.10. |
Forcing updates |
|
Ineffective, kept for backward compatibility. |
Forcing updates |
|
Display the version information and stop. |
-B, -ntp and -V |
|
Display the version information without stopping the build. |
-B, -ntp and -V |
|
Produce execution debug output. |
-q, -e and -X |
The same list on Maven 3.9.16 lacks -UA, -UM, --artifacts-update-policy and --metadata-update-policy; apart from those four entries the two
mvn --help outputs are identical (compared with diff).
Maven 4 (release candidate)
Maven 4.0.0-rc-7 reshapes the option list; the full set printed by its mvn --help was compared with the 3.10.0 one. The changes that matter
on the command line:
| Option | Maven 4.0.0-rc-7 |
|---|---|
|
Resume the reactor from the last failed project, using the |
|
Fail the build when anything is logged at or above a severity, such as |
|
|
|
The new name of |
|
New settings and toolchains levels: the project, and the installation. |
|
Load command line options from a file and merge them with the CLI ones. |
|
"When used together with -pl, do not recurse into sub-projects of selected aggregators." |
|
An optional project: if it is not in the reactor it is ignored. |
|
|
|
Not in the Maven 4.0.0-rc-7 option list. |
The two options people ask about most were run. -r after a failed build (-fae -DfailEngine=true, then fixing the failure by running without the
property) picks up where the first run stopped:
# Maven 4.0.0-rc-7
mvn -B -ntp -fae -DfailEngine=true test
cat target/resume.properties
mvn -B -ntp -r test
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn [args] -r
#Fri Oct 16 14:38:36 CEST 2026
remainingProjects=io.tidepool\:tidepool-engine, io.tidepool\:tidepool-cli
[INFO] Resuming from io.tidepool:tidepool-engine, io.tidepool:tidepool-cli due to the --resume / -r feature.
[INFO] Building tidepool-engine 1.0.0-SNAPSHOT [4/5]
[INFO] Building tidepool-cli 1.0.0-SNAPSHOT [5/5]
[INFO] Reactor Summary for tidepool-engine 1.0.0-SNAPSHOT:
[INFO] tidepool-engine .................................... SUCCESS [ 1.667 s]
[INFO] tidepool-cli ....................................... SUCCESS [ 0.440 s]
[INFO] BUILD SUCCESS
(Three commands; the output is filtered.) Note that -r needs no project name: the failed build recorded the remaining projects. The resume
file lives in the build directory of the top project, and the successful build deleted it. -fos (--fail-on-severity) turns warnings into failures:
tidepool-data has no main sources, so packaging it logs JAR will be empty. With -fos WARN:
# Maven 4.0.0-rc-7
mvn -B -ntp -fos WARN -pl tidepool-data package
[INFO] Enabled to break the build on log level WARN.
[WARNING] JAR will be empty - no content was marked for inclusion!
[ERROR] BUILD FAILURE
[ERROR] Build failed due to log statements with a higher severity than allowed. Fix the logged issues or remove flag --fail-on-severity (-fos).
(Filtered. The run also logged a WARNING about the dependency state of target/classes, which is also counted.) The exit code was 1; with
-fos ERROR the same project built with exit code 0. On Maven 3.10.0 the option does not exist and -fos is not rejected cleanly: it appears to be read as -f with the
value os, and the build fails with Non-readable POM, followed by a path ending in os. Check the help of the Maven you run.
Recipes
A CI build with the options of this page, run on the scratch project (exit code 0; the end of the output is shown):
mvn -B -ntp -V verify
[INFO] Reactor Summary for tidepool-parent 1.0.0-SNAPSHOT:
[INFO]
[INFO] tidepool-parent .................................... SUCCESS [ 0.000 s]
[INFO] tidepool-model ..................................... SUCCESS [ 1.115 s]
[INFO] tidepool-engine .................................... SUCCESS [ 0.711 s]
[INFO] tidepool-cli ....................................... SUCCESS [ 0.417 s]
[INFO] tidepool-data ...................................... SUCCESS [ 0.342 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Everyday recipes, none of which needs more than the options above (the commands were assembled from options that were run individually above, not run as written):
| Goal | Command |
|---|---|
The default for CI: logs without noise, versions at the top |
|
Everything that can run, then report all independent failures |
|
One module and what it needs, no tests |
|
A module and everything that uses it, to check a change |
|
One test class in one module |
|
Continue after fixing a failure (3.x) |
|
Continue after fixing a failure (Maven 4) |
|
Are my dependencies reachable offline? |
|
A dependency that was published after a failed attempt |
|
Build in parallel |
|
Save the whole log, show nothing |
|
Why did this plugin get that value? |
|
The command line that CI uses is worth keeping out of the shell history and in the project. The .mvn/maven.config file and the MAVEN_ARGS variable (3.9.0 and
later) hold default options, and the Maven Wrapper (mvnw) pins the Maven version itself; they are on
Configuring Maven and
Maven Wrapper.
Where the books are out of date
Older books describe a Maven 2 command line. The parts that matter today:
-
They tell you to install a reactor plugin or to use the 2.1-era
--reactorflags. All of it is built into the command line:-pl,-am,-amd,-rf,-fae,-T. The reference is the guide linked in Choosing what to build. -
They show
-Uas "update snapshots" only. As above, it also retries cached failures for releases, and 3.10 gives you-UAand-UMfor each half. -
They use
archetype:create, which is gone (archetype:generatereplaced it); see Getting Started. -
They stop at Maven 3’s options. Maven 4 adds
-r,-fosand the project and installation settings options listed above.
Equivalents in Ant and Gradle
| Need | Maven | Ant | Gradle |
|---|---|---|---|
Run a named unit of work |
|
|
|
More diagnostic output |
|
|
|
Less output |
|
|
|
Stack trace on failure |
|
(in the |
|
Define a property |
|
|
|
Alternate build file or directory |
|
|
|
Offline |
|
(no option) |
|
Refresh dependencies |
|
(no option) |
|
Parallel build |
|
(no option) |
|
Keep going after a failure |
|
|
|
(The Ant column is read from ant -h of Ant 1.10.18 and the Gradle column from gradle -h of Gradle 9.8.1; the options of those two tools were not run
for this page. "No option" means that the help lists none. The "stack trace" row for Ant is left without an option for that reason.) Ant’s options are on
Running Ant and Gradle’s on
Command-Line Interface; the whole comparison of how the
three tools are driven is on Comparing Ant, Maven & Gradle.