ChatGPT解决这个技术问题 Extra ChatGPT

Differences between Ant and Maven [closed]

Closed. This question needs to be more focused. It is not currently accepting answers. Want to improve this question? Update the question so it focuses on one problem only by editing this post. Closed 8 years ago. Improve this question

Could someone tell me the differences between Ant and Maven? I have never used either. I understand that they are used to automate the building of Java projects, but I do not know where to start from.

Since answers are dominated by Maven advocates I would like to balance it a little. See this answer for example stackoverflow.com/questions/1306579/…
While this does not directly answer the question of comparing Ant vs Maven, my input would be to look at using Gradle, which could give you access to both Ant and Maven simultaneously. gradle.org

h
hjpotter92

In Maven: The Definitive Guide, I wrote about the differences between Maven and Ant in the introduction the section title is "The Differences Between Ant and Maven". Here's an answer that is a combination of the info in that introduction with some additional notes.

A Simple Comparison

I'm only showing you this to illustrate the idea that, at the most basic level, Maven has built-in conventions. Here's a simple Ant build file:

<project name="my-project" default="dist" basedir=".">
    <description>
        simple example build file
    </description>   
    <!-- set global properties for this build -->   
    <property name="src" location="src/main/java"/>
    <property name="build" location="target/classes"/>
    <property name="dist"  location="target"/>

    <target name="init">
      <!-- Create the time stamp -->
      <tstamp/>
      <!-- Create the build directory structure used by compile -->
      <mkdir dir="${build}"/>   
    </target>

    <target name="compile" depends="init"
        description="compile the source " >
      <!-- Compile the java code from ${src} into ${build} -->
      <javac srcdir="${src}" destdir="${build}"/>  
    </target>

    <target name="dist" depends="compile"
        description="generate the distribution" >
      <!-- Create the distribution directory -->
      <mkdir dir="${dist}/lib"/>

      <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file
-->
      <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
   </target>

   <target name="clean"
        description="clean up" >
     <!-- Delete the ${build} and ${dist} directory trees -->
     <delete dir="${build}"/>
     <delete dir="${dist}"/>
   </target>
 </project>

In this simple Ant example, you can see how you have to tell Ant exactly what to do. There is a compile goal which includes the javac task that compiles the source in the src/main/java directory to the target/classes directory. You have to tell Ant exactly where your source is, where you want the resulting bytecode to be stored, and how to package this all into a JAR file. While there are some recent developments that help make Ant less procedural, a developer's experience with Ant is in coding a procedural language written in XML.

Contrast the previous Ant example with a Maven example. In Maven, to create a JAR file from some Java source, all you need to do is create a simple pom.xml, place your source code in ${basedir}/src/main/java and then run mvn install from the command line. The example Maven pom.xml that achieves the same results.

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.sonatype.mavenbook</groupId>
  <artifactId>my-project</artifactId>
  <version>1.0</version>
</project>

That's all you need in your pom.xml. Running mvn install from the command line will process resources, compile source, execute unit tests, create a JAR, and install the JAR in a local repository for reuse in other projects. Without modification, you can run mvn site and then find an index.html file in target/site that contains links to JavaDoc and a few reports about your source code.

Admittedly, this is the simplest possible example project. A project which only contains source code and which produces a JAR. A project which follows Maven conventions and doesn't require any dependencies or customization. If we wanted to start customizing the behavior, our pom.xml is going to grow in size, and in the largest of projects you can see collections of very complex Maven POMs which contain a great deal of plugin customization and dependency declarations. But, even when your project's POM files become more substantial, they hold an entirely different kind of information from the build file of a similarly sized project using Ant. Maven POMs contain declarations: "This is a JAR project", and "The source code is in src/main/java". Ant build files contain explicit instructions: "This is project", "The source is in src/main/java", "Run javac against this directory", "Put the results in target/classses", "Create a JAR from the ....", etc. Where Ant had to be explicit about the process, there was something "built-in" to Maven that just knew where the source code was and how it should be processed.

High-level Comparison

The differences between Ant and Maven in this example? Ant...

doesn't have formal conventions like a common project directory structure, you have to tell Ant exactly where to find the source and where to put the output. Informal conventions have emerged over time, but they haven't been codified into the product.

is procedural, you have to tell Ant exactly what to do and when to do it. You had to tell it to compile, then copy, then compress.

doesn't have a lifecycle, you had to define goals and goal dependencies. You had to attach a sequence of tasks to each goal manually.

Where Maven...

has conventions, it already knew where your source code was because you followed the convention. It put the bytecode in target/classes, and it produced a JAR file in target.

is declarative. All you had to do was create a pom.xml file and put your source in the default directory. Maven took care of the rest.

has a lifecycle, which you invoked when you executed mvn install. This command told Maven to execute a series of sequence steps until it reached the lifecycle. As a side-effect of this journey through the lifecycle, Maven executed a number of default plugin goals which did things like compile and create a JAR.

What About Ivy?

Right, so someone like Steve Loughran is going to read that comparison and call foul. He's going to talk about how the answer completely ignores something called Ivy and the fact that Ant can reuse build logic in the more recent releases of Ant. This is true. If you have a bunch of smart people using Ant + antlibs + Ivy, you'll end up with a well designed build that works. Even though, I'm very much convinced that Maven makes sense, I'd happily use Ant + Ivy with a project team that had a very sharp build engineer. That being said, I do think you'll end up missing out on a number of valuable plugins such as the Jetty plugin and that you'll end up doing a whole bunch of work that you didn't need to do over time.

More Important than Maven vs. Ant

Is that you use a Repository Manager to keep track of software artifacts. I'd suggest downloading Nexus. You can use Nexus to proxy remote repositories and to provide a place for your team to deploy internal artifacts. You have appropriate modularization of software components. One big monolithic component rarely scales over time. As your project develops, you'll want to have the concept of modules and sub-modules. Maven lends itself to this approach very well. You adopt some conventions for your build. Even if you use Ant, you should strive to adopt some form of convention that is consistent with other projects. When a project uses Maven, it means that anyone familiar with Maven can pick up the build and start running with it without having to fiddle with configuration just to figure out how to get the thing to compile.


Links are broken again.
I use Nebeans and Ant works by default without any tunings (Netbeans conventions?). Currently trying Maven and find it more lengthy during first builds and constantly using internet connection. Building offline is possibly impossible. This is uncomfortable.
K
KevinS

Maven is a Framework, Ant is a Toolbox

Maven is a pre-built road car, whereas Ant is a set of car parts. With Ant you have to build your own car, but at least if you need to do any off-road driving you can build the right type of car.

To put it another way, Maven is a framework whereas Ant is a toolbox. If you're content with working within the bounds of the framework then Maven will do just fine. The problem for me was that I kept bumping into the bounds of the framework and it wouldn't let me out.

XML Verbosity

tobrien is a guy who knows a lot about Maven and I think he provided a very good, honest comparison of the two products. He compared a simple Maven pom.xml with a simple Ant build file and he made mention of how Maven projects can become more complex. I think that its worth taking a look at a comparison of a couple of files that you are more likely to see in a simple real-world project. The files below represent a single module in a multi-module build.

First, the Maven file:

<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 http://maven.apache.org/maven-4_0_0.xsd">

    <parent>
        <groupId>com.mycompany</groupId>
        <artifactId>app-parent</artifactId>
        <version>1.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>persist</artifactId>
    <name>Persistence Layer</name>

    <dependencies>

        <dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>common</artifactId>
            <scope>compile</scope>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>domain</artifactId>
            <scope>provided</scope>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate</artifactId>
            <version>${hibernate.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>${commons-lang.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring</artifactId>
            <version>${spring.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.dbunit</groupId>
            <artifactId>dbunit</artifactId>
            <version>2.2.3</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
            <classifier>jdk15</classifier>
        </dependency>

        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>${commons-dbcp.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc</artifactId>
            <version>${oracle-jdbc.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.easymock</groupId>
            <artifactId>easymock</artifactId>
            <version>${easymock.version}</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

And the equivalent Ant file:

<project name="persist" >

    <import file="../build/common-build.xml" />


    <path id="compile.classpath.main">
        <pathelement location="${common.jar}" />
        <pathelement location="${domain.jar}" />
        <pathelement location="${hibernate.jar}" />
        <pathelement location="${commons-lang.jar}" />
        <pathelement location="${spring.jar}" />
    </path>


    <path id="compile.classpath.test">
        <pathelement location="${classes.dir.main}" />
        <pathelement location="${testng.jar}" />
        <pathelement location="${dbunit.jar}" />
        <pathelement location="${easymock.jar}" />
        <pathelement location="${commons-dbcp.jar}" />
        <pathelement location="${oracle-jdbc.jar}" />
        <path refid="compile.classpath.main" />
    </path>


    <path id="runtime.classpath.test">
        <pathelement location="${classes.dir.test}" />
        <path refid="compile.classpath.test" />
    </path>


</project>

tobrien used his example to show that Maven has built-in conventions but that doesn't necessarily mean that you end up writing less XML. I have found the opposite to be true. The pom.xml is 3 times longer than the build.xml and that is without straying from the conventions. In fact, my Maven example is shown without an extra 54 lines that were required to configure plugins. That pom.xml is for a simple project. The XML really starts to grow significantly when you start adding in extra requirements, which is not out of the ordinary for many projects.

But you have to tell Ant what to do

My Ant example above is not complete of course. We still have to define the targets used to clean, compile, test etc. These are defined in a common build file that is imported by all modules in the multi-module project. Which leads me to the point about how all this stuff has to be explicitly written in Ant whereas it is declarative in Maven.

Its true, it would save me time if I didn't have to explicitly write these Ant targets. But how much time? The common build file I use now is one that I wrote 5 years ago with only slight refinements since then. After my 2 year experiment with Maven, I pulled the old Ant build file out of the closet, dusted it off and put it back to work. For me, the cost of having to explicitly tell Ant what to do has added up to less than a week over a period of 5 years.

Complexity

The next major difference I'd like to mention is that of complexity and the real-world effect it has. Maven was built with the intention of reducing the workload of developers tasked with creating and managing build processes. In order to do this it has to be complex. Unfortunately that complexity tends to negate their intended goal.

When compared with Ant, the build guy on a Maven project will spend more time:

Reading documentation: There is much more documentation on Maven, because there is so much more you need to learn.

Educating team members: They find it easier to ask someone who knows rather than trying to find answers themselves.

Troubleshooting the build: Maven is less reliable than Ant, especially the non-core plugins. Also, Maven builds are not repeatable. If you depend on a SNAPSHOT version of a plugin, which is very likely, your build can break without you having changed anything.

Writing Maven plugins: Plugins are usually written with a specific task in mind, e.g. create a webstart bundle, which makes it more difficult to reuse them for other tasks or to combine them to achieve a goal. So you may have to write one of your own to workaround gaps in the existing plugin set.

In contrast:

Ant documentation is concise, comprehensive and all in one place.

Ant is simple. A new developer trying to learn Ant only needs to understand a few simple concepts (targets, tasks, dependencies, properties) in order to be able to figure out the rest of what they need to know.

Ant is reliable. There haven't been very many releases of Ant over the last few years because it already works.

Ant builds are repeatable because they are generally created without any external dependencies, such as online repositories, experimental third-party plugins etc.

Ant is comprehensive. Because it is a toolbox, you can combine the tools to perform almost any task you want. If you ever need to write your own custom task, it's very simple to do.

Familiarity

Another difference is that of familiarity. New developers always require time to get up to speed. Familiarity with existing products helps in that regard and Maven supporters rightly claim that this is a benefit of Maven. Of course, the flexibility of Ant means that you can create whatever conventions you like. So the convention I use is to put my source files in a directory name src/main/java. My compiled classes go into a directory named target/classes. Sounds familiar doesn't it.

I like the directory structure used by Maven. I think it makes sense. Also their build lifecycle. So I use the same conventions in my Ant builds. Not just because it makes sense but because it will be familiar to anyone who has used Maven before.


I really like how you "Stole" ideas from Maven and apply them to your Ant builds to follow common conventions and make transition easer for others.
To avoid bloat in pom.xmls, I generate most of them via XSLT.
c
cherouvim

Ant is mainly a build tool.

Maven is a project and dependencies management tool (which of course builds your project as well).

Ant+Ivy is a pretty good combination if you want to avoid Maven.


This. Comparison between Ant+Ivy and Maven2 here: ant.apache.org/ivy/m2comparison.html
Why would you want to avoid Maven? Maven is, in my experience, one of the few parts of java development that's pleasant.
@Benson: It's a controversial issue. If it was the silver bullet then everyone would be using it.
A
Ascalonian

Just to list some more differences:

Ant doesn't have formal conventions. You have to tell Ant exactly where to find the source, where to put the outputs, etc.

Ant is procedural. You have to tell Ant exactly what to do; tell it to compile, copy, then compress, etc.

Ant doesn't have a lifecycle.

Maven uses conventions. It knows where your source code is automatically, as long as you follow these conventions. You don't need to tell Maven where it is.

Maven is declarative; All you have to do is create a pom.xml file and put your source in the default directory. Maven will take care of the rest.

Maven has a lifecycle. You simply call mvn install and a series of sequence steps are executed.

Maven has intelligence about common project tasks. To run tests, simple execute mvn test, as long as the files are in the default location. In Ant, you would first have to JUnit JAR file is, then create a classpath that includes the JUnit JAR, then tell Ant where it should look for test source code, write a goal that compiles the test source and then finally execute the unit tests with JUnit.

Update:

This came from Maven: The Definitive Guide. Sorry, I totally forgot to cite it.


Was that update a pun?
@vakio - I am going to guess you mean because I used "site" instead of "cite"? That was totally a bad spelling on my part and I fixed it
C
Community

Maven or Ant? is a very similar question to this one, which should help you answer your questions.

What is Maven? on the official site.

edit: For a new/greenfield project, I'd recommend using Maven: "convention over configuration" will save you a decent chunk of time in writing and setting up build and deployment scripts. When you use ant, the build script tends to grow over time in length and complexity. For existing projects, it can be hard to shoehorn their configuration/layout into the Maven system.


Maven will save you time at the beginning of your project but over time, if you have anything other than a very simple project, the Maven scripts will become far more complicated than the Ant equivalent. For example, look at the Maven Assembly plugin.
I would argue that accomplishing what the Assembly plugin does is so much easier to do in it's Maven format (where you lay out the model of the assembly in xml format) than to do all of the manual steps in Ant, but YMMV
Hi Matt, the learning curve for the assembly plugin is much steeper than that for the Ant tar or zip task. The descriptor format is something like 150 lines long and contains a whole bunch of non-intuitive configuration options. On top of that, it doesn't work! At the point I gave up on the Assembly plugin, filtering on unpack didn't work and neither did file mode options and it couldn't fixcrlf. Not sure what you mean by "all of the manual steps in Ant". I spent about 5 minutes getting Ant to do what I couldn't get the assembly plugin to do in hours.
first link is now dead :/
J
James Kingsbery

Maven acts as both a dependency management tool - it can be used to retrieve jars from a central repository or from a repository you set up - and as a declarative build tool. The difference between a "declarative" build tool and a more traditional one like ant or make is you configure what needs to get done, not how it gets done. For example, you can say in a maven script that a project should be packaged as a WAR file, and maven knows how to handle that.

Maven relies on conventions about how project directories are laid out in order to achieve its "declarativeness." For example, it has a convention for where to put your main code, where to put your web.xml, your unit tests, and so on, but also gives the ability to change them if you need to.

You should also keep in mind that there is a plugin for running ant commands from within maven:

http://maven.apache.org/plugins/maven-ant-plugin/

Also, maven's archetypes make getting started with a project really fast. For example, there is a Wicket archetype, which provides a maven command you run to get a whole, ready-to-run hello world-type project.

https://wicket.apache.org/start/quickstart.html


a
alex

I can take a person that has never seen Ant - its build.xmls are reasonably well-written - and they can understand what is going on. I can take that same person and show them a Maven POM and they will not have any idea what is going on.

In an engineering organization that is huge, people write about Ant files becoming large and unmanageable. I've written those types and clean Ant scripts. It's really understanding upfront what you need to do going forward and designing a set of templates that can respond to change and scale over a 3+ year period.

Unless you have a simple project, learning the Maven conventions and the Maven way about getting things done is quite a bit of work.

At the end of the day you cannot consider project startup with Ant or Maven a factor: it's really the total cost of ownership. What it takes for the organization to maintain and extend its build system over a few years is one of the main factors that must be considered.

The most important aspects of a build system are dependency management and flexibility in expressing the build recipe. It must be somewhat intuitive when done well.


G
Gad

I'd say it depends upon the size of your project... Personnally, I would use Maven for simple projects that need straightforward compiling, packaging and deployment. As soon as you need to do some more complicated things (many dependencies, creating mapping files...), I would switch to Ant...


I disagree. I agree that it's good to use maven for simple projects, but I would argue that with increased complexity your benefits from using maven increase by orders of magnitude.
I disagree as well, Maven really starts to work well when you have a more complex system with many interrelated modules. If you need to write functional tests, run reports, and deploy artifacts to a repository manager, why would you do all of that yourself with Ant?
Maven is fine for a simple project, but I had a nightmare of a time trying to do things that should be simple in a more complex project. E.g. creating a distributable package, obfuscating code, creating a webstart bundle, configuring profiles. @Benson, as your project becomes more complex, Maven becomes a ball and chain. The power and flexibility of Ant will give you greater productivity benefits than Maven. @tobrien, Ant works just fine for multi-module projects, writing functional tests etc. Configuring non-default reporting plugins in Maven is usually more verbose than the Ant equivalent.
I've just started to add maven to an existing project and I found that things doesn't work as expected. The website is built in php and it is deployed using a script. These things doesn't work smoothly in Maven, you have to make very odd things to make it work.
m
markt

Maven also houses a large repository of commonly used open source projects. During the build Maven can download these dependencies for you (as well as your dependencies dependencies :)) to make this part of building a project a little more manageable.


+1, having seen what it takes to keep the Central Maven Repository up and running, I'll have to chime in and suggest that everybody using anything like Maven and Ivy should consider installing a repository manager. It doesn't matter which one, but I am partial to Nexus nexus.sonatype.org.