web-dev-qa-db-ja.com

AntとMavenの違い

誰かがAntとMavenの違いを教えてもらえますか?私も使用したことがありません。 Javaプロジェクトの構築を自動化するために使用されることは理解していますが、どこから始めればよいのかわかりません。

177
rtacconi

Maven:The Definitive Guide で、セクションタイトルが "AntとMavenの違い" の概要でMavenとAntの違いについて書きました。その紹介文の情報といくつかの追加のメモを組み合わせた回答があります。

簡単な比較

これは、最も基本的なレベルで、Mavenに組み込みの規則があるという考えを説明するためだけに示しています。簡単なAntビルドファイルを次に示します。

<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>

この単純なAntの例では、Antに何をすべきかを正確に伝える必要があることがわかります。 src/main/Javaディレクトリのソースをtarget/classesディレクトリにコンパイルするjavacタスクを含むコンパイルの目標があります。 Antにソースがどこにあるか、結果のバイトコードをどこに保存するか、これをすべてJARファイルにパッケージ化する方法を正確に伝える必要があります。 Antの手続き型を減らすのに役立つ最近の開発がいくつかありますが、Antでの開発者の経験は、XMLで記述された手続き型言語のコーディングにあります。

前のAntの例とMavenの例を比較してください。 MavenでJavaソースからJARファイルを作成するには、単純なpom.xmlを作成し、ソースコードを$ {basedir}/src/main/Javaに配置してから実行するだけです。コマンドラインからmvn install。同じ結果を達成するサンプルMaven pom.xml。

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

Pom.xmlに必要なのはそれだけです。コマンドラインからmvn installを実行すると、リソースの処理、ソースのコンパイル、単体テストの実行、JARの作成、およびローカルリポジトリへのJARのインストールが行われ、他のプロジェクトで再利用できます。変更することなく、mvnサイトを実行して、JavaDocへのリンクとソースコードに関するいくつかのレポートを含むindex.htmlファイルをtarget/siteで見つけることができます。

確かに、これは可能な限り単純なプロジェクト例です。ソースコードのみを含み、JARを生成するプロジェクト。 Mavenの規則に従っており、依存関係やカスタマイズを必要としないプロジェクト。動作のカスタマイズを開始したい場合、pom.xmlのサイズが大きくなり、最大のプロジェクトでは、多くのプラグインのカスタマイズと依存関係の宣言を含む非常に複雑なMaven POMのコレクションを見ることができます。ただし、プロジェクトのPOMファイルがより大きくなった場合でも、Antを使用した同様のサイズのプロジェクトのビルドファイルとはまったく異なる種類の情報を保持します。 Maven POMには、「これはJARプロジェクトです」と「ソースコードはsrc/main/Javaにあります」という宣言が含まれています。 Antビルドファイルには、「これはプロジェクトです」、「ソースはsrc/main/Javaにあります」、「このディレクトリに対してjavacを実行します」、「target/classsesに結果を入力します」、「...からJARを作成します」など。Antがプロセスについて明示的である必要があった場合、ソースコードがどこにあり、どのように処理されるべきかを知るだけの何かがMavenに組み込まれていました。

高レベル比較

この例のAntとMavenの違いは?蟻...

  • 一般的なプロジェクトのディレクトリ構造のような正式な規則はありません。ソースを見つけて出力をどこに置くかをAntに正確に伝える必要があります。非公式の慣習が時間の経過とともに現れてきましたが、それらは製品に体系化されていません。
  • 手続き型であるため、Antに何をいつ実行するかを正確に伝える必要があります。コンパイル、コピー、圧縮を指示する必要がありました。
  • ライフサイクルがないため、目標と目標の依存関係を定義する必要がありました。タスクのシーケンスを各目標に手動で添付する必要がありました。

どこMaven ...

  • 規約があり、規約に従ってソースコードがどこにあるかはすでにわかっています。バイトコードをターゲット/クラスに配置し、ターゲットにJARファイルを生成しました。
  • 宣言的です。必要なのは、pom.xmlファイルを作成し、ソースをデフォルトのディレクトリに置くことだけでした。残りはMavenが処理しました。
  • mvn installを実行したときに呼び出したライフサイクルがあります。このコマンドは、ライフサイクルに到達するまで一連のシーケンスステップを実行するようにMavenに指示しました。ライフサイクル全体のこの旅の副作用として、Mavenは、JARのコンパイルや作成などを行う多くのデフォルトのプラグイン目標を実行しました。

アイビーはどうですか?

そうです、スティーブ・ラフランのような人がその比較を読んで、ファウルを呼ぶでしょう。彼は、答えがIvyと呼ばれるものを完全に無視する方法と、Antの最近のリリースでビルドロジックを再利用できるという事実について説明します。これは本当です。 Ant + antlibs + Ivyを使用している優秀な人々がいる場合、うまく機能する適切に設計されたビルドになります。 Mavenが理にかなっていると確信していますが、非常に鋭いビルドエンジニアがいるプロジェクトチームでAnt + Ivyを喜んで使用します。そうは言っても、Jettyプラグインなどの多くの貴重なプラグインを見逃してしまうことになると思います。

Maven対Antよりも重要

  1. リポジトリマネージャーを使用してソフトウェアアーティファクトを追跡することです。 Nexusをダウンロード中 をお勧めします。 Nexusを使用して、リモートリポジトリをプロキシし、チームが内部成果物を展開する場所を提供できます。
  2. ソフトウェアコンポーネントを適切にモジュール化できます。 1つの大きなモノリシックコンポーネントが時間の経過とともにスケーリングすることはほとんどありません。プロジェクトの開発に伴い、モジュールとサブモジュールの概念が必要になります。 Mavenはこのアプローチに非常に適しています。
  3. ビルドにはいくつかの規則を採用します。 Antを使用する場合でも、他のプロジェクトと一貫性のある何らかの形式の規則を採用するよう努める必要があります。プロジェクトがMavenを使用する場合、Mavenに精通している人なら誰でもビルドを取得し、コンパイルする方法を理解するために構成をいじる必要なくビルドを実行できることを意味します。
216
Tim O'Brien

Mavenはフレームワーク、Antはツールボックス

Mavenは構築済みのロードカーですが、Antは一連の自動車部品です。 Antを使用すると、独自の車を構築する必要がありますが、少なくともオフロード走行を行う必要がある場合は、適切な種類の車を構築できます。

別の言い方をすれば、Mavenはフレームワークであり、Antはツールボックスです。フレームワークの範囲内での作業に満足している場合、Mavenは正常に機能します。私にとっての問題は、私がフレームワークの境界にぶつかり続け、それが私を手放さないことでした。

XML冗長性

tobrienはMavenについて多くのことを知っている人で、2つの製品の非常に良い、正直な比較を提供してくれたと思います。彼は単純なMaven pom.xmlを単純なAntビルドファイルと比較し、Mavenプロジェクトがより複雑になる方法について言及しました。単純な実世界のプロジェクトで見られる可能性が高いいくつかのファイルの比較を見る価値があると思います。以下のファイルは、マルチモジュールビルドの単一モジュールを表しています。

まず、Mavenファイル:

<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>

同等のAntファイル:

<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は彼の例を使用して、Mavenに組み込みの規則があることを示しましたが、それは必ずしもXMLの記述が少なくなるという意味ではありません。私は反対が真実であることがわかった。 pom.xmlはbuild.xmlの3倍の長さであり、慣例から逸脱することはありません。実際、私のMavenの例は、プラグインの構成に必要な追加の54行なしで示されています。そのpom.xmlは単純なプロジェクト用です。追加の要件を追加し始めると、XMLは実際に大きく成長し始めますが、これは多くのプロジェクトにとって異常ではありません。

ただし、Antに指示する必要があります

上記の私のAntの例はもちろん完全ではありません。クリーン、コンパイル、テストなどに使用されるターゲットを定義する必要があります。これらは、マルチモジュールプロジェクトのすべてのモジュールによってインポートされる共通のビルドファイルで定義されます。これは、Mavenでは宣言型であるのに対し、Antではこれらすべてを明示的に記述する必要があるという点に私を導きます。

確かに、これらのAntターゲットを明示的に記述する必要がなければ、時間を節約できます。しかし、どのくらいの時間ですか?現在使用している一般的なビルドファイルは、5年前に作成したもので、それ以降わずかな改良が加えられています。 Mavenで2年間の実験を行った後、古いAntビルドファイルをクローゼットから取り出し、ほこりをふき取り、元に戻しました。私にとって、Antに何をすべきかを明示的に伝えなければならないコストは、5年間で1週間未満になりました。

複雑さ

私が言及したい次の大きな違いは、複雑さとそれが持つ実世界の効果です。 Mavenは、ビルドプロセスの作成と管理を担当する開発者の作業負荷を軽減することを目的に構築されました。これを行うには、複雑でなければなりません。残念ながら、その複雑さは意図した目標を否定する傾向があります。

Antと比較すると、Mavenプロジェクトのビルド担当者はより多くの時間を費やします。

  • ドキュメントを読む:Mavenにはさらに多くのドキュメントがあります。学ぶ必要があるものがはるかに多いからです。
  • チームメンバーの教育:自分で答えを見つけようとするよりも、知っている人に尋ねる方が簡単だと感じています。
  • ビルドのトラブルシューティング:MavenはAnt、特に非コアプラグインよりも信頼性が低くなります。また、Mavenビルドは再現できません。プラグインのSNAPSHOTバージョンに依存している場合(非常に可能性が高い)、何も変更しなくてもビルドが中断する可能性があります。
  • Mavenプラグインの作成:プラグインは通常、特定のタスクを念頭に置いて作成されます。 Webstartバンドルを作成します。これにより、他のタスクでそれらを再利用したり、目標を達成するためにそれらを組み合わせたりすることがより困難になります。そのため、既存のプラグインセットのギャップを回避するには、独自のプラグインを作成する必要があります。

対照的に:

  • Antドキュメントは簡潔で包括的であり、すべて1か所にまとめられています。
  • Antは単純です。 Antを学習しようとする新しい開発者は、知っておく必要がある残りの部分を理解できるようにするために、いくつかの簡単な概念(ターゲット、タスク、依存関係、プロパティ)を理解するだけで済みます。
  • Antは信頼できます。 Antは既に機能しているため、過去数年にわたってあまりリリースされていません。
  • Antビルドは通常、オンラインリポジトリ、実験的なサードパーティプラグインなどの外部依存関係なしで作成されるため、繰り返し可能です。
  • Antは包括的です。ツールボックスであるため、ツールを組み合わせて、ほぼすべてのタスクを実行できます。独自のカスタムタスクを記述する必要がある場合は、非常に簡単です。

親しみやすさ

もう1つの違いは、親しみやすさです。新しい開発者は、常に速度を上げるのに時間が必要です。既存の製品に精通していることがその点で役立ち、MavenサポーターはこれがMavenの利点であると正しく主張しています。もちろん、Antの柔軟性により、好みの規則を作成できます。したがって、私が使用する規則は、ソースファイルをディレクトリ名src/main/Javaに置くことです。コンパイルしたクラスは、target/classesという名前のディレクトリに配置されます。おなじみの音はしません。

Mavenで使用されるディレクトリ構造が好きです。理にかなっていると思います。また、ビルドのライフサイクル。したがって、Antビルドでも同じ規則を使用します。理にかなっているからというだけでなく、以前にMavenを使用したことがある人なら誰でも知っているからです。

112

Antは主にビルド​​ツールです。

Mavenは、プロジェクトおよび依存関係管理ツールです(もちろん、プロジェクトもビルドします)。

Mavenを避けたい場合は、Ant + Ivy は非常に良い組み合わせです。

20
cherouvim

MavenまたはAnt? は、これと非常によく似た質問であり、質問に答えるのに役立ちます。

Mavenとは? 公式サイト.

edit:新規/グリーンフィールドプロジェクトの場合、Mavenを使用することをお勧めします。ビルドおよび展開スクリプトのセットアップ。 antを使用すると、ビルドスクリプトは時間の経過とともに複雑さを増していく傾向があります。既存のプロジェクトの場合、Mavenシステムに構成/レイアウトを簡単に追加することは困難です。

17
matt b

さらにいくつかの違いをリストするために:

  • Antには正式な規則はありません。 Antのソースの場所、出力先などを正確に指定する必要があります。
  • Antは手続き型です。 Antに何をすべきかを正確に伝える必要があります。コンパイル、コピー、圧縮などを指示します。
  • Antにはライフサイクルがありません。
  • Mavenは規則を使用します。これらの規則に従う限り、ソースコードが自動的にどこにあるかを認識します。 Mavenの場所を伝える必要はありません。
  • Mavenは宣言型です。必要なのは、pom.xmlファイルを作成し、ソースをデフォルトディレクトリに配置することだけです。残りはMavenが処理します。
  • Mavenにはライフサイクルがあります。 mvn installを呼び出すだけで、一連のシーケンスステップが実行されます。
  • Mavenには、一般的なプロジェクトタスクに関するインテリジェンスがあります。テストを実行するには、ファイルがデフォルトの場所にある限り、単純にmvn testを実行します。 Antでは、最初にJUnit JARファイルが必要です。次に、JUnit JARを含むクラスパスを作成し、テストソースコードを探す場所をAntに伝え、テストソースをコンパイルする目標を記述し、最後に単体テストを実行します。 JUnitで。

更新:

これは、 Maven:The Definitive Guide に由来します。申し訳ありませんが、引用するのを完全に忘れていました。

16
Ascalonian

Mavenは、依存関係管理ツール(中央リポジトリまたは設定したリポジトリからjarを取得するために使用できます)と宣言型ビルドツールの両方として機能します。 「宣言」ビルドツールとantやmakeなどの従来のツールとの違いは、実行方法ではなく、実行する必要があるものを設定することです。たとえば、mavenスクリプトで、プロジェクトをWARファイルとしてパッケージ化する必要があると言うことができ、mavenはそれを処理する方法を知っています。

Mavenは、その「宣言性」を実現するためにプロジェクトディレクトリをどのようにレイアウトするかについての規則に依存しています。たとえば、メインコードを配置する場所、web.xml、ユニットテストなどを配置する規則がありますが、必要に応じて変更することもできます。

また、Maven内からantコマンドを実行するためのプラグインがあることに留意する必要があります。

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

また、mavenのアーキタイプにより、プロジェクトをすぐに開始できます。たとえば、Wicketアーキタイプがあります。これは、実行可能なhello worldタイプのプロジェクト全体を取得するために実行するmavenコマンドを提供します。

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

14
James Kingsbery

Antを見たことのない人を連れて行くことができます-そのbuild.xmlsはかなりよく書かれています-そして彼らは何が起こっているのか理解できます。私はその同じ人を連れてMaven POMを見せることができます。

巨大なエンジニアリング組織では、Antファイルが大きくなり、管理不能になることについて人々が書きます。これらのタイプを記述しましたand Clean Antスクリプト。今後何をする必要があるかを事前に理解し、3年以上にわたって変化に対応し、拡張できるテンプレートのセットを設計しています。

単純なプロジェクトがない限り、物事を成し遂げるためのMavenの規則とMavenの方法を学ぶのはかなりの作業です。

結局のところ、AntまたはMavenを使用したプロジェクトの開始を要因と見なすことはできません。それは実際には総所有コストです。組織が数年にわたってビルドシステムを維持および拡張するために必要なことは、考慮しなければならない主な要因の1つです。

ビルドシステムの最も重要な側面は、依存関係の管理とビルドレシピの表現における柔軟性です。うまくやれば、やや直感的でなければなりません。

10
kramer

私はそれがあなたのプロジェクトのサイズに依存すると言うだろう...個人的に、私は簡単なコンパイル、パッケージング、展開を必要とする単純なプロジェクトにMavenを使用します。もっと複雑なこと(多くの依存関係、マッピングファイルの作成など)を行う必要があるとすぐに、Antに切り替えます...

6
karlipoppins

Mavenには、一般的に使用されるオープンソースプロジェクトの大規模なリポジトリもあります。ビルド中に、Mavenはこれらの依存関係(および依存関係の依存関係)をダウンロードして、プロジェクトのビルドのこの部分をもう少し管理しやすくします。

4
markt