目標

目標是任務和資料類型的容器,它們在建置過程中合作以達到所需狀態。

目標可以依賴其他目標,而 Apache Ant 會確保這些其他目標在目前目標之前已執行。例如,您可能有編譯目標和建立可發行套件目標。您只能在先編譯後才能建立可發行套件,因此發行目標依賴編譯目標。

Ant 會嘗試以 depends 屬性中出現的順序 (從左到右) 執行目標。請記住,當較早的目標依賴較晚的目標時,較晚的目標可能會較早執行。

<target name="A"/>
<target name="B" depends="A"/>
<target name="C" depends="B"/>
<target name="D" depends="C,B,A"/>

假設我們要執行目標 D。從其 depends 屬性來看,您可能會認為會先執行目標 C,然後是 B,最後是 A。錯!C 依賴 B,而 B 依賴 A,因此會先執行 A,然後是 B,再是 C,最後才是 D。

Call-Graph:  A → B → C → D

在從給定目標 (例如上述的 D) 向後延伸的依賴鏈中,每個目標只會執行一次,即使有多個目標依賴它也是如此。因此,執行 D 目標會先呼叫 C,而 C 會先呼叫 B,而 B 會先呼叫 A。在 A、B 和 C 執行完畢後,執行會回到 D 的依賴清單,而清單不會呼叫 B 和 A,因為它們已分別在解析 C 和 B 的依賴過程中作為 D 的依賴項而被呼叫。如果在處理 C 和 B 時未發現此類依賴項,則會在處理 D 的依賴清單時在 C 之後執行 B 和 A。

目標還有能力在已設定 (或未設定) 屬性的情況下執行。這允許根據系統狀態 (Java 版本、作業系統、命令列屬性定義等) 更佳地控制建置流程。若要讓目標感知此屬性,您應加入 if (或 unless) 屬性,並加上目標應對其做出反應的屬性名稱。注意:在最簡單的情況下,Ant 只會檢查屬性是否已設定,值並不重要,但使用屬性擴充,您可以建立更複雜的條件。請參閱屬性頁面以取得更多詳細資訊。例如

<target name="build-module-A" if="module-A-present"/>
<target name="build-own-fake-module-A" unless="module-A-present"/>

在第一個範例中,如果已設定 module-A-present 屬性 (為任何值,例如 false),則會執行目標。在第二個範例中,如果已設定 module-A-present 屬性 (同樣,為任何值),則不會執行目標。

if/unless 屬性中只能指定一個屬性名稱。如果您想要檢查多個條件,可以使用依賴目標來計算檢查結果

<target name="myTarget" depends="myTarget.check" if="myTarget.run">
    <echo>Files foo.txt and bar.txt are present.</echo>
</target>

<target name="myTarget.check">
    <condition property="myTarget.run">
        <and>
            <available file="foo.txt"/>
            <available file="bar.txt"/>
        </and>
    </condition>
</target>
Call-Graph:  myTarget.check → maybe(myTarget)

如果沒有 ifunless 屬性,目標將始終執行。

重要事項ifunless 屬性僅啟用或停用附加它們的目標。它們不控制條件目標依賴的目標是否執行。事實上,它們甚至不會在目標即將執行且其所有前置目標都已執行之前進行評估。

可選的 description 屬性可用於提供此目標的一行描述,該描述由 -projecthelp 命令列選項列印。沒有此類描述的目標被視為內部目標,除非使用 -verbose-debug 選項,否則不會列出。

將您的 tstamp 任務放在所謂的初始化目標中是一個好習慣,所有其他目標都依賴於此目標。確保該目標始終是其他目標的依賴項清單中的第一個目標。在本手冊中,大多數初始化目標的名稱為 "init"

<project>
    <target name="init">
        <tstamp/>
    </target>
    <target name="otherTarget" depends="init">
        ...
    </target>
</project>

特別是如果您只有少數任務,您也可以將這些任務直接放在專案標籤下(自 Ant 1.6.0 起

<project>
    <tstamp/>
</project>

如果設定了 depends 屬性和 if/unless 屬性,則會先執行 depends 屬性。

目標具有以下屬性

屬性 說明 必要
name 目標的名稱。
depends 此目標依賴的目標名稱的逗號分隔清單。
if 必須設定才能執行此目標的屬性名稱,或 評估為 true 的內容
unless 必須未設定才能執行此目標的屬性名稱,或 評估為 false 的內容
description 此目標功能的簡短說明。
extensionOf 將目前的目標新增到名為 擴充點 的依賴項清單中。自 Ant 1.8.0 起
onMissingExtensionPoint 如果此目標嘗試擴充不存在的 擴充點,該怎麼辦。(failwarnignore)。自 Ant 1.8.2 起 否;除非存在 extensionOf,否則不允許,預設為 fail

目標名稱可以是 XML 檔案編碼中有效的任何英數字元串。空字串 在此組中,逗號 , 和空格   也是如此。請避免使用這些字元,因為它們將不會在未來的 Ant 版本中受到支援,因為它們在命令列和 IDE 上會造成混淆。IDE 對不尋常目標名稱或包含空格的任何目標名稱的支援會因 IDE 而異。

以連字號開頭的目標,例如 -restart,是有效的,可用於命名不應從命令列直接呼叫的目標。
對於 Ant 的主類別,每個以連字號開頭的選項都是 Ant 本身的選項,而不是目標。因此,無法從命令列呼叫這些目標。另一方面,IDE 通常不使用 Ant 的主類別作為進入點,而且通常可以從 IDE 呼叫它們。

擴充點

自 Ant 1.8.0 起.

擴充點類似於目標,它們具有名稱和 depends 清單,而且可以從命令列執行。就像目標一樣,它們表示建置程序中的狀態。

與目標不同,它們不包含任何任務,它們的主要目的是收集在 depends 清單中對所需狀態有貢獻的目標。

目標可以透過其 extensionOf 屬性將自己新增到擴充點的 depends 清單中。如果有多個目標新增自己,則會在擴充點的明確 depends 屬性的目標之後新增新增自己的目標,但它們的相對順序未定義。

擴充點的主要目的是作為建置檔案的擴充點,這些檔案設計為 匯入。在已匯入的檔案中,擴充點定義必須達到的狀態,而且來自其他建置檔案的目標可以加入所述擴充點的 depends 清單,以對該狀態有貢獻。

例如,已匯入的建置檔案可能需要編譯程式碼,它可能看起來像

<target name="create-directory-layout">
   ...
</target>
<extension-point name="ready-to-compile"
              depends="create-directory-layout"/>
<target name="compile" depends="ready-to-compile">
   ...
</target>
Call-Graph:  create-directory-layout → 'empty slot' → compile

而且您需要在編譯之前產生一些來源,然後在您的主建置檔案中,您可以使用類似

<target name="generate-sources"
        extensionOf="ready-to-compile">
   ...
</target>
Call-Graph:  create-directory-layout → generate-sources  → compile

這將確保在 compile 目標之前執行 generate-sources 目標。

不要依賴 depends 清單的順序,如果 generate-sources 依賴於 create-directory-layout,則它必須透過自己的 depends 屬性明確依賴於它。