まず、このドキュメントが対象とするプロジェクトについて、いくつかの前提を挙げます。
AntはIDEの優れた補助ツールでもあり、デプロイメントのあらゆる雑務や、クリーンで自動化されたビルドを行うことができます。しかし、優れた最新のIDEはそれ自体が生産性向上ツールであり、使い続けるべきです。Antを使うことで、チームはIDEの選択に多少の自由度を持つことができます。「開発では好きなものを使って構いませんが、デプロイメントビルドにはAntを使ってください」 多くの最新のオープンソースおよび商用IDE(jEdit、Forte、Eclipse、IDEAなど)がAntをサポートしているため、開発者は優れたIDEを使用し、Antはツールに統合された厳格でポータブルなビルドプロセスを提供することができます。
標準のターゲット名を使用することで、ant タスクを使用して、下位のクラスに作業を委譲する包括的なAntビルドファイルを簡単に作成できます。例えば、cleanターゲットは、intfとimplのサブディレクトリに、親ディレクトリから渡すことができます。
<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では、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の一般的な障壁は、移植性のないコマンドラインツール(execタスク)の使用、パスの問題、およびハードコーディングによるものの配置です。
どちらのコマンドライン呼び出しタスクでも、コードを実行するプラットフォームを指定できるため、ターゲットとするプラットフォームごとに異なるタスクを記述できます。あるいは、プラットフォームの違いは、Antが呼び出す外部コード内で処理できます。これは、新しいタスクのコンパイル済みJava、または外部スクリプトファイルにすることができます。
このプラットフォーム間の違い(実際には、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では正しく実行できません。 Get、Touch、Unjar/Unwar/Unzip など、そのようなタスクはJava 1.1では機能が低下し、通常は現在のタイムスタンプが代わりに使用されます。
最後に、Perlは、バッチファイルではなく、クロスプラットフォームでJava呼び出しをラップするのに適した場所です。ほとんどのUnixディストリビューションに含まれており、ActiveStateからWin32プラットフォーム用に簡単にダウンロードできます。.pl拡張子を持つPerlファイルは、1行目のコメントに通常のUnixパスを記述し、実行可能としてマークすることで、Windows、OS/2、およびUnixで実行できるため、問題なくAntから呼び出すことができます。Perlコードは、独自のプラットフォームの問題を解決できます。Perlコードを再配布する際には、ファイルの行末を適切なプラットフォームに設定することを忘れないでください。 fixCRLF がその処理を実行できます。
もう1つの良い戦術は、統合ディレクトリツリーを使用し、そのツリー内に追加のツールを追加することです。すべての参照は、ツリーを基準にして相対的に行うことができます。チームメンバーがプロジェクト内のディレクトリをパスに追加することが想定されている場合は、Ant `exec`タスクによって呼び出されるツールを含め、コマンドラインツールをそこに含めることができます。すべてをソースコード管理下に置くと、CVSまたは同等のものからビルド/実行環境を取得するための一元的な場所が得られます。
Antは、デプロイ用にファイルをJar、Tar、または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アプリケーションをデプロイ、アンデプロイ、およびリロードするタスクが含まれています。
最後に、CopyとCopydirを使用してファイルを宛先にコピーするか、Mailまたは添付ファイルを認識するMimeMailを使用して個人またはプロセスに送信するというフォールバックがあります。あるプロジェクトでは、私たちのチームはAntを使用して、ビルドとその後の長いCopyタスクのセットを通じてCDイメージをビルドしました。これは驚くほどうまく機能し、WinNTリモートデスクトップ接続を介して実行していたWebブラウザーからプルダウンしたmyrealbox.comの無料メールサービスにメールで送信したときよりもはるかに簡単でした。SSHを介してトンネリングされていました。
bin | 共通のバイナリ、スクリプト - これをパスに配置します。 |
build | これはビルド用のツリーです。Antはこれを作成し、「clean」プロジェクトで空にすることができます。 |
dist | 配布出力はここに配置されます。ディレクトリはAntで作成され、cleanはそれを空にします。 |
doc | 手作業で作成されたドキュメント |
lib | インポートされたJavaライブラリはこのディレクトリに配置されます。 |
src | ソースコードはこのツリーの下に、*パッケージ名と一致する階層で*配置されます。<javac>の依存関係ルールではこれが必要です。 |
Javadoc出力は、doc/フォルダーの下のbuild/、またはdoc/javadoc.
サブプロジェクト全体で単一のビルドを行うには、親build.xmlファイルを使用して、サブプロジェクトを呼び出します。
このスタイルは、異なるチームが異なるコードアクセス権/コミットメント権を持っている場合に適しています。リスクは、サブプロジェクトに余分な自由度を与えることで、互換性のないソース、ライブラリ、ビルドプロセスが発生し、ワークロードと統合の苦労が増える可能性があることです。
かなり疎結合のプロジェクトのコレクションを制御する唯一の方法は、すべてが互換性があることを確認する完全に自動化されたビルドおよびテストプロセスを用意することです。Sam Rubyは、すべてのアパッチJavaライブラリに対してこれを実行し、何かが壊れたときに全員にメールを送信します。独自のプロジェクトでは、Cruise Controlを使用して、自動化された継続的なバックグラウンドビルドプロセスを利用できる場合があります。
という名前の独立したビルドファイルを配置できます。このプロジェクトスタイルは、全員が互いに信頼し合っており、サブプロジェクトがあまりにも大きく複雑でない場合に適しています。リスクは、プロジェクトの進行に伴い、より疎結合の設計への分割が必要になることです。しかし、これが実現するまでに、スケジュールのプレッシャーと複雑に絡み合ったビルドファイルにより、分割を実行することがほぼ不可能になります。そうなった場合は、プロジェクトディレクトリ構造をリファクタリングする時間があるまで、そのままにしておきます。
多くの場合、更新にはbuild.xmlファイルの変更が必要になります。ほとんどの変更は後方互換性を維持するように意 نظرされていますが、互換性のない変更が必要になる場合があります。そのため、大きな節目の後の落ち着いた時期に更新を行うことが重要です。ant.jarと関連ファイルをCVSツリーに含めることで、古いバージョンのソフトウェアを確実にビルドできるようにすることも、この理由の一つです。
最も積極的な戦略は、Antソースの週次または日次のスナップショットを取得し、ビルドして使用することです。これは、新しいタスクと属性が安定するまで時間がかかることがあるため、build.xmlファイルをより定期的に調整する必要があります。このアプローチを採用するには、本当に新しい機能が必要であるか、余計な作業を楽しんでいるか、同僚を困らせることに喜びを感じている必要があります。
新しいタスクでAntを拡張し始めると、定期的なビルドを取得することが急に魅力的になります。最新のAntビルドは、基礎クラスの定期的な拡張機能を利用できるため、拡張機能を作成するための常に最適なプラットフォームです。また、既に完了している作業に時間を浪費することを防ぎます。EJBエンジン、SOAPサーバーとの通信、テキストファイルの大文字への変換など、複雑な処理を行うための新しく提出されたタスクは、まさに必要なものである可能性があります。そのため、それを取得し、拡張し、拡張機能を世界中に提供してください。これは、Ant 0.8で「テキストケースコンバーター」タスクの作業を単独で開始し、6か月後にその存在を発表し、賞賛の代わりに既存の実装への有用なポインターを得るよりも、確かに優れています。このプロセスに参加することの最終的な利点は、Ant CVSツリーにタスクを追加しやすくなり、Antがプロジェクトを機能させるために行ったすべての変更を引き受ける日付が早まることです。それが起こると、公式のAntリリースに戻り、他のすべての危機に対処できます。
また、他の開発者が作業、問題、経験を投稿する場である開発メーリングリストに参加する必要があります。量は非常に多く、1日に40以上のメッセージが送信される可能性があるため、あまり使用していないメールアドレスにルーティングすることを検討してください。そして、チームの全員を購読させないでください。気が散りすぎる可能性があります。
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は、制御するサーバーの特別な場合を除いて、実際のインストーラーツールの代わりにはなりませんが、そのコンテキストでは、リモートインストールをビルドと統合できます。
すべてのパーサー用の醜いメカニズムとクリーンなメカニズムの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>タスクのすべての使用に設定することを忘れないでください。
PROJECT_HOME
の下のCVS制御ライブラリツリーから実行されるカスタム呼び出しスクリプトを用意することで、 また、チーム全体で Ant のバージョンを制御できます。開発者は必要に応じて Ant の別のコピーを持つことができますが、CVS ツリーには常にプロジェクトのビルドに使用される jar セットが含まれています。既存の Ant スクリプトを呼び出すラッパースクリプトを作成することもできます。これは、それらを拡張する簡単な方法です。ラッパースクリプトは、追加の定義を追加し、明示的なターゲットに名前を付け、再定義することができますANT_HOMEそして、一般的に開発を容易にします。Windows の「ant」は実際には「ant.bat」であるため、別のバッチファイルから「CALL ant」ステートメントを使用して呼び出す必要があります。そうしないと、ラッパーに戻りません。
さらに一歩進んで、Ant タスクインターフェースをコードに、セカンダリ、プライマリ、または唯一のインターフェースとして提供することを検討してください。Ant は、クラスパスの設定を処理するため、実際には Java アプリケーションの優れたブートローダーであり、プリアンブルとポストアンブルの作業にすべての組み込みタスクを再利用できます。XDoclet などの一部のプロジェクトは、Ant の下でのみ実行されます。それが適切な場所だからです。
デバッグ/リリースの切り替えは、コンパイルタスクの前に呼び出される個別の初期化ターゲットで処理できます。これにより、適切なプロパティが定義されます。Antcall は、ビルドファイルに 2 つのプロパティ初期化パスを持つことができるため、ここで役立ちます。
内部ターゲットを使用してプロセスを構造化する必要があります
<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 タスクをビルドすることで処理できます。XSLT はこのために使用できます。
また、制御されていない機能の増加に抵抗するために、ある種の変更管理プロセスが必要です。Bugzilla は、これのためのシンプルで低コストのツールです。Ant と継続的なテストプロセスを使用すると、避けられない変更に適応するためにコードを迅速に進化させることができます。
このドキュメントに関するご質問は、Antメーリングリストをご利用ください。