Scriptdef

說明

Scriptdef 可用於使用腳本語言定義 Apache Ant 任務。由 Apache BSFJSR 223 支援的 Ant 腳本語言可用於定義腳本。Scriptdef 提供一種機制,可將建置中的控制邏輯封裝在 Ant 任務中,並將提供控制樣式任務的需求降至最低。在保留 Ant 建置檔案簡單結構的同時,可以使用複雜邏輯。Scriptdef 也可用於建立新的自訂任務原型。當然,隨著腳本複雜性的增加,最好將任務定義移轉到基於 Java 的自訂任務中。

注意:此任務仰賴未包含在 Ant 散發版中的外部函式庫。請參閱 函式庫相依性 以取得更多資訊。

任務支援的屬性和巢狀元素可以使用 <attribute><element> 巢狀元素來定義。這些屬性可供實作任務的腳本使用,作為兩個集合樣式腳本變數 attributeselements。可以使用屬性名稱存取 attributes 集合中的元素。使用巢狀元素名稱存取 elements 集合。這將傳回巢狀元素的所有執行個體清單。可以使用整數索引存取此清單中的執行個體。

注意:Ant 會將所有屬性和元素名稱轉換為全小寫名稱,因此即使您使用 name=SomeAttribute,您也必須使用 someattributeattributes 集合中擷取屬性的值。

名稱 self (自 Ant 1.6.3 起) 是對 scriptdef 任務執行個體的預先定義參考。可將其用於記錄或與 Ant 的其他部分整合。self.text 屬性包含傳遞給腳本的任何巢狀文字

如果未傳入屬性或元素,則 attributes.get()elements.get() 將傳回 null。腳本必須執行任何檢查和驗證。self.fail(String message) 可用於引發 BuildException

名稱 project 是對 Ant 專案的預先定義參考。如需撰寫腳本的更多資訊,請參閱 <script> 任務。

參數

屬性 說明 必填
name 使用腳本建立的任務名稱
language 腳本編寫的程式語言。必須是支援的 Apache BSF 或 JSR 223 語言
manager 要使用的腳本引擎管理員。請參閱 script 任務以使用此屬性。 否;預設為 auto
src 腳本的位置(作為檔案),如果不在內嵌
encoding 腳本的編碼(作為檔案)。自 Ant 1.10.2 起 否;預設為 JVM 預設字元編碼
compiled 如果為 true,腳本會在第一次評估之前編譯,以加快多次執行,條件是 managerjavax,且目標引擎實作 javax.script.Compilable。請注意,bsf 管理員可能會自動編譯腳本。自 Ant 1.10.2 起 否;預設為 false
uri 此定義應存在的 XML 命名空間 uri。
classpath 傳遞到腳本的類別路徑。
classpathref 要使用的類別路徑,作為 參考 給定其他地方定義的路徑。
loaderRef 用於載入腳本的載入器名稱,由指定的類別路徑建構。這允許多個腳本定義重複使用相同的類別載入器。
setbeans 此屬性控制是否設定執行腳本中所有屬性、參考和目標的變數。如果此屬性為 false,則只設定 projectself 變數。如果此屬性為 true,則設定所有變數。自 Ant 1.10.13 起 否;預設為 false 以維持向後相容性

參數指定為巢狀元素

attribute

屬性 說明 必填
name 屬性的名稱
default 屬性的預設值自 Ant 1.10.13 起

element

屬性 說明 必填
name 由腳本定義的任務支援的巢狀元素名稱
classname 要使用的巢狀元素的類別名稱。這直接指定類別,是指定 Ant 類型名稱的替代方法。
type 這是 Ant 任務或類型的名稱,當要建立此元素時使用。這是直接指定類別名稱的替代方法。如果類型在命名空間中,則必須在類型之前加上 URI 和 :。例如 type=antlib:example.org:newtype

classpath

請參閱 script 任務以使用此巢狀元素。

任何資源集合

自 Ant 1.7.1 起

此任務可以從任何作為巢狀元素提供的資源載入腳本。

範例

下列定義建立一個任務,支援一個稱為 attr 的屬性,以及兩個巢狀元素,一個是檔案組,另一個是路徑。執行時,產生的任務會記錄屬性的值和第一個檔案組的 basedir

<scriptdef name="scripttest" language="javascript">
  <attribute name="attr1"/>
  <element name="fileset" type="fileset"/>
  <element name="path" type="path"/>
  <![CDATA[

    self.log("Hello from script");
    self.log("Attribute attr1 = " + attributes.get("attr1"));
    self.log("First fileset basedir = "
      + elements.get("fileset").get(0).getDir(project));

  ]]>
</scriptdef>

<scripttest attr1="test">
  <path>
    <pathelement location="src"/>
  </path>
  <fileset dir="src"/>
  <fileset dir="main"/>
</scripttest>

下列是上述指令碼的變形,會列出檔案組元素的數量,並逐一執行

<scriptdef name="scripttest2" language="javascript">
  <element name="fileset" type="fileset"/>
  <![CDATA[
    filesets = elements.get("fileset");
    self.log("Number of filesets = " + filesets.size());
    for (i = 0; i < filesets.size(); ++i) {
      self.log("fileset " + i + " basedir = "
        + filesets.get(i).getDir(project));
    }
  ]]>
</scriptdef>

<scripttest2>
  <fileset dir="src"/>
  <fileset dir="main"/>
</scripttest2>

當指令碼有語法錯誤時,scriptdef 名稱會列在錯誤中。例如,在上述指令碼中,移除右大括弧會產生下列錯誤

build.xml:15: SyntaxError: missing } in compound
statement (scriptdef <scripttest2>; line 10)

只有在實際執行 script 任務時,才會偵測到指令碼錯誤。

下一個範例在 Jython 中使用巢狀文字。它也會在新的 XML 名稱空間中宣告指令碼,必須使用此名稱空間來參照任務。在新的名稱空間中宣告指令碼,可確保 Ant 不會建立具有相同 (名稱空間、區域名稱) 名稱對應的任務。

<target name="echo-task-jython">
  <scriptdef language="jython"
             name="echo"
             uri="https://example.org/script">
      <![CDATA[
self.log("text: " +self.text)
      ]]>
    </scriptdef>
</target>

<target name="testEcho" depends="echo-task-jython"
        xmlns:s="https://example.org/script">
  <s:echo>nested text</s:echo>
</target>

下一個範例顯示如何使用 <classpath>loaderref 來存取 beanshell jar。

<scriptdef name="b1" language="beanshell"
           loaderref="beanshell-ref">
  <attribute name="a"/>
  <classpath path="${user.home}/scripting/beanshell/bsh-1.3b1.jar"/>
  self.log("attribute a is " + attributes.get("a"));
</scriptdef>

<scriptdef name="b2" language="beanshell"
           loaderref="beanshell-ref">
  <attribute name="a2"/>
  self.log("attribute a2 is " + attributes.get("a2"));
</scriptdef>

<b1 a="this is an 'a'"/>
<b2 a2="this is an 'a2' for b2"/>

測試指令碼

測試指令碼最簡單的方法是使用 AntUnit Ant 函式庫。這會執行指令碼中所有以 test 開頭的目標 (及其相依性)。