這篇文章整理我在寫 Apache Ant 建構腳本(build.xml)時最核心的三個元素:project、target、property。我會逐一說明每個元素有哪些屬性、怎麼用,並附上可以直接執行的 XML 範例與實際輸出結果,讓你快速看懂 Ant 腳本的運作方式。
Ant 建構腳本的根元素 project 是什麼?有哪些屬性?
project 元素是 Ant 構建檔的根項目,Ant 構建檔至少應該包含一個 project 元素,否則會發生錯誤。在每個 project 元素下,可包含多個 target 元素。它的屬性有三個:
| 屬性 | 用途 |
|---|---|
name | 指定 project 元素的名稱 |
default | 指定 project 預設執行時所要執行的 target 名稱 |
basedir | 指定基準路徑的位置;未指定時,使用 Ant 構建檔的所在目錄作為基準目錄 |
舉例:
<?xml version="1.0" ?>
<project name="antPro" default="getBaseDir" basedir="C:/ThinkInJAVACode">
<target name="getBaseDir">
<echo message="The base dir is: ${basedir}"/>
</target>
</project>
從上例可以看出,我在這裡定義了 default 屬性的值為 getBaseDir,也就是當執行 ant 命令時,如果沒有指明待執行的 target,就會執行預設的 target——getBaseDir。此外,我也定義了 basedir 屬性的值為 C:/ThinkInJAVACode,進入 C:/ThinkInJAVACode 後執行 ant 命令,會得到以下結果:
Buildfile: C:\ThinkInJAVACode\build.xml
sayBaseDir:
[echo] The base dir is: C:\ThinkInJAVACode
BUILD SUCCESSFUL
Total time: 0 seconds
target 元素怎麼運作?depends、if、unless 屬性差在哪?
target 是 Ant 的基本執行單元,它可以包含一個或多個具體的任務,多個 target 之間可以存在相互依賴關係。它有如下屬性:
| 屬性 | 用途 |
|---|---|
name | 指定 target 的名稱,這個名稱在同一個 project 中必須是唯一的。我們可以透過指定 target 名稱來執行某個 target |
depends | 描述 target 之間的依賴關係;若依賴多個 target,以「,」間隔。Ant 會依照 depends 屬性中 target 出現的順序依次執行,被依賴的 target 會先執行 |
if | 驗證指定的屬性是否存在;若存在,所在的 target 才會被執行 |
unless | 功能與 if 相反:驗證指定的屬性是否存在;若不存在,所在的 target 才會被執行 |
description | 關於 target 功能的簡短描述與說明 |
舉例說明:
<?xml version="1.0" ?>
<project name="targetPro" default="targetB">
<target name="targetA" if="ant.java.version">
<echo message="JAVA Version: ${ant.java.version}"/>
</target>
<target name="targetB" depends="targetA" unless="philander">
<description>
a depend example!
</description>
<echo message="The base dir is: ${basedir}"/>
</target>
</project>
從以下執行結果可以看到,我們執行的是名為 targetB 的 target。由於它依賴 targetA,所以 targetA 會首先被執行;同時因為系統配置了 JDK,ant.java.version 屬性存在,所以 targetA 被執行,輸出資訊 [echo] JAVA Version: 1.6。targetA 執行完畢後接著執行 targetB——因為 philander 屬性不存在,而 unless 屬性是在屬性不存在時才進入所在 target 的,由此可知 targetB 得以執行:
Buildfile: C:\ThinkInJAVACode\build.xml
targetA:
[echo] JAVA Version: 1.6
targetB:
[echo] The base dir is: C:\ThinkInJAVACode
BUILD SUCCESSFUL
Total time: 0 seconds
property 元素怎麼定義參數?有哪些內置屬性可用?
property 元素可以看作參量或參數的定義。project 的屬性可以透過 property 元素來設定,也可以在 Ant 之外設定。若要在外部引入某個檔案,例如 build.properties,可以透過如下內容將其引入:
<property file="build.properties"/>
property 元素可用作 task 的屬性值:在 task 中把屬性名放在 ${ 和 } 之間,放在 task 屬性值的位置即可取值。
Ant 提供了一些內置屬性,其中能得到系統屬性的清單與 Java 文件中 System.getProperties() 方法得到的屬性一致,這些系統屬性可參考 Sun 網站的說明。同時,Ant 還提供了一些它自己的內置屬性:
basedir:project 基目錄的絕對路徑ant.file:buildfile 的絕對路徑,上例中ant.file的值為C:\ThinkInJAVACode\build.xmlant.version:Ant 的版本資訊,本文為 1.8.1ant.project.name:當前指定的 project 名字,即前文提到的 project 的name屬性值ant.java.version:Ant 檢測到的 JDK 版本,本文為 1.6
舉例說明:
<?xml version="1.0" ?>
<project name="propertyPro" default="example">
<property name="name" value="philander"/>
<property name="age" value="25"/>
<target name="example">
<echo message="name: ${name}, age: ${age}"/>
</target>
</project>
上例中我設置了名為 name 和 age 的兩個屬性,這兩個屬性設置後,在下文中可以透過 ${name} 和 ${age} 分別取得這兩個屬性值。
常見問題
build.xml 中一定要有 project 元素嗎?
一定要有。project 是 Ant 構建檔的根元素,一個 build.xml 至少要包含一個 project 元素,否則 Ant 會直接報錯。所有 target 都必須定義在 project 底下。
target 的 depends 屬性可以依賴多個 target 嗎?
可以。多個依賴 target 之間用逗號「,」間隔,Ant 會依照 depends 屬性中 target 出現的順序依次執行,所有被依賴的 target 都會在目標 target 之前先執行完畢。
target 的 if 和 unless 屬性有什麼差別?
if 是「屬性存在才執行」,unless 則相反,是「屬性不存在才執行」。兩者都用來驗證指定屬性是否存在,藉此控制 target 是否執行,常用於依環境條件切換建構流程。
怎麼在 Ant task 中引用 property 的值?
把屬性名放在 ${ 和 } 之間,寫在 task 的屬性值位置即可,例如 ${name}。property 可以用 <property> 元素直接定義,也可以透過 <property file="build.properties"/> 從外部檔案引入。
Ant 提供哪些常用的內置屬性?
常用的有 basedir(project 基目錄絕對路徑)、ant.file(buildfile 絕對路徑)、ant.version(Ant 版本)、ant.project.name(project 名稱)、ant.java.version(偵測到的 JDK 版本)。此外所有可由 System.getProperties() 取得的系統屬性也都可用。
參考資料
延伸閱讀
- ant 腳本編寫 – 關鍵元素:同樣聚焦 Ant、Java,可接著比較不同情境的做法。
- Apache Ant 常用命令整理:copy、delete、mkdir、move、echo 用法範例:同樣聚焦 Ant、Java,可接著比較不同情境的做法。
- 利用 Ant 構建和部署 Java 專案:同樣聚焦 Ant、Java,可接著比較不同情境的做法。
最後更新
2026-08-28(原文發布於 2013-07-25,本文保留原始筆記內容並補上 GEO 結構。)
關於作者
Claire Chang | 企業 AI 導入與流程轉型顧問。專注於 AI Agent 架構設計、ERP 系統整合與企業 AI 治理。
首次發布:2013-07-25
