4

Ant プラグインのタスク定義を定義する適切な(最新のベスト プラクティスなど) 方法について、私は本当に混乱しています。以下は、社内の Java アプリの 1 つから取得したコードのスニペットですbuild.xml。次の Ant ターゲットはすべて 100% 完璧に機能することに注意してください (簡潔にするために、それらをまとめてカット アンド ペーストし、内容のほとんどを取り除いています)。

<project name="MyApp" default="package" basedir="." xmlns:jacoco="antlib:org.jacoco.ant">
    <path id="cobertura.path">
        <!-- ... -->
    </path>

    <taskdef name="jacoco-coverage" classname="org.jacoco.ant.CoverageTask"/>
    <taskdef name="jacoco-report" classname="org.jacoco.ant.ReportTask"/>
    <taskdef classpathref="cobertura.path" resource="tasks.properties" />
    <taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask"/>

    <target name="run-coco" depends="doOtherStuff">
        <jacoco:coverage>
            <!-- ... -->
        </jacoco:covergae>

        <jacoco-report>
            <!-- ... -->
        </jacoco-report>        
    </target>

    <target name="findbugs">
        <antcall target="compile" />
        <findbugs home="${findbugs.home}" output="xml:withMessages" outputFile="findbugs.xml">
            <!-- ... -->
        </findbugs>
    </target>
</project>
  1. Findbugs ではなく JaCoCo の XML 名前空間を定義する必要があるのはなぜですか?
  2. アントリブとは?XML 名前空間定義内にある場合もあれば、そこにない場合もあります。
  3. jacoco-coveragejavacoco-reporttaskdefs の両方が名前にハイフン ("-") を使用しますが、対応するタスクが呼び出されjacoco:coveragejacoco-reportそれぞれ...なぜコロン (":") がカバレッジに使用され、どのように機能するのでしょうか (信頼してください! )?

前もって感謝します!

4

1 に答える 1

10

この質問を 1 つずつ見ていきましょう。

ステップ #1: タスクを定義する

次の 2 つの方法のいずれかでタスクを定義できます。

  1. クラスファイルを指定して、そのクラスファイルが名前を定義するタスクを指定できます。
  2. タスク名を持つ jar 内のリソースファイルと、それらのタスク名が使用するクラスファイルを指すことができます。

JaCoCo の場合は、最初に次のことを行いました。

<taskdef name="jacoco-coverage" 
    classname="org.jacoco.ant.CoverageTask"/>
<taskdef name="jacoco-report"
    classname="org.jacoco.ant.ReportTask"/>

ただし、2 番目の方法でも実行できます。

<taskdef resource="org/jacoco/ant/antlib.xml"/>

jacoco jar ファイルを開いてそのディレクトリをドリルダウンすると、antlib.xml. そのファイルを見ると、次のように表示されます。

<antlib>
    <taskdef name="coverage"  classname="org.jacoco.ant.CoverageTask"/>
    <taskdef name="agent"     classname="org.jacoco.ant.AgentTask"/>
    <taskdef name="report"    classname="org.jacoco.ant.ReportTask"/>
    <taskdef name="merge"     classname="org.jacoco.ant.MergeTask"/>
    <taskdef name="dump"      classname="org.jacoco.ant.DumpTask"/>
</antlib>

そのため、jar にリソース ファイルがある場合は、すべてのタスクを 1 つの .xml で定義できます<taskdef>jacoco-coverageあなたが呼んだものは単にcoverageここで呼び出され、あなたjacoco-reportが呼んだものはここで呼び出されることに注意してくださいreport

<jacoco-coverage/>Ant タスクとして使用した場合、私は を使用します<coverage/>

ステップ #2: JAR ファイルはどこにありますか?

上記では、タスクを次のように定義しました。

<taskdef resource="org/jacoco/ant/antlib.xml">

Ant はクラスパスのどこかでそのパスを見つけなければなりませんが、どこでしょうか? JaCoCo jar をフォルダーに入れる$ANT_HOME/libと、クラスパスに自動的に含まれます。これにより、タスクの定義が非常に簡単になります。残念ながら、他の誰かがあなたの Ant スクリプトを実行したい場合、その JaCoCo jar をダウンロードして自分の$ANT_HOME/libフォルダーに入れなければならないことも意味します。あまり携帯できません。

幸いなことに、その JaCoCo jar が配置されている場所を指定できます。通常、プロジェクトはバージョン管理下にあるため、配置するのに最適な場所は、 がある場所のすぐ下にあるプロジェクトのディレクトリbuild.xmlです。誰かがあなたのプロジェクトと をチェックアウトするとbuild.xml、JaCoCo.jar も取得します。

私の好みは、という名前のディレクトリを作成し、そのディレクトリ内にすべてのタスク セットごとにantlibサブディレクトリを作成することです。antlibこの場合、 というディレクトリがありantlib/jacocoます。

jacoco.jar ファイルが安全に保管されたら。そのディレクトリで、<classpath>サブエンティティを追加し<taskdef>て、検索場所を指定できますjacoco.jar

クラスパスの前:

<taskdef resource="org/jacoco/ant/antlib.xml"/>

クラスパスの後:

<taskdef resource="org/jacoco/ant/antlib.xml">
   <classpath>
       <fileset dir="${basedir}/antlib/jacoco"/>
   </classpath>
</taskdef>

を使用することに注意してください。JaCoCo jar ファイルが呼び出されているかどうか<fileset/>は気にしません。jar の正確な名前がわかっている場合は、次のようにすることができます。jacoco.jarjacoco-2.3.jar

<taskdef resource="org/jacoco/ant/antlib.xml">
   <classpath path="${basedir}/antlib/jacoco/jacoco.jar"/>
</taskdef>

そして、数行を保存します。

ステップ #3: XML 名前空間

この時点でjacoco:、タスク名にプレフィックスを付ける必要はありません。

私は単にこれを行うことができます:

<project name="MyApp" default="package" basedir=".">

    <taskdef resource="org/jacoco/ant/antlib.xml">
        <classpath path="${basedir}/antlib/jacoco/jacoco.jar"/>
    </taskdef>

    <target name="run-coco" depends="doOtherStuff">
        <coverage>
            <!-- ... -->
        <coverage>

        <report>
            <!-- ... -->
        <report>        
    </target>
</project>

そして、あなたはそれをそのままにしておくことができます。まったく問題ありません。シンプルでクリーン。

Fooしかし、 という名前の Ant タスク セットとという名前の 2 つの異なる Ant タスク セットを使用Barしていて、両方に<munge/>タスクが定義されている場合はどうなるでしょうか。

<taskdef resource="org/foo/ant/antlib.xml">
    <classpath path="${basedir}/antlib/foo.jar/>
</taskdef>

<taskdef resource="org/bar/ant/antlib.xml">
    <classpath path="${basedir}/antlib/bar.jar/>
</taskdef>

<target name="munge-this">
    <!-- Is this foo.jar's or bar.jar's munge task? -->
    <munge vorbix="fester"/>
</target>

どのmungeタスクが実行されていますか? にあるものですかfoo.jar、それともにあるものbar.jarですか?

これを回避するために、Ant では一連のタスクごとにXML 名前空間を定義できます。このような名前空間は、最上位の<project>エンティティ、タスク自体の内部、または名前で定義できます<target>。99% の場合、それは<project>エンティティで行われます。

<project name="demo" default="package" basename="."
    xmlns:foo="I-will-have-fries-with-that"
    xmlns:bar="Never-on-a-first-date">

 <taskdef uri="I-will-have-fries-with-that"
    resource="org/foo/ant/antlib.xml">
    <classpath path="${basedir}/antlib/foo.jar/>
</taskdef>

<taskdef uri="Never-on-a-first-date"
    resource="org/bar/ant/antlib.xml">
    <classpath path="${basedir}/antlib/bar.jar/>
</taskdef>

<target name="munge-this">
    <!-- Look the 'foo:' XMLNS prefix! It's foo.jar's much task! -->
    <foo:munge vorbix="fester"/>
</target>

<munge/>これで、Foo タスク リストのタスクであることがわかりました。

xmlns、XML 名前空間を定義します。はタスクのxmlns:fooFoo セットの名前空間を定義し、xmlns:barタスクのバー セットの名前空間を定義します。のタスクを使用するときは、名前空間foo.jarを前に付けます。foo:このプレフィックスは の直後にあることに注意してくださいxmlns:

uri、名前空間文字列に一致する単なる文字列です。文字列I-will-have-fries-with-thatとを使用しNever-on-a-first-dateて、文字列自体は重要ではないことを示しました。重要なのは、この文字列がタスクのuriパラメーターと一致することです。<taskdef>このようにして、定義されているタスクは、使用すべき名前空間を認識します。

通常、URI 文字列は URI 定義です。これには 2 つの方法があります。

  • ある程度標準化されたantlib:URI を使用し、名前空間にその逆の名前を使用します: antlib:org.jacoco.ant
  • プロジェクトを指す URL を使用します: http://www.eclemma.org/jacoco/

ドキュメントを指すので、後者を好みます。ただし、前者の方が人気があるようです。

それでは、Jacoco がどのように機能するかを見てみましょう。

<project name="MyApp" default="package" basedir="."
    xmlns:jacoco="antlib:org.jacoco.ant">

    <taskdef uri="antlib:org.jacoco.ant" 
        resource="org/jacoco/ant/antlib.xml">
        <classpath path="${basedir}/antlib/jacoco/jacoco.jar"/>
    </taskdef>

    <target name="run-coco" depends="doOtherStuff">
        <jacoco:coverage>
            <!-- ... -->
        <jacoco:coverage>

        <jacoco:report>
            <!-- ... -->
        <jacoco:report>        
    </target>
</project>

uriJaCoCo<taskdef/>の は文字列と同じであることに注意してくださいxmlns:jacoco

タスク定義については以上です。jacoco:プレフィックスの由来と、そのクラスを含む実際のクラス名、またはタスク名クラスの両方を指すリソースファイルを指してタスクを定義する方法を説明できれば幸いです。

于 2013-04-11T01:40:11.980 に答える