重複:螞蟻是不是一種編程語言。實際上,在黑板上寫下100次。
螞蟻不是一種編程語言,所以不要這樣想。它是一個構建依賴矩陣。
對於程序員來說,圍繞這個想法很困難。他們想要告訴Ant每一步以及何時應該完成。他們想要循環,如果語句。他們會求助於使用build.sh
腳本來調用Ant中的各種目標,因爲您無法輕鬆編程Ant。
在Ant中,您指定了離散任務,以及哪些任務依賴於其他任務,並讓Ant處理執行任務的位置和時間。
我在說的是,你通常不會將任務分成子任務,然後嘗試對它們調用<ant>
或<subant>
。
有離散任務,但讓每個任務都知道他們依賴的其他任務。還要記住在Ant中沒有真正的順序。當你列出depends=
任務,也不能保證其順序,他們將在執行。
標準的Ant風格(這意味着我的方式做到這一點(又名正確的方式),而不是我的方式同事這樣做(aka The Wrong Way)),通常規定在屬性文件的頂部定義任務,而不是在任何目標中定義任務。下面是我如何構建一個基本的輪廓我build.xml
:
<project name=...>
<!-- Build Properties File -->
<property name="build.properties.file"
value="${basedir}/build.properties"/>
<property file="${build.properties.file"/>
<!-- Base Java Properties -->
<property name="..." value="..."/>
<taskdef/>
<taskdef/>
<!-- Javac properties -->
<property name="javac..." value="..."/>
<task/>
<task/>
</project>
這就產生了一個有趣的層次。如果您有一個名爲build.properties
的文件,它將覆蓋build.xml
腳本中定義的屬性。例如,您有:
<property name="copy.verbose" value="false"/>
<copy todir="${target}"
verbose="${copy.verbose}">
<fileset dir="${source}"/>
</copy>
您可以通過僅僅在build.properties
文件中設置copy.verbose = true
開啓冗長的副本。
$ ant -Dbuild.properties.file="my.build.properties"
(是的,是的,我知道有一個爲ant
一個-property
命令行參數)
我通常:而且,你可以僅僅通過指定在命令行上指定一個不同的構建屬性文件將build.xml
中的各個值設置爲假定的默認值,但任何人都可以通過創建build.properties
文件來更改它們。而且,由於所有的基本屬性都在開頭,所以很容易找到。
任務也在這個非目標空間中定義。這樣,我可以很容易地找到定義,因爲它們在每個build.xml
的相同位置,並且我知道我可以使用任務而不用擔心任務定義目標是否已經命中。現在
,你的問題:
定義您的任務(並沒有定義任務焦油,否則你會自己開車瘋了)。然後,定義每個這些任務的依賴關係。開發人員可以選擇他們想要擊中的目標。例如:
<project>
<description>
yadda, yadda, yadda
</description>
<taskdef name="cobertura"/>
<target name="compile"
description="Compile the code"/>
<!-- Do you have to compile code before you run Cobertura?-->
<target name="coverage"
description="Calculate test coverage"
depends="compile">
<mkdir dir="${coverage.dir}"/>
<cobertura-instrument/>
</target>
<project>
如果你想編譯代碼,但不運行任何測試,你與compile
目標執行ant
。如果您想運行測試,則執行ant
,並使用coverage
目標。沒有必要使用depends=
參數。
另請注意description=
參數和<description>
任務。這是因爲如果你這樣做:
$ ant -p
螞蟻會顯示哪些內容在<description>
任務,具有description
參數所有目標,而且描述。這樣,開發人員就知道哪些目標用於哪些任務。
順便說一句,我還建議做正確的方式(也就是我這樣做),並在Maven lifecycle goals後命名您的目標。爲什麼?因爲這是標準化目標名稱的好方法。開發人員知道clean
將刪除所有構建的工件,並且compile
將運行<javac>
任務,並且該test
將運行junit
測試。因此,您應該使用Cobertura plugin:cobertura
中的目標。
編輯
我的問題是:我把「覆蓋」作爲與「優化」和「調試」,即構建味道。這就是我的困難所在:對於Java,覆蓋率在編譯步驟中會產生額外的中間目標。
我看Corburta頁面,並且有在<javac>
任務沒有真正的改變(這是的一部分編譯目標。
相反,你對已建成.class
文件運行Corburtura ,然後運行<junit>
任務。最大的變化是在你的<junit>
現在的任務,其中必須包括您Corburtura罐子引用,以及對你的儀表類。
我想像你可以有一個corburtura
目標或要什麼都叫它。該目標運行儀器化的JUnit測試。這是您希望開發人員打的目標,並且應該包含運行儀器測試的說明。
當然,如果不先測試它們,您將無法運行測試的Junit測試。因此,您的corburtura
目標將取決於另一個instrument.tests
目標。這個目標是內部的。運行你的build.xml
的人通常不會在沒有運行這些測試的情況下說「儀器測試」。因此,這個目標沒有描述。
當然,instrument.tests
目標取決於其.class
文件到儀器,所以它必須就compile
目標的依賴在運行<javac>
任務:
<target name="instrument.classes"
depends="compile">
<coburtura-instrument/>
</target>
<target name="corburtura"
depends="instrument.classes"
description="Runs the JUnit tests instrumented with Corburtura">
<junit/>
</target>
唯一的問題是,你指定你的<junit>
目標兩次:一次當儀表,一次正常測試。這可能是一個小問題。如果您更新了JUnit測試的運行方式,則必須在兩個地方完成。
如果你想解決這個問題,你可以使用<macrodef>
來定義運行宏的JUnit測試。我使用了Corbertura頁面上的內容來幫助提綱。完全沒有經過測試,可能是語法錯誤:
<target name="instrument.tests"
depends="compile">
<corburtura-instrument/>
</target>
<target name="corburtura"
depends="instrument.tests"
description="Instrument and run the JUnit tests">
<run.junit.test fork.flag="true">
<systemproperty.addition>
<sysproperty key="net.sourceforge.corbertura.datafile"
file="${basedir}/cobertura.ser" />
</systemproperty.addition>
<pre.classpath>
<classpath location="${instrumented.dir}" />
</pre.classpath>
<post.classpath>
<classpath refid="cobertura_classpath" />
</post.classpath>
</run.junit.test>
</target>
<target name="test"
description="Runs the Junit tests without any instrumentation">
<run.junit.test/>
</target>
<macrodef name="run.junit.test">
<attribute name="fork.flag" default="false"/>
<element name="sysproperty.addition" optional="yes"/>
<element name="pre.classpath" optional="yes"/>
<element name="post.classpath" optional="yes"/>
<sequential>
<junit fork="@{fork.flag}" dir="${basedir}" failureProperty="test.failed">
<systemproperty.addtion/>
<pre.classpath/>
<classpath location="${classes.dir}" />
<post.classpath/>
<formatter type="xml" />
<test name="${testcase}" todir="${reports.xml.dir}" if="testcase" />
<batchtest todir="${reports.xml.dir}" unless="testcase">
<fileset dir="${src.dir}">
<include name="**/*Test.java" />
</fileset>
</batchtest>
</junit>
</sequential>
</macrodef>
(我使用ant 1.8.2) – xtofl