実践的Apache Ant™

本番開発システムにおけるApache Antの活用

Steve Loughran
最終更新日 2005-03-16

はじめに

Apache Ant は、チーム開発プロセスにおいて非常に貴重なツールとなる一方、開発という名の終わりのない危機において、新たな問題を引き起こす可能性もあります。このドキュメントでは、Antを最大限に活用するための戦略と戦術を紹介します。ところどころ軽薄な表現があり、Ant XMLの実際の例はほとんどありません。例の欠如は意図的なもので、ドキュメントのメンテナンスコストを抑えるためです。ここで取り上げる概念のほとんどは、XML表現による詳細を必要としません。構文ではなく、プロセスに関心があるからです。最後に、ここで述べるコメントは、あくまでも皆様のニーズに合わせてカスタマイズする必要がある提案であり、すべきこととすべきでないことについての厳格なルールではないことにご注意ください。

まず、このドキュメントが対象とするプロジェクトについて、いくつかの前提を挙げます。

つまり、物事を正しく行うための時間がない、チームの他のメンバーの仕事のやり方を厳密に管理できない、開発プロセスはしばしば混沌を最小限に抑えることに重点が置かれているということです。このようなプロジェクトにおけるAntの役割は、ビルド、テスト、デプロイのプロセスを円滑に進め、他の問題に集中できるようにすることです。

コアプラクティス

Antに何をさせたいかを明確にする

Antは万能薬ではありません。開発ツールという武器庫にある、錆びついた弾丸の一つに過ぎません。その主な目的は、Javaプロジェクトの構築とデプロイを加速させることです。Antを拡張してJavaで可能なことは何でもできます。例えば、Webサイトのデプロイメントを支援するために、JPEGファイルを縮小して再圧縮する画像処理タスクを書くことは容易に想像できます。しかし、それはAnt本来の目的の範囲を超えているため、慎重に検討する必要があります。

AntはIDEの優れた補助ツールでもあり、デプロイメントのあらゆる雑務や、クリーンで自動化されたビルドを行うことができます。しかし、優れた最新のIDEはそれ自体が生産性向上ツールであり、使い続けるべきです。Antを使うことで、チームはIDEの選択に多少の自由度を持つことができます。「開発では好きなものを使って構いませんが、デプロイメントビルドにはAntを使ってください」 多くの最新のオープンソースおよび商用IDE(jEdit、Forte、Eclipse、IDEAなど)がAntをサポートしているため、開発者は優れたIDEを使用し、Antはツールに統合された厳格でポータブルなビルドプロセスを提供することができます。

標準ターゲットを定義する

複数のサブプロジェクトがある場合は、標準のターゲットセットを定義します。インターフェースと実装のjarファイルが分割されているプロジェクトでは、**impl** と **intf** ターゲット、そしてデバッグバージョン用の **debug-impl** と **debug-intf** ターゲットを検討することができます。もちろん、どこにでもある **clean** ターゲットも必要です。

標準のターゲット名を使用することで、ant タスクを使用して、下位のクラスに作業を委譲する包括的なAntビルドファイルを簡単に作成できます。例えば、cleanターゲットは、intfimplのサブディレクトリに、親ディレクトリから渡すことができます。

<target name="clean"  depends="clean-intf, clean-impl">
</target>

<target name="clean-intf" >
    <ant dir="intf" target="clean" />
</target>

<target name="clean-impl">
    <ant dir="impl" target="clean" />
</target>  
ターゲットにdescriptionタグを付けると、ant -projecthelpを実行すると、説明付きのすべてのタスクが「メインターゲット」として、説明のないすべてのタスクがサブターゲットとしてリストされます。そのため、プロジェクトが大きく複雑になる前から、すべてのエントリポイントを記述しておくことは非常に便利です。

新しいタスクでAntを拡張する

Antが希望どおりに動作しない場合は、exec タスクと java タスク、または インラインスクリプト を使用して拡張できます。多くのbuild.xmlファイルを持つプロジェクトでは、機能を実装するための中心的な場所を1つに絞ることで、メンテナンスのオーバーヘッドを削減できることがすぐにわかります。Javaコードによるタスク拡張の実装は、最初は余計な労力に思えるかもしれませんが、次のような利点があります。ある意味で、Antが成功した要因は、機能(「タスク」)と使用方法の宣言(「ビルドファイル」)を切り離したことだと言えます。MakeやIDEで複雑なことをしようとすると、誰もが恐れるような複雑なmakefileや、非常に壊れやすいIDE設定が必要になります。しかし、AntタスクはすべてのAntユーザーが再利用および共有できます。現在Antのコアおよびオプションタスクとして提供されている多くのタスク(皆様が現在、あるいは将来依存することになるタスク)は、目の前の問題を解決しようとした人々によって書かれたものです。

自動テストを取り入れる

(あるいは「早期に非難し、頻繁に非難する」)

Antでは、JUnit タスクを呼び出して、チームが作成したコードのユニットテストを行うことができます。自動テストは最初は余計な作業に思えるかもしれませんが、JUnitはユニットテストの作成を非常に簡単にするため、実施しない理由はほとんどありません。JUnitの使い方を学び、テストケースを作成し、Antの「test」ターゲットに統合して、日次または時間ごとのチームビルドで自動的にテストが適用されるように時間を投資しましょう。Java Development with Ant の無料ダウンロード可能な章では、Ant内からJUnitを使用する方法を紹介しています。

Antタスク、シェルスクリプトまたはバッチファイル、あるいは継続的インテグレーションツールを介して、SCMシステムからコードを取得する方法を追加すれば、統合テストコードは、タスク専用の任意のマシンで実行できる純粋なAntタスクにすることができます。これは、ビルドとユニットテストが通常の開発マシンとは異なるターゲットで動作することを確認するのに最適です。例えば、開発者が選択の余地があれば喜んで使用することはないWin95/Java1.1の組み合わせでも使用できます。

システムテストはユニットテストよりも自動化が難しいですが、システムの大部分をストレスをかけるJavaコードを書くことができれば(JUnitタスクとして実行できなくても)、java タスクを使用してそれらを呼び出すことができます。重大なクラッシュがビルド全体を壊さないように、これらのテストには新しいJVMを指定するのが最善です。Webページ用の HttpUnit や、J2EEおよびサーブレットテスト用の Cactus などのJunit拡張機能は、テストフレームワークの拡張に役立ちます。適切にテストするには、これらをプロジェクトで動作させるために、そして優れたユニットテスト、システムテスト、回帰テストを導き出すために、多くの労力を費やす必要がありますが、正常に動作するソフトウェアを出荷することで、顧客は満足するでしょう。

Antのアドオンを活用する

AntのディストリビューションはAntの世界の限界ではなく、始まりに過ぎません。最新のリストについては、 外部ツールとタスクのページ をご覧ください。その中のいくつかをご紹介します。

クロスプラットフォームAnt

Antは、これまでで最高のクロスプラットフォームJava開発およびテスト基盤です。しかし、注意を怠ると、1つのプラットフォーム、あるいは1つのワークステーションだけで動作するビルドファイルを作成してしまう可能性があります。

クロスプラットフォームAntの一般的な障壁は、移植性のないコマンドラインツール(execタスク)の使用、パスの問題、およびハードコーディングによるものの配置です。

コマンドラインアプリケーション:Exec / Apply

外部呼び出しの問題点は、すべての関数がクロスプラットフォームで見つかるわけではなく、見つかったとしても名前が異なる場合が多いことです。DOSの子孫は、多くの場合、ファイルの末尾に.exeまたは.batが付いていることを期待します。コマンドの命名に拡張子を明示的に含めると問題になります(しないでください!)。Unix版とDOS版の実行ファイルをプロジェクトの同じbinディレクトリに名前の衝突なしに保存できる場合は、問題ありません。

どちらのコマンドライン呼び出しタスクでも、コードを実行するプラットフォームを指定できるため、ターゲットとするプラットフォームごとに異なるタスクを記述できます。あるいは、プラットフォームの違いは、Antが呼び出す外部コード内で処理できます。これは、新しいタスクのコンパイル済みJava、または外部スクリプトファイルにすることができます。

クロスプラットフォームパス

Unixパスは、ディレクトリ間の区切りにスラッシュ(/)、エントリの区切りにコロン(:)を使用します。したがって、*"/bin/java/lib/xerces.jar:/bin/java/lib/ant.jar"* はUnixのパスです。Windowsでは、パスは区切り文字にセミコロン(;)を使用する必要があります。コロンはディスクドライブの指定に使用され、区切り文字にはバックスラッシュ(\)が使用されます。* "c:\bin\java\lib\xerces.jar;c:\bin\java\lib\ant.jar"* のようになります。

このプラットフォーム間の違い(実際には、Javaクラスパスパラダイム全体)は、何時間も悩ませる可能性があります。

Antはパスの問題を軽減しますが、完全に解消するわけではありません。あなた自身も努力する必要があります。パス名を処理するためのルールは、「DOSライクなパス名が処理される」、「Unixライクなパスが処理される」です。ディスクドライブ -*「C:」*- はDOSベースのボックスで処理されますが、これらをbuild.xmlファイルに配置すると、移植性が完全に失われます。相対ファイルパスの方がはるかに移植性が高くなります。セミコロンはパス区切り文字として機能します。これは、Ant呼び出しラッパーにコマンドラインで定義されたプロパティとしてjarのリストが含まれている場合に便利です。ビルドファイルでは、個々のファイル(`location=`属性を使用)をリストするか、*.jarのファイルセットをクラスパス定義に含めることで、クラスパスを構築する方が良い場合があります。

また、PathConvertタスクを使用して、完全に解決されたパスをプロパティに格納することもできます。なぜそうするのでしょうか?それは、そのパスを他の方法で使用できるからです。たとえば、呼び出しているアプリケーションにパラメータとして渡したり、`replace`タスクを使用してローカライズされたシェルスクリプトまたはバッチファイルにパッチを適用したりできます。

DOS由来のファイルシステムは大文字と小文字を区別しないことに注意してください(WinNT POSIXサブシステムがNTFSに対して実行されるというあいまいな例外を除く)。また、Windowsは4文字以上のすべてのファイル拡張子を3文字の拡張子として扱います(DELETE *.javをJavaディレクトリで試して、この悲惨な例を確認してください)。

Antの大文字と小文字の区別に関するポリシーは、基盤となるファイルシステムの実装に従います。ファイル拡張子の処理に関しては、*.javでは.javaファイルは見つかりません。Javaコンパイラは大文字と小文字を区別します。「ExampleThree」というクラスを「examplethree.java」で実装することはできません。

一部のタスクは1つのプラットフォームでのみ動作します。 Chmod は典型的な例です。これらのタスクは、通常、サポートされていないプラットフォームでは警告メッセージのみを生成し、ターゲットの残りのタスクは引き続き呼び出されます。他のタスクは、プラットフォームまたはJavaバージョンによって機能が低下します。特に、ファイルのタイムスタンプを調整するタスクは、Java 1.1では正しく実行できません。 GetTouchUnjar/Unwar/Unzip など、そのようなタスクはJava 1.1では機能が低下し、通常は現在のタイムスタンプが代わりに使用されます。

最後に、Perlは、バッチファイルではなく、クロスプラットフォームでJava呼び出しをラップするのに適した場所です。ほとんどのUnixディストリビューションに含まれており、ActiveStateからWin32プラットフォーム用に簡単にダウンロードできます。.pl拡張子を持つPerlファイルは、1行目のコメントに通常のUnixパスを記述し、実行可能としてマークすることで、Windows、OS/2、およびUnixで実行できるため、問題なくAntから呼び出すことができます。Perlコードは、独自のプラットフォームの問題を解決できます。Perlコードを再配布する際には、ファイルの行末を適切なプラットフォームに設定することを忘れないでください。 fixCRLF がその処理を実行できます。

チーム開発プロセス

各チームメンバーがIDE/エディター、またはOSを選択できる場合でも、各ボックスに機能のベースラインを設定する必要があります。特に、JDKとjarは完全に同期している必要があります。理想的には、すべての開発者/ターゲットシステムで使用可能な最新の安定したJava/JDKバージョンを選択し、しばらくの間、それに固執してください。すべてのツール(特に、毎晩新しいビルドが利用可能なオープンソースツール)の連絡窓口となる担当者を割り当てることを検討してください。必要な場合を除き、これらのツールは、実際には毎月、または正式リリースが行われたときにのみ更新する必要があります。

もう1つの良い戦術は、統合ディレクトリツリーを使用し、そのツリー内に追加のツールを追加することです。すべての参照は、ツリーを基準にして相対的に行うことができます。チームメンバーがプロジェクト内のディレクトリをパスに追加することが想定されている場合は、Ant `exec`タスクによって呼び出されるツールを含め、コマンドラインツールをそこに含めることができます。すべてをソースコード管理下に置くと、CVSまたは同等のものからビルド/実行環境を取得するための一元的な場所が得られます。

Antを使用したデプロイ

AntとMakeなどの古いツールとの大きな違いの1つは、JavaをリモートサイトにデプロイするプロセスがAntではかなり進化していることです。これは、今日では誰もがそれをしなければならないため、多くの人がタスクを容易にするために努力してきたからです。

Antは、デプロイ用にファイルをJarTar、またはZipできます。一方、Warタスクは、サーブレットのデプロイを改善するためにjarタスクを拡張します。Jlinkは、複数のサブjarをマージできるjar生成ファイルです。これは、個別のjarがサブプロジェクトによって生成されるが、最終出力がマージされたjarであるビルドプロセスに最適です。Cabは、Win32ボックスで使用して、IEデプロイをターゲットにする必要がある場合に役立つcabファイルをビルドできます。

ftpタスクを使用すると、サーバーにコンテンツを移動できます。ビルドファイルにftpパスワードを配置しないように注意してください。アクセス制御が厳格なプロパティファイルの方がわずかに優れています。FixCRLFタスクは、ファイルの行末を調整する必要がある場合に、しばしば役立つ中間手順です。WebDavタスクは長い間議論されてきましたが、Webサーバーへのより安全なアップロードを提供するもので、まだTODOリストにあります。jakarta-slideライブラリにそのようなタスクがあるという噂があります。MacOS X、Linux、Windows XPはすべてWebDAVファイルシステムをサポートしているため、ファイアウォールを介してcopyを使用してデプロイできる場合があります。

EJBデプロイはejbタスクによって支援され、serverdeployスイートは複数のサーバーにデプロイできます。Antの人気が高まったことで、ベンダーは独自のデプロイタスクを作成し、サーバーと一緒に再配布するようになりました。たとえば、Tomcat 4.1インストールには、Webアプリケーションをデプロイ、アンデプロイ、およびリロードするタスクが含まれています。

最後に、CopyCopydirを使用してファイルを宛先にコピーするか、Mailまたは添付ファイルを認識するMimeMailを使用して個人またはプロセスに送信するというフォールバックがあります。あるプロジェクトでは、私たちのチームはAntを使用して、ビルドとその後の長いCopyタスクのセットを通じてCDイメージをビルドしました。これは驚くほどうまく機能し、WinNTリモートデスクトップ接続を介して実行していたWebブラウザーからプルダウンしたmyrealbox.comの無料メールサービスにメールで送信したときよりもはるかに簡単でした。SSHを介してトンネリングされていました。

ディレクトリ構造

ディレクトリツリーの構成方法は、プロジェクトによって大きく異なります。出発点として使用できるディレクトリレイアウトパターンをいくつか紹介します。すべてのJakartaプロジェクトは、ほぼ同じスタイルに従っているため、あるプロジェクトから別のプロジェクトに簡単に移動でき、必要に応じて簡単にクリーンアップできます。

単純なプロジェクト

プロジェクトには、以下のサブディレクトリが含まれています。
bin 共通のバイナリ、スクリプト - これをパスに配置します。
build これはビルド用のツリーです。Antはこれを作成し、「clean」プロジェクトで空にすることができます。
dist 配布出力はここに配置されます。ディレクトリはAntで作成され、cleanはそれを空にします。
doc 手作業で作成されたドキュメント
lib インポートされたJavaライブラリはこのディレクトリに配置されます。
src ソースコードはこのツリーの下に、*パッケージ名と一致する階層で*配置されます。<javac>の依存関係ルールではこれが必要です。
bin、lib、doc、およびsrcディレクトリは、ソースコード管理下に置く必要があります。わずかなバリエーションとして、配布jarに含めるコンテンツの追加ツリー(infファイル、画像など)があります。これらはソースの下にも配置でき、metadataディレクトリにはweb.xmlなどのマニフェストがあり、webフォルダーにはWebコンテンツ(JSP、html、画像など)があります。このフォルダー(またはサブ階層)にコンテンツをまとめておくことで、デプロイ前にリンクを簡単にテストできます。warファイルなどのデプロイイメージの実際の作成は、適切なAntタスクに任せることができます。デプロイ階層に基づいてソースツリーを完全にモデル化する必要はありません。

Javadoc出力は、doc/フォルダーの下のbuild/、またはdoc/javadoc.

に送ることができます。インターフェースと実装の分割

インターフェースが実装コードから分割されている場合、インターフェースディレクトリに別のビルドパスを用意するだけで、またはjarの構築時にインターフェース用に1つのjar、実装用に1つのjarを用意することで、わずかな変更で対応できます。

疎結合サブプロジェクト

疎結合アプローチでは、複数のプロジェクトがツリーの独自のコピーを持ち、独自のソースコードアクセス権を持つことができます。考慮すべき違いの1つは、すべてのプロジェクトでbinディレクトリとlibディレクトリのインスタンスを1つだけにすることです。これは、xerces.jarのコピーを同期させるのに役立つ場合もありますが、ユニットテストが完了する前に基盤となるjarファイルが更新される場合があるため、悪い場合もあります。

サブプロジェクト全体で単一のビルドを行うには、親build.xmlファイルを使用して、サブプロジェクトを呼び出します。

このスタイルは、異なるチームが異なるコードアクセス権/コミットメント権を持っている場合に適しています。リスクは、サブプロジェクトに余分な自由度を与えることで、互換性のないソース、ライブラリ、ビルドプロセスが発生し、ワークロードと統合の苦労が増える可能性があることです。

かなり疎結合のプロジェクトのコレクションを制御する唯一の方法は、すべてが互換性があることを確認する完全に自動化されたビルドおよびテストプロセスを用意することです。Sam Rubyは、すべてのアパッチJavaライブラリに対してこれを実行し、何かが壊れたときに全員にメールを送信します。独自のプロジェクトでは、Cruise Controlを使用して、自動化された継続的なバックグラウンドビルドプロセスを利用できる場合があります。

統合サブプロジェクト

密結合プロジェクトは、すべてのソースが同じツリーにあります。異なるプロジェクトが異なるサブディレクトリを所有します。ビルドファイルは、これらのサブディレクトリ(たとえば、src/com/iseran/coresrc/com/iseran/extras)に移動するか、最上位に保持し、core.xmlextras.xml.

という名前の独立したビルドファイルを配置できます。このプロジェクトスタイルは、全員が互いに信頼し合っており、サブプロジェクトがあまりにも大きく複雑でない場合に適しています。リスクは、プロジェクトの進行に伴い、より疎結合の設計への分割が必要になることです。しかし、これが実現するまでに、スケジュールのプレッシャーと複雑に絡み合ったビルドファイルにより、分割を実行することがほぼ不可能になります。そうなった場合は、プロジェクトディレクトリ構造をリファクタリングする時間があるまで、そのままにしておきます。

Ant更新ポリシー

Antを使い始めたら、チームが各自のコピーをいつ、どのように更新するかについてのポリシーを定めるべきです。簡単なポリシーとしては、「重要度の低いタスク(睡眠や日光を浴びることなど)すべてを後回しにした、大きな節目の後の公式リリースごと」があります。これは、開発中のAntの変更や時折発生する不安定性から隔離してくれます。主な欠点は、Antに常に追加されている新しいタスクや機能を利用できないことです。

多くの場合、更新にはbuild.xmlファイルの変更が必要になります。ほとんどの変更は後方互換性を維持するように意 نظرされていますが、互換性のない変更が必要になる場合があります。そのため、大きな節目の後の落ち着いた時期に更新を行うことが重要です。ant.jarと関連ファイルをCVSツリーに含めることで、古いバージョンのソフトウェアを確実にビルドできるようにすることも、この理由の一つです。

最も積極的な戦略は、Antソースの週次または日次のスナップショットを取得し、ビルドして使用することです。これは、新しいタスクと属性が安定するまで時間がかかることがあるため、build.xmlファイルをより定期的に調整する必要があります。このアプローチを採用するには、本当に新しい機能が必要であるか、余計な作業を楽しんでいるか、同僚を困らせることに喜びを感じている必要があります。

新しいタスクでAntを拡張し始めると、定期的なビルドを取得することが急に魅力的になります。最新のAntビルドは、基礎クラスの定期的な拡張機能を利用できるため、拡張機能を作成するための常に最適なプラットフォームです。また、既に完了している作業に時間を浪費することを防ぎます。EJBエンジン、SOAPサーバーとの通信、テキストファイルの大文字への変換など、複雑な処理を行うための新しく提出されたタスクは、まさに必要なものである可能性があります。そのため、それを取得し、拡張し、拡張機能を世界中に提供してください。これは、Ant 0.8で「テキストケースコンバーター」タスクの作業を単独で開始し、6か月後にその存在を発表し、賞賛の代わりに既存の実装への有用なポインターを得るよりも、確かに優れています。このプロセスに参加することの最終的な利点は、Ant CVSツリーにタスクを追加しやすくなり、Antがプロジェクトを機能させるために行ったすべての変更を引き受ける日付が早まることです。それが起こると、公式のAntリリースに戻り、他のすべての危機に対処できます。

また、他の開発者が作業、問題、経験を投稿する場である開発メーリングリストに参加する必要があります。量は非常に多く、1日に40以上のメッセージが送信される可能性があるため、あまり使用していないメールアドレスにルーティングすることを検討してください。そして、チームの全員を購読させないでください。気が散りすぎる可能性があります。

Antを使用したインストール。

Antは環境変数を読み取り、ファイルのコピー、解凍、削除、JavaおよびOS呼び出しを行うことができるため、簡単なインストールタスクに使用できます。たとえば、Tomcatのインストーラーは環境変数TOMCAT_HOMEを抽出し、Tomcatの実行を停止し、warファイルをTOMCAT_HOME/webappsにコピーできます。Tomcatを再び起動することもできますが、Tomcatが終了するまでビルドは完了しません。これはおそらく望ましいことではありません。

Antを使用する利点は、まず、同じインストールターゲットをローカルビルドファイルから(antによるinstall.xmlファイルの呼び出しを介して)使用できること、次に、基本的なインストールターゲットの作成が非常に簡単であることです。このアプローチの欠点は、宛先に最新のAntが正しくプリインストールされている必要があること、そしてAntがエラーをうまく処理できないことです。優れたインストーラーは、ファイルが使用中であることからjarバージョンが異なることまで、問題が発生した場合の処理に関するすべてです。これは、Antがシュリンクラップソフトウェアには適していないことを意味しますが、ローカルサーバーへのデプロイとインストールには有効です。

私が関わったある主要なビルドプロジェクトでは、Bluestoneアプリケーションサーバー用のAntインストールビルドファイルがあり、単一のマシン上のアプリサーバーの4つのインスタンスすべてをシャットダウンし、warファイルの新しいバージョン(日付スタンプとビルドスタンプ付き)をアーカイブディレクトリにコピーし、現在デプロイされているwarバージョンをクリーンアップしてから、新しいバージョンをインストールしました。BluestoneはオンデマンドでJVMを再起動したため、このスクリプトはWebサービスのデプロイに必要なすべてでした。ファイアウォールの背後にあるシステムでは、ftpタスクを使用してwarファイルとビルドファイルをコピーし、telnetタスクを使用してビルドファイルをリモートで呼び出すことで、デプロイプロセスを強化しました。その結果、IDE(Jedit)またはコマンドライン内からローカルサーバーへの再コンパイルと再デプロイを自動化することができました。これは非常に貴重でした。IDEツールバーのボタンを押して、Webアプリをビルド、単体テスト、デプロイ、そして機能テストすることを想像してみてください。

後で追加したもう1つの工夫は、インストールチェックリストを実行するためのJUnitテストケースでした。ネットワークドライブへのアクセス許可、サーバー間の概算クロック同期、DNS機能、実行可能ファイルの生成機能、およびその他すべてのトラブルスポットを確認するテストにより、インストールスクリプトはインストール時にシステムのヘルステストを自動的に実行し、問題を報告できました。[同じテストはJMX MBeanからも呼び出すことができますが、それは別の話です]。

そのため、Antは、制御するサーバーの特別な場合を除いて、実際のインストーラーツールの代わりにはなりませんが、そのコンテキストでは、リモートインストールをビルドと統合できます。

ヒントとコツ

get
getタスクは任意のURLを取得できるため、リモートサーバーの再起動から開発者の携帯電話へのSMS /ページャーメッセージの送信まで、ビルドプロセス中にリモートサーバー側のコードをトリガーするために使用されます。
i18n
国際化は常に問題です。Antは、ASCII以外のすべての文字をUnicodeにエスケープできるnative2asciiタスクで役立ちます。これを使用して、独自の非ASCII言語で文字列(およびコメント)を含むJavaファイルを記述し、javacにフィードする前にnative2asciiを使用してASCIIに変換できます。i18nとl12nの残りはあなた次第です...
プロパティファイルの使用
外部プロパティファイルを使用して、ユーザーごとの設定をビルドファイル(特にパスワード)から除外します。プロパティファイルを使用して、ソースプロパティからプロパティファイル名を動的に生成するだけで、単一のプロパティの値に基づいて複数のプロパティを動的に設定することもできます。また、複数のビルドファイルにわたる定数のソースとしても使用できます。
Jikesを使用した高速コンパイル
Jikesコンパイラは通常、javacよりもはるかに高速で、依存関係チェックを行い、より優れたエラーメッセージ(通常)を生成します。入手してください。次に、build.compilerを「jikes」に設定して、ビルドファイルで使用します。ビルドファイルで明示的にこれを行うと、チーム全体(およびサブプロジェクト)もjikesを使用する必要があるため、少し怪しげです。これは、小規模なクローズドソースプロジェクトでのみ制御できます。ただし、ANT_OPTS = -Dbuild.compiler=jikesを環境に設定すると、システム上のすべてのビルドでJikesが自動的に使用されますが、他のユーザーは独自のコンパイラを選択するか、antに現在のJavaバージョンに適したコンパイラを選択させることができます。
複数プロジェクトを簡素化するための#includeターゲットbuild.xml
XMLパーサー自体を使用して、XMLファイルをビルドファイルにインポートできます。これにより、マルチプロジェクト開発プログラムは、カットアンドペーストの再利用ではなく、参照を通じてコードを共有できます。また、時間の経過とともに再利用できる標準タスクのファイルを構築することもできます。インポートメカニズムはAntが認識するレベルよりも低いレベルにあるため、「レガシー」言語CおよびC ++の#includeメカニズムと同等に扱います。

すべてのパーサー用の醜いメカニズムとクリーンなメカニズムの2つの包含メカニズムがあります。醜い方法は、Ant1.5以前で使用可能だった唯一の方法です。

    <!DOCTYPE project [
      <!ENTITY propertiesAndPaths SYSTEM "propertiesAndPaths.xml">
      <!ENTITY taskdefs SYSTEM "taskdefs.xml">
    ]>  
    
        &propertiesAndPaths;
        &taskdefs;
Ant1.6のよりクリーンな方法は、<import>タスクであり、ビルドファイル全体を他のプロジェクトにインポートします。エンティティ包含の例は、2つのimportステートメントで*ほぼ*置き換えることができます。
 <import file="propertiesAndPaths.xml">
 <import file="taskdefs.xml">
トップレベルの宣言(プロパティとtaskdefs)は、importステートメントが記述されているXMLファイルに正確に挿入されるのではなく、ファイルの最後に追加されるため、ほぼと言います。これは、インポートプロセスがメインビルドファイルの解析後、実行中に実行されるのに対し、XMLエンティティ拡張は解析プロセス中に処理されるためです。

<import>タスクは、ターゲットをオーバーライドしたり、antプロパティを使用してインポートするファイルの場所を指定したりするなど、強力な処理を実行します。これらの機能の詳細については、ドキュメントを参照してください。

XML包含を多用する前に、antタスクを使用すると、他のビルドファイルの任意のターゲットを呼び出すことができることに注意してください。すべてのプロパティ設定はそのターゲットに伝播します。そのため、実際には、ユーティリティターゲットのスイート「-deploy-to-stack-a", "email-to-team", "cleanup-installation」を用意できます。これは、メインビルドファイルのいずれかから、おそらく微妙に変更されたパラメーターで呼び出すことができます。実際、いくつかのプロジェクトの後、基本的なJava開発プロジェクトのコアターゲット(コンパイル、デバッグ、デプロイ)を含む再利用可能なコアビルドファイルを作成できる場合があります。プロジェクト固有のビルドファイルは独自の設定で呼び出します。もしあなたがこれを達成することができれば、あなたは間違いなくソフトウェア成熟度のはしごを登っています。少し努力すれば、SEI CMMレベル0の組織「個々の英雄的行為では不十分」からSEI CMMレベル1、「プロジェクトは個々の英雄的行為が原因でのみ成功する」に進むことができます。

注意:ant*inheritall*属性がfalseに設定されていない限り、すべてのプロパティをコピーします。その属性が存在する前は、呼び出し元が呼び出し元のプロパティを意図せずに上書きしないように、すべてのビルドファイルのすべてのプロパティ定義に注意深く名前を付ける必要がありました。今では、inheritall="false"を<ant>タスクのすべての使用に設定することを忘れないでください。

XSLを介して複雑なAntビルドを実装する
XSLTを使用して、ソースXMLファイルからbuild.xmlファイルを動的に生成できます。xsltタスクは変換を制御します。これは、複雑なビルドファイルを動的に作成するための現在推奨されている戦略です。ただし、その使用はまだ非常にまれです。つまり、あなたはテクノロジーの最先端にいることになります。
呼び出しスクリプトを変更する
DOS、Unix、またはPerlスクリプトを開始点として使用して独自の呼び出しスクリプトを作成することにより、個々のプロジェクトのAntの設定と動作を変更できます。たとえば、ANT_HOMEの代わりに別の変数をベースとして使用したり、クラスパスを異なる方法で拡張したり、インターフェイスディレクトリのすべてのproject.interfaces」という新しいコマンドラインプロパティを.jarファイルから動的に作成したりできます。

PROJECT_HOME

の下のCVS制御ライブラリツリーから実行されるカスタム呼び出しスクリプトを用意することで、 また、チーム全体で Ant のバージョンを制御できます。開発者は必要に応じて Ant の別のコピーを持つことができますが、CVS ツリーには常にプロジェクトのビルドに使用される jar セットが含まれています。

既存の Ant スクリプトを呼び出すラッパースクリプトを作成することもできます。これは、それらを拡張する簡単な方法です。ラッパースクリプトは、追加の定義を追加し、明示的なターゲットに名前を付け、再定義することができますANT_HOMEそして、一般的に開発を容易にします。Windows の「ant」は実際には「ant.bat」であるため、別のバッチファイルから「CALL ant」ステートメントを使用して呼び出す必要があります。そうしないと、ラッパーに戻りません。

Ant から呼び出すことができるように、すべてのコードを記述します
これは少し奇妙で理想主義的に思えるかもしれませんが、これは、将来のある時点でライブラリとして呼び出される可能性があるかのように、すべての Java コードを記述する必要があることを意味します。そのため、呼び出しを配置しないでくださいSystem.exit()コードの奥深くに - いくつかの関数から抜け出したい場合は、代わりに例外を発生させてmain()が処理するようにします。

さらに一歩進んで、Ant タスクインターフェースをコードに、セカンダリ、プライマリ、または唯一のインターフェースとして提供することを検討してください。Ant は、クラスパスの設定を処理するため、実際には Java アプリケーションの優れたブートローダーであり、プリアンブルとポストアンブルの作業にすべての組み込みタスクを再利用できます。XDoclet などの一部のプロジェクトは、Ant の下でのみ実行されます。それが適切な場所だからです。

replace タスクを使用して、プロジェクト内のテキストファイルをプログラムで変更します。
プロジェクトにソースファイル(BAT ファイル、ASPX ページ(!)、JVM オプションなどのプロジェクトのいくつかのプロパティ、またはエラーを転送する URL など、特定のインストール用にコンパイル時に静的にカスタマイズする必要があるもの)があるとします。 replace タスクを使用して、ファイルを修正し、テキストを置換し、そのビルドまたは宛先にカスタマイズされたバージョンを作成できます。もちろん、宛先ごとのカスタマイズはインストールまで遅らせる必要がありますが、リモートインストールに Ant を使用している場合は、突然実現可能になります。
メーリングリストを使用する
Ant に関連するメーリングリストは、ユーザーと開発者の 2 つあります(メーリングリスト)。Ant ユーザーは、Ant の使用に関する*すべて*の質問を送信する場所です。インストール、構文、コードサンプルなど - 質問をそこに投稿するか、アーカイブを検索して、クエリが以前に投稿されて回答されているかどうかを確認してください。Ant-developer は Ant の開発が行われる場所であるため、「プロジェクトをビルドするとコンパイルエラーが発生する」や「zip ファイルを作成する方法」などを投稿する場所*ではありませ*ん。一方、実際に Ant を拡張している場合は、新しいタスクを追加する方法、既存のタスクに変更を加える方法、そして Ant ソースツリーに組み込みたい場合は作業の結果を投稿する方法について質問するのに最適な場所です。

すべてをまとめる

この世界では、Ant ビルドプロセスはどのように見えるでしょうか?簡潔にするために単一のディレクトリ構造を想定すると、ビルドファイルにはいくつかのトップレベルのターゲットが含まれている必要がありますサブプロジェクト「web」、「bean-1」、「bean-2」には、独自のビルドファイルを与えることができます -web.xml, bean-1.xml, bean-2.xml- 同じエントリポイントを使用します。データベース、Web サイトの画像などに関連する追加のトップレベルタスクは、それらがプロセスの一部である場合は考慮する必要があります。

デバッグ/リリースの切り替えは、コンパイルタスクの前に呼び出される個別の初期化ターゲットで処理できます。これにより、適切なプロパティが定義されます。Antcall は、ビルドファイルに 2 つのプロパティ初期化パスを持つことができるため、ここで役立ちます。

内部ターゲットを使用してプロセスを構造化する必要があります

デバッグとリリースの切り替えは、次のようなプロパティで init-release を条件付きにすることで実行できます。release.buildが設定されている :-
<target name="init-release" if="release.build">
    <property name="build.debuglevel" value="lines,source"/>    
  </target>
その後、「コンパイル」などの依存ターゲットがこの条件付きターゲットに依存します。そこでは「デフォルト」のプロパティが設定され、次にプロパティが実際に使用されます。Ant プロパティは*不変*であるため、リリースターゲットが実行された場合、その設定はデフォルト値をオーバーライドします
<target name="compile" depends="init,init-release">
    <property name="build.debuglevel" value="lines,vars,source"/> 
    <echo>debug level=${build.debuglevel}</echo>
    <javac destdir="${build.classes.dir}"
       debug="true"
       debuglevel="${build.debuglevel}"
       includeAntRuntime="false"
       srcdir="src">
      <classpath refid="compile.classpath"/>
    </javac>
  </target>
その結果、リリースモードにはファイル名と行のデバッグ情報(バグレポートに役立つ)のみが含まれ、開発システムには変数も含まれるビルドができました.

init タスクでエコーできるプロジェクト名プロパティを定義すると便利です。これにより、マルチファイルビルドでどの Ant ファイルが壊れているかを把握できます。

内部 Ant タスクの内容は、独自のプロジェクトによって異なります。非常に重要な戦術の 1 つは、「参照を通じてパスの再定義を減らす」ことです。ID を付けて「refid」属性で参照することでパスを再利用できます。共有クラスパスはファイル内で 1 回だけ定義する必要があります。ファイルセットも同様に再利用できます。

ディレクトリ構造を設定し、Ant タスクを定義したら、コーディングを開始します。早期の優先事項は、自動テストプロセスを設定することです。これは、コードが機能することを確認するのに役立つだけでなく、ビルドプロセスが機能していることを確認するのにも役立ちます。

以上です。ビルドファイルは、新しいソースファイルが追加されても変更する必要はありません。成果物またはビルドプロセスの一部を変更する場合にのみ変更する必要があります。ある時点で、プロジェクトの再構築など、ビルドプロセス全体を大幅に再構築したい場合があります。それでも、作成したビルドファイルは、分割ビルドファイルプロセスの基盤として機能するはずです。すべてのビルドファイルが読み取るプロパティファイルに共通プロパティを取り出し、ターゲット名を統一し、プロジェクトを続行するだけです。ソースコード管理システムの再構築は、多くの場合、はるかに困難な作業です。

Ant の制限

ビルドプロセスの唯一のメカニズムとして Ant を採用し始める前に、Ant が*行わない*ことを認識しておく必要があります。

スクリプト言語ではありません

Ant を使用すると、プラットフォームとクラスライブラリのテストを少し行って、プラットフォーム固有のビルドを実行できるようにすることで、実行したいことを宣言できます。問題が発生した場合の処理方法を指定したり(リスナークラスはそれを行うことができます)、複雑な条件付きステートメントをサポートしたりすることはできません。

ビルドで例外を処理する必要がある場合は、独自のリスナークラスを作成する方法の簡単な例として、サウンドリスナーを参照してください。複雑な条件付きステートメントは、他の何かでテストを実行してから適切な Ant タスクをビルドすることで処理できます。XSLT はこのために使用できます。

Make ではありません

make の機能、特に推論ルールと依存関係チェックは、Ant には含まれていません。それは、それらがビルドを行う「異なる」方法だからです。Make では依存関係とビルド手順を記述する必要がありますが、Ant ではタスクとタスク間の順序を記述する必要があります。タスク自体が依存関係チェックを実行するかどうかを決定できます。Jikes を使用した完全な Java ビルドは非常に高速であるため、依存関係チェックは比較的議論の余地がありませんが、他の多くのタスク(すべてではありません)は、動作する前にソースファイルのタイムスタンプと宛先ファイルのタイムスタンプを比較します。

人間にとって使いやすい言語ではありません

XML は、人間にとって使いやすい情報表現ではありません。プログラムにとっては妥当な表現であり、テキストエディターとソースコード管理システムはすべてうまく処理できます。しかし、複雑な Ant ファイルは、XML が少し醜いため醜くなる可能性があり、複雑なビルドは、まあ、複雑です。先月書いたファイルが戻ってきたときにも意味がわかるように XML コメントを使用し、必要に応じて適切な XML エディターを使用してファイルを編集してください。

大きなプロジェクトはすぐに複雑になります

大規模なソフトウェアプロジェクトは、相互依存のライブラリ、長いテストサイクル、困難な展開プロセス、そしてそれぞれがソリューションの独自の部分に取り組んでいる多くの人々など、独自の複雑さを生み出します。締め切りが迫り、統合の問題が克服できなくなり、週末と平日の作業負荷の区別がつかなくなり、チームの半分が他の半分と話をしなくなる前でさえそうです。Ant はビルドとテストのプロセスを簡素化し、フルタイムの「makefile エンジニア」の役割を排除できる可能性がありますが、それでも誰かが「ビルドを所有する」ことをやめなければならないわけではありません。ビルドの責任者であるということは、システムに「ant all」と入力するだけではありません。使用するビルドツール、共通のターゲット、プロパティ名とファイル、そして一般的にサブプロジェクトのビルドプロセスを監督する必要があることを意味します。小規模なプロジェクトでは、それを行う必要はありませんが、覚えておいてください。小規模なプロジェクトは見えないうちに大規模なプロジェクトになります。少しのプロセスから始めれば、必要に応じて拡張できます。何もせずに始めると、必要なときには手遅れになります。

ソフトウェアプロジェクトの他のすべての基本的な部分は依然として必要です

ソースコード管理システムがない場合、あなたは困ることになります。Web ページ、依存 jar、インストールファイルなど、すべてが SCM の下にない場合、あなたは依然として困ることになります。それはいつ起こるかという問題です。CVS は事実上無料で、Ant とうまく連携しますが、Sourcesafe、Perforce、Clearcase、StarTeam にも Ant タスクがあります。これらのタスクを使用すると、自動インクリメントビルドカウンターと自動ファイル更新プロセスを使用できます。

また、制御されていない機能の増加に抵抗するために、ある種の変更管理プロセスが必要です。Bugzilla は、これのためのシンプルで低コストのツールです。Ant と継続的なテストプロセスを使用すると、避けられない変更に適応するためにコードを迅速に進化させることができます。

終わりに

ソフトウェア開発は楽しいものです。厳しいプロジェクトの渦中にいて、統合のストレスと非常識な締め切りに向けてすべてをコーディングしようとするのは楽しいことです。確かに爽快です。プロセスに少し自動化を追加すると、混乱が少なくなり、面白みが少なくなるかもしれませんが、それは開発プロセスを管理するための第一歩です。それでも楽しむことはできます。心配事を減らし、ビルド/テスト/デプロイのサイクルを短縮し、機能の増加やスキーなどの重要なことに費やす時間を増やすだけです。さあ、外に出て楽しんでください!

参考文献

著者について

Steve Loughranは、企業の研究開発ラボの研究員であり、現在は、楽しみのために、無理な締め切りの中で本番Webサービスを構築するという長期休暇中です。彼はまた、Apache AntとApache Axisのコミッターであり、Java Development with Antの共著者でもあります。彼は、このドキュメントが気に入った方は、この本を気に入っていただけると思っています。なぜなら、この本はAntを説明するだけでなく、プロセス、デプロイメント、ベストプラクティス、そしてAntを真に役立つものにするためのその他の分野についても深く掘り下げているからです。(マニュアルを焼き直す方が簡単だったでしょうが、それではそれほど役に立たなかったでしょうし、それほど楽しくもなかったでしょう)。

このドキュメントに関するご質問は、Antメーリングリストをご利用ください。