建構檔案


在Ant 中,你想要執行哪些任務,任務的執行順序,任務執行過程中共用的屬性,都是定義在build.xml檔 案中。通常一個專案會有一個build.xml,例如,以下將待會要執行的一些任務定義在build.xml中:
<project name="example" default="run"> 
<property name="src.dir" value="src"/>
<property name="bin.dir" value="bin"/>
<property name="bak.dir" value="bak"/>

<target name="prepare">
<mkdir dir="${bin.dir}"/>
<mkdir dir="${bak.dir}"/>
<copy todir="${bak.dir}">
<fileset dir="${bin.dir}"/>
</copy>
</target>

<target name="compile" depends="prepare">
<javac srcdir="${src.dir}" destdir="${bin.dir}"/>
</target>

<target name="run" depends="compile">
<java classname="cc.openhome.HelloAnt">
<classpath path="${bin.dir}"/>
</java>
</target>
</project>

這邊打算進 行的工作是:編譯src/cc/openhome中的HelloAnt.java,其編譯成果將儲存至bin目錄中,如果 bin目錄不存在就建立它,每一次編譯將bin中前一次編譯的成果複製至bak目錄,如果bak目錄不存在就建立它,最後執行程式。想像一下,原本你在文 字模式下,要執行完這些動作,需要下哪些指令(javac、java、copy等)與相關引數(-d、-cp、-sourcepath等),也想像一下, 在IDE中也許本來並沒有備份這個選項,你可以使用Ant來完成。

在上例中,build.xml是以<project>為 根標籤。一個build.xml中可以定義多個任務, 這些任務可能是建立目錄、編譯原始碼、搬移檔案、產生doc文件、進行測試、產生測試報告等,這些任務通常組織為一個目標 (target)

<project> 中包括數個<target>,每一個< target>有一個名稱, <project>的任務執行進入點預設是名稱為"run"<target>, 每個<target> 可以使用depends屬性指定依賴其它的< target>,也就是所依賴的<target>必須先執行完成,才會執行自己的目標。在上例中,"run"的完成依賴於 "compile"的完成,"compile"的完成又依賴於"prepare"的完成,所以在建構開始時,會先執行"prepare",完成後再執行 "compile",最後執行"run"。

構過程中< target>所共享的屬性,可以使用<property>標 籤設定,每一個屬性的值會有個名稱對應,以這個例子而言,您設定了程式碼來源位置、編譯結果目標目錄與備份目錄。

HelloAnt.java只是個簡單的程式:
package cc.openhome;
public class HelloAnt {
public static void main(String[] args) {
System.out.println("Hello! Ant!!");
}
}

就這個例子而言,使用Ant是有點小題大作了,不過這讓我們可以將焦點集中在Ant本身的設定與執行。編 輯好build.xml之後,在文字模式下於build.xml所在的目錄中,直接下ant指 令即可開始建構專案,ant預設會讀取同一個目錄下的build.xml,第一次執行ant時會出現以下的文字提示建構過程:
>ant
Buildfile: C:\workspace\example\build.xml

prepare:
    [mkdir] Created dir: C:\workspace\example\bin
    [mkdir] Created dir: C:\workspace\example\bak

compile:
    [javac] C:\workspace\example\build.xml:14: warning: 'includeantruntime' was not
set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 1 source file to C:\workspace\example\bin

run:
     [java] Hello! Ant!!

BUILD SUCCESSFUL
Total time: 1 second


可以看到ant已 經完成了所指定的工作,現在假設修改了HelloAnt.java並存檔,接下來再次下達ant指令,這次出現以下的文字提示建構過程:
>ant
Buildfile: C:\workspace\example\build.xml

prepare:
     [copy] Copying 1 file to C:\workspace\example\bak

compile:
    [javac] C:\workspace\example\build.xml:14: warning: 'includeantruntime' was
not set, defaulting to build.sysclasspath=last; set to false for repeatable buil
ds

run:
     [java] Hello! Ant!!

BUILD SUCCESSFUL
Total time: 0 seconds


這次由於bin與 bak目錄已經存在,就不用再進行新建目錄的工作,ant檢查bin中有之前構建的檔案,於是將它複製至bak目錄中。

在建
程式時,有些目標 所定義的任務可能是可選的,可以藉由在設定<target>時 設定if條 件,並在建構時指定該條件為true 或 false,以決定該目標是否要執行,例如可以這麼設定:
<target name="some" if="conditional">
    some task.....
</target>
 
使用if設定條件 目標時,表示只有在conditional被設置時才會被執行,在執行
ant指令時,您就可以如下來決定some是否 要執行:
ant -buildfile build.xml -Dconditional=true

您也可以使用unless來設定條件目標:
<target name="some" unless="conditional">
    some task.....
</target>
 
由於您使用了 unless來設定條件目標,所以只有在conditional沒有被設定時,目標才會被執行。由於
ant可以在一個建構檔案中調用另一個建構檔案,在調用的時候,兩個建構檔案之間可能會有一些重複的屬性設定,如果您 想要避免某個屬性被重複設定了,可以這麼撰寫:
<target name="setProperties" unless="setProperties">
    <property name="someProperty" value="someValue"/>
    ...
</target>
 
你在啟動ant指令時,也可以指定目標,例如:
ant prepare

可以使用<ant>標 籤,在一個
建構檔案中調用另一個建構檔案,一個簡單的例子 如下:
<project name="someProject" default="all">
    ......
    <target name="some" depends="other">
        <ant antfile="./project2/build.xml">
            <property name="condition_name" value="true">
        </ant>
    <target>
    ......
</project>
 

在<property> 中設定value為true,當您在另一個建構中有目標使用了條件式(if或unless)時,這可以給予該條件一個true的特性值。

您也可以指定專案的目錄來調用預設的build.xml,例如:
<project name="someProject" default="all">
    ....
    <target name="some" depends="other">
        <ant dir="./project2">
            <property name="condition_name" value="true">
        </ant>
    <target>
    ....
</project>
 

您也可以僅僅調用另一個建構檔案中的某個目標,例如:
<ant antfile="./project2/build.xml" target="prepare"/>