kapok

          垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            455 隨筆 :: 0 文章 :: 76 評論 :: 0 Trackbacks

          http://www.oracle.com/technology/global/cn/pub/articles/bodewig_ant1.6.html

          為大型項(xiàng)目提供的 Ant 1.6 新特性

          作者:Stefan Bodewig

          了解 Ant 1.6 的新特性以及它們?nèi)绾斡绊懩M織編譯過程的方式。

          雖然 Ant 版本的 1.5.x 系列在任務(wù)級方面有很大的改善,但它沒有改變?nèi)藗兪褂?Ant 的方式。而 Ant 1.6 卻有所不同。它增加了幾個(gè)新特性,以支持大型或非常復(fù)雜的編譯情況。但是,要充分利用它們的功能,用戶可能需要稍微調(diào)整它們的編譯過程。

          本文重點(diǎn)介紹了其中的三種新特性 — <macrodef>、<import>、<subant> 任務(wù),表明使用它們可以有什么收獲,以及它們?nèi)绾斡绊懩M織編譯設(shè)置的方式。

          大多數(shù)編譯工程師遲早會面臨必須執(zhí)行相同的任務(wù)組合但在幾個(gè)地方配置稍微有點(diǎn)不同的情況。一個(gè)常見的例子是創(chuàng)建一個(gè)web 應(yīng)用程序存檔,對于開發(fā)系統(tǒng)、測試系統(tǒng)和生產(chǎn)系統(tǒng)有著不同的配置。

          讓我們假設(shè) web 應(yīng)用程序擁有依賴于目標(biāo)系統(tǒng)的不同的 web 部署描述符,并為開發(fā)環(huán)境使用了一個(gè)不同的 JSP 集合以及一個(gè)不同的資料庫集合。配置信息將放在屬性中,創(chuàng)建 web 存檔的任務(wù)看起來將類似于

            <target name="war" depends="jar">
              <war destfile="${war.name}"
                   webxml="${web.xml}">
                <lib refid="support-libraries"/>
                <lib file="${jar.name}"/>
                <fileset dir="${jsps}"/>
              </war>
          </target>
          

          其中 support-libraries 是引用一個(gè)在其它位置定義的 <fileset> ,該引用指向您的應(yīng)用程序所需的附加資料庫的一個(gè)公共集合。

          如果您只想一次創(chuàng)建一個(gè) web 存檔,那么您只需要正確地設(shè)置屬性。比如說,您可以從一個(gè)您的目標(biāo)專有的屬性文件中加載它們。

          利用 Ant 1.5 創(chuàng)建存檔

          現(xiàn)在,假定您想為測試系統(tǒng)和生產(chǎn)系統(tǒng)同時(shí)創(chuàng)建存檔,以確保您真正為兩個(gè)系統(tǒng)打包了相同的應(yīng)用程序。利用 Ant 1.5,您可能使用 <antcall> 來調(diào)用擁有不同屬性設(shè)置的 "war" 目標(biāo),類似:

            <target name="production-wars">
              <antcall target="war">
                <param name="war.name" value="${staging.war.name}"/>
                <param name="web.xml" value="${staging.web.xml}"/>
              </antcall>
              <antcall target="war">
                <param name="war.name" value="${production.war.name}"/>
                <param name="web.xml" value="${production.web.xml}"/>
              </antcall>
          </target>
          

          當(dāng)然,這假定兩個(gè)目標(biāo)系統(tǒng)都將使用相同的 jar 和 JSP。

          但這種方法有一個(gè)主要缺點(diǎn) — 就是速度慢。<antcall> 重新分析編譯文件,并為每一次調(diào)用重新運(yùn)行調(diào)用的目標(biāo)所依賴的所有目標(biāo)。在上面的例子中,"jar" 目標(biāo)將被運(yùn)行兩次。我們希望這對第二次調(diào)用沒有影響,因?yàn)?"war" 目標(biāo)依賴于它。

          利用 Ant 1.6 創(chuàng)建存檔

          使用 Ant 1.6,您可以忘掉用 <antcall> 來實(shí)現(xiàn)宏的方法,相反您可以通過參數(shù)化現(xiàn)有的任務(wù)來創(chuàng)建一個(gè)新的任務(wù)。因而上面的例子將變?yōu)椋?/SPAN>

            <macrodef name="makewar">
              <attribute name="webxml"/>
              <attribute name="destfile"/>
              <sequential>
                <war destfile="@{destfile}"
                     webxml="@{webxml}">
                  <lib refid="support-libraries"/>
                  <lib file="${jar.name}"/>
                  <fileset dir="${jsps}"/>
                </war>
              </sequential>
            </macrodef>
          

          這定義了一個(gè)名稱為 makewar 的任務(wù),該任務(wù)可以和任何其它的任務(wù)一樣使用。該任務(wù)有兩個(gè)必需的屬性,webxml 和 destfile。要使屬性可選,我們必需在任務(wù)定義中提供一個(gè)默認(rèn)值。這個(gè)示例假定 ${jar.name}${jsps} 在編譯期間為常量,從而它們?nèi)匀蛔鳛閷傩灾付āW⒁猓瑢傩栽谑褂萌蝿?wù)時(shí)展開而不是在定義宏的地方展開。

          所用任務(wù)的特性幾乎完全和屬性一樣,它們通過 @{} 而不是 ${} 展開。與屬性不同,它們是可變的,也就是說,它們的值可以(并將)隨著每一次調(diào)用而改變。它們也只在您的宏定義程序塊內(nèi)部可用。這意味著如果您的宏定義還包含了另一個(gè)定義了宏的任務(wù),那么您內(nèi)部的宏將看不到包含的宏的屬性。

          于是新的 production-wars 目標(biāo)將類似于:

            <target name="production-wars">
              <makewar destfile="${staging.war.name}"
                       webxml="${staging.web.xml}"/>
              <makewar destfile="${production.war.name}"
                       webxml="${production.web.xml}"/>
          </target>
          

          這個(gè)新的代碼段不僅執(zhí)行得快一些,而且也更易讀,因?yàn)閷傩悦Q提供了更多的信息。

          宏任務(wù)還可以定義嵌套的元素。<makewar> 定義中的 <war> 任務(wù)的嵌套 <fileset> 可以是這種嵌套元素的一種。可能開發(fā)目標(biāo)需要一些額外的文件或想從不同的位置中挑選 JSP 或資源。以下代碼段將一個(gè)可選的嵌套 <morefiles> 元素添加到了 <makewar> 任務(wù)中

            <macrodef name="makewar">
              <attribute name="webxml"/>
              <attribute name="destfile"/>
              <element name="morefiles" optional="true"/>
              <sequential>
                <war destfile="@{destfile}"
                     webxml="@{webxml}">
                  <lib refid="support-libraries"/>
                  <lib file="${jar.name}"/>
                  <fileset dir="${jsps}"/>
                  <morefiles/>
                </war>
              </sequential>
            </macrodef>
          

          調(diào)用將類似于:

            <makewar destfile="${development.war.name}"
                     webxml="${development.web.xml}">
              <morefiles>
                <fileset dir="${development.resources}"/>
                <lib refid="development-support-libraries"/>
              </morefiles>
            </makewar>
          

          這就像 <morefiles> 的嵌套元素直接在 <war> 任務(wù)內(nèi)部使用的效果一樣。

          即使迄今為止的示例僅顯示了包裝單個(gè)任務(wù)的 <macrodef>,但它不限于此。

          下面的宏不僅將創(chuàng)建 web 存檔,還將確保包含最終存檔的目錄在試圖寫入之前存在。在一個(gè)實(shí)際的編譯文件中,您可能在調(diào)用任務(wù)之前使用一個(gè)設(shè)置目標(biāo)來完成這個(gè)操作。

            <macrodef name="makewar">
              <attribute name="webxml"/>
              <attribute name="destfile"/>
              <element name="morefiles" optional="true"/>
              <sequential>
                <dirname property="@{destfile}.parent"
                         file="@{destfile}"/>
                <mkdir dir="${@{destfile}.parent}"/>
                <war destfile="@{destfile}"
                     webxml="@{webxml}">
                  <lib refid="support-libraries"/>
                  <lib file="${jar.name}"/>
                  <fileset dir="${jsps}"/>
                  <morefiles/>
                </war>
              </sequential>
            </macrodef>
          

          這里注意兩件事情:

          首先,特性在屬性展開之前展開,因此結(jié)構(gòu) ${@{destfile}.parent} 將展開一個(gè)名稱包含了 destfile 特性的值和 ".parent" 后綴的屬性。這意味著您可以將特性展開嵌入到屬性展開中,而不是將屬性展開嵌入特性展開中。

          其次,這個(gè)宏定義了屬性,該屬性的名稱基于一個(gè)特性的值,因?yàn)?Ant 中的屬性是全局的并且不可改變。第一次嘗試使用

                <dirname property="parent"
                         file="@{destfile}"/>
          

          相反將不會在 "production-wars" 目標(biāo)中的第二次 <makewar> 調(diào)用產(chǎn)生期望的結(jié)果。第一次調(diào)用將定義一個(gè)新的名稱為 parent 的屬性,該屬性指向父目錄 ${staging.war.name}。第二次調(diào)用將查看這個(gè)屬性但不會修改它的值。

          預(yù)期 Ant 未來的版本將支持某些類型的限定范圍的屬性,這種屬性只在宏執(zhí)行期間定義。在此之前,使用特性的名稱來構(gòu)建屬性名稱是一種變通辦法,潛在的副作用是要創(chuàng)建大量的屬性。

          提示:如果您查看您的編譯文件時(shí)發(fā)現(xiàn)使用了 <antcall> 代替宏,那么強(qiáng)烈建議您考慮使用 macrodef 將其轉(zhuǎn)換成真正的宏。性能影響可能非常顯著,并且還可能產(chǎn)生更易讀和更易于維護(hù)的編譯文件。
          導(dǎo)入

          將一個(gè)編譯文件分成多個(gè)文件有幾個(gè)原因。

          1. 文件可能變得太大,需要分成幾個(gè)單獨(dú)的部分,以便更易于維護(hù)。
          2. 您有某個(gè)功能集是多個(gè)編譯文件公用的,您想共享它。

          共享公用功能/在 Ant 1.6 之前包含文件

          在 Ant 1.6 之前,您唯一的選擇是實(shí)體包含的 XML 方法,類似于:

            <!DOCTYPE project [
                <!ENTITY common SYSTEM "file:./common.xml">
            ]>
            
            <project name="test" default="test" basedir=".">
            
              <target name="setup">
                ...
          </target>
            
              &common;
            
              ...
            
          </project>
          

          摘自 Ant 常見問題解答。

          這種方法有兩個(gè)主要的缺點(diǎn)。您不能使用 Ant 屬性指向您想包含的文件,因此被迫在您的編譯文件中對位置進(jìn)行硬編碼。您想包含的文件只是一個(gè) XML 文件的一部分,它可能沒有一個(gè)根元素,因而使用支持 XML 的工具進(jìn)行維護(hù)更加困難。

          共享公用功能/使用 Ant 1.6 包含文件

          Ant 1.6 自帶了一個(gè)名稱為 import 的新任務(wù),您現(xiàn)在可以使用它。上面的示例將變?yōu)?/SPAN>

            <project name="test" default="test" basedir=".">
            
              <target name="setup">
                ...
          </target>
            
              <import file="common.xml"/>
            
              ...
            
          </project>
          

          因?yàn)樗且粋€(gè)任務(wù),因此您可以使用 Ant 所有的特性來指定文件位置。主要的差異是被導(dǎo)入的文件本身必須是一個(gè)有效的 Ant 編譯文件,因而必須有一個(gè)名稱為 project 的根元素。如果您想從實(shí)體包含轉(zhuǎn)換到導(dǎo)入,那么您必須在導(dǎo)入的文件的內(nèi)容首尾放上 <project> 標(biāo)記;然后 Ant 將在讀取文件時(shí)再次劃分它們。

          注意文件名稱由 Ant 任務(wù)根據(jù)編譯文件的位置(而不是指定的基本目錄)確定。如果您沒有設(shè)置項(xiàng)目的 basedir 屬性或?qū)⑵湓O(shè)為 ".",那么您將不會注意到任何差異。如果您需要根據(jù)基本目錄解析一個(gè)文件,那么您可以使用一個(gè)屬性作為變通辦法,類似于:

            <property name="common.location" location="common.xml"/>
            <import file="${common.location}"/>
          

          屬性 common.location 將包含文件 common.xml 的絕對路徑,并已根據(jù)導(dǎo)入項(xiàng)目的基本目錄解析。

          使用 Ant 1.6,所有的任務(wù)都可能放在目標(biāo)之外或之內(nèi),除了兩個(gè)例外。<import> 一定不能嵌入到目標(biāo)中,<antcall> 一定不能在目標(biāo)外使用(否則它將創(chuàng)建一個(gè)無限循環(huán))。

          而 <import> 可做的不僅僅是導(dǎo)入另一個(gè)文件。

          首先,它定義了名稱為 ant.file.NAME 的特殊屬性,其中 NAME 替換為每一個(gè)導(dǎo)入文件的 <project> 標(biāo)記的名稱屬性。這個(gè)屬性包含了導(dǎo)入文件的絕對路徑,導(dǎo)入文件可用來根據(jù)它自己的位置(而不是導(dǎo)入文件的基本目錄)定位文件和資源。

          這意味著 <project> 的名稱屬性在 <import> 任務(wù)環(huán)境中變得更加重要。它還用來為在被導(dǎo)入的編譯文件中定義的目標(biāo)提供別名。如果導(dǎo)入了以下文件

          <project name="share">
              <target name="setup">
                <mkdir dir="${dest}"/>
          </target>
          </project>
          

          導(dǎo)入編譯文件可以查看作為 "setup" 或 "share.setup" 的目標(biāo)。后者在目標(biāo)覆蓋的上下文中變得非常重要。

          讓我們假定有一個(gè)包含了多個(gè)獨(dú)立的組件(每個(gè)組件擁有它自己的編譯文件)的編譯系統(tǒng)。這些編譯文件幾乎相同,因此我們決定將公用功能轉(zhuǎn)移到一個(gè)共享和已導(dǎo)入的文件中。為了簡單起見,我們只介紹 Java 文件的編譯和創(chuàng)建結(jié)果的一個(gè) JAR 存檔。共享的文件將類似于

            <project name="share">
              <target name="setup" depends="set-properties">
                <mkdir dir="${dest}/classes"/>
                <mkdir dir="${dest}/lib"/>
          </target>
              <target name="compile" depends="setup">
                <javac srcdir="${src}" destdir="${dest}/classes">
                  <classpath refid="compile-classpath"/>
          </javac>
          </target>
              <target name="jar" depends="compile">
                <jar destfile="${dest}/lib/${jar.name}" basedir="${dest}/classes"/>
          </target>
          </project>
          

          這個(gè)文件不會作為一個(gè)獨(dú)立的 Ant 編譯文件進(jìn)行工作,因?yàn)樗鼪]有定義 "setup" 所依賴的 "set-properties" 目標(biāo)。

          組件 A 的編譯文件可能類似于

            <project name="A" default="jar">
              <target name="set-properties">
                <property name="dest" location="../dest/A"/>
                <property name="src" location="src"/>
                <property name="jar.name" value="module-A.jar"/>
                <path id="compile-classpath"/>
          </target>
              <import file="../share.xml"/>
          </project>
          

          它僅設(shè)置適當(dāng)?shù)沫h(huán)境,然后將全部的編譯邏輯交給被導(dǎo)入的文件負(fù)責(zé)。注意該編譯文件創(chuàng)建了一個(gè)空的路徑作為編譯 CLASSPATH,因?yàn)樗亲园摹DK B 依賴于 A,它的編譯文件將類似于

            <project name="B" default="jar">
              <target name="set-properties">
                <property name="dest" location="../dest/B"/>
                <property name="src" location="src"/>
                <property name="jar.name" value="module-B.jar"/>
                <path id="compile-classpath">
                  <pathelement location="../dest/A/module-A.jar"/>
                </path>
          </target>
              <import file="../share.xml"/>
          </project>
          

          您將注意到該編譯文件與 A 的編譯文件幾乎一樣,因此似乎有可能將大多數(shù)的 set-properties 目標(biāo)也推送到 shared.xml 中。實(shí)際上,我們可以假定有一個(gè)對 dest 和 src 目標(biāo)一致的命名慣例,以實(shí)現(xiàn)這一目的。

            <project name="share">
              <target name="set-properties">
                <property name="dest" location="../dest/${ant.project.name}"/>
                <property name="src" location="src"/>
                <property name="jar.name" value="module-${ant.project.name}.jar"/>
          </target>
          
              ... contents of first example above ...
          </project>
          

          ant.project.name 是一個(gè)內(nèi)置的屬性,它包含了最外面的 <project> 標(biāo)記的名稱屬性的值。因此,如果模塊 A 的編譯文件導(dǎo)入了 share.xml,那么它將擁有值 A。

          注意,所有的文件都與導(dǎo)入編譯文件的基本目錄相關(guān),因此 scr 屬性的實(shí)際值依賴于導(dǎo)入文件。

          為此,A 的編譯文件將簡單地變?yōu)?/SPAN>

          <project name="A" default="jar">
              <path id="compile-classpath"/>
              <import file="../share.xml"/>
          </project>
          

          B 的編譯文件將變?yōu)?/SPAN>

            <project name="B" default="jar">
              <path id="compile-classpath">
                <pathelement location="../dest/A/module-A.jar"/>
              </path>
              <import file="../share.xml"/>
          </project>
          

          現(xiàn)在假定 B 增加了一些 RMI 接口,需要在編譯類之后但在創(chuàng)建 jar 之前運(yùn)行 <rmic>。這就是目標(biāo)覆蓋能派上用場的地方。如果我們在導(dǎo)入編譯文件中定義了一個(gè)目標(biāo),該目標(biāo)與被導(dǎo)入的編譯文件中的一個(gè)目標(biāo)名稱相同,那么將使用導(dǎo)入編譯文件中的目標(biāo)。例如,B 可以使用:

            <project name="B" default="jar">
              <path id="compile-classpath">
                <pathelement location="../dest/A/module-A.jar"/>
              </path>
              <import file="../share.xml"/>
          
              <target name="compile" depends="setup">
                <javac srcdir="${src}" destdir="${dest}/classes">
                  <classpath refid="compile-classpath"/>
          </javac>
                <rmic base="${dest}/classes" includes="**/Remote*.class"/>
          </target>
          </project>
          

          在上面的示例中將使用 "compile" 目標(biāo),而不是 share.xml 中的目標(biāo);然而,不幸的是,這只是從共享那里復(fù)制 <javac> 任務(wù)。一種更好的解決方案是:

            <project name="B" default="jar">
              <path id="compile-classpath">
                <pathelement location="../dest/A/module-A.jar"/>
              </path>
              <import file="../share.xml"/>
          
              <target name="compile" depends="share.compile">
                <rmic base="${dest}/classes" includes="**/Remote*.class"/>
          </target>
          </project>
          

          這只是使 B 的 "compile" 在原來的 "compile" 目標(biāo)使用之后運(yùn)行 <rmic>。

          如果我們想在編譯之前生成一些 Java 源代碼(例如通過 XDoclet),我們可以使用類似下面的方法:

              <import file="../share.xml"/>
          
              <target name="compile" depends="setup,xdoclet,share.compile"/>
              <target name="xdoclet">
                 .. details of XDoclet invocation omitted ..
          </target>
          

          因此您可以完全覆蓋一個(gè)目標(biāo)或通過在原始目標(biāo)之前或之后運(yùn)行任務(wù)來增強(qiáng)它。

          這里要注意一個(gè)危險(xiǎn)。目標(biāo)覆蓋機(jī)制使導(dǎo)入編譯文件依賴于在導(dǎo)入文件中使用的名稱屬性。如果任何人修改了導(dǎo)入文件的名稱屬性,那么導(dǎo)入編譯文件將被破壞。Ant 開發(fā)社區(qū)目前正在討論在 Ant 的一個(gè)未來的版本中為此提供一個(gè)解決方案。

          提示:如果您在編譯文件中發(fā)現(xiàn)了非常常見的結(jié)構(gòu),那么值得嘗試將文件重構(gòu)為一個(gè)(一些)共享文件,并在必要時(shí)使用目標(biāo)覆蓋。這可以使您的編譯系統(tǒng)更加一致,并讓您能夠重用編譯邏輯。
          Subant

          在某種意義上,subant 是兩種任務(wù)合二為一,因?yàn)樗私獠僮鞯膬煞N模式。

          如果您使用 <subant> 的 genericantfile 屬性,那么它的工作方式和 <antcall> 一樣,調(diào)用包含任務(wù)的同一個(gè)編譯文件中的目標(biāo)。與 <antcall> 不同,<subant> 獲取目錄的列表或集合,并將為每一個(gè)目錄調(diào)用一次目標(biāo),以設(shè)定項(xiàng)目的基本目錄。如果您想在任意數(shù)量的目錄中執(zhí)行完全一樣的操作,那么這非常有用。

          第二種模式不使用 genericantfile 屬性,而獲取一個(gè)編譯文件的列表和集合進(jìn)行迭代,以在每一個(gè)編譯文件中調(diào)用目標(biāo)。這種工作方式類似于在一個(gè)循環(huán)中使用 <ant> 任務(wù)。

          第二種形式的典型情景是幾個(gè)能夠獨(dú)立編譯的模塊的一個(gè)編譯系統(tǒng),但是該系統(tǒng)需要一個(gè)主編譯文件來一次性編譯所有的模塊。

          接下來的步驟

          使用以下資源了解關(guān)于 Ant 的更多信息,并開始編譯和部署 Java 項(xiàng)目。

          Ant 業(yè)界趨勢
          對這個(gè)跨平臺編譯工具的形成進(jìn)行幕后觀察

          閱讀關(guān)于 JDeveloper 中的 Ant 集成的更多信息
          Oracle JDeveloper 中的 Ant 集成是通過在 JDeveloper 項(xiàng)目中添加一個(gè) Ant 編譯文件或通過從一個(gè)現(xiàn)有的 JDeveloper 項(xiàng)目中創(chuàng)建一個(gè)新的 Ant 編譯文件來實(shí)現(xiàn)的。

          下載 Oracle JDeveloper 10g
          Oracle JDeveloper 10g 是一個(gè)集成開發(fā)環(huán)境,它提供了對建模、開發(fā)、調(diào)試、優(yōu)化和部署 Java 應(yīng)用程序及 Web 服務(wù)的端到端支持。

          測試驅(qū)動:將 Ant 用于編譯
          這個(gè) viewlet 演示了已擁有 Ant 項(xiàng)目的用戶如何能夠在 JDeveloper 內(nèi)部使用這些項(xiàng)目。

          Ant 入門第 1 部分
          這里開始將這個(gè)非常有用的工具用于構(gòu)建和部署 Java 項(xiàng)目。本文介紹了您可能在 Java 開發(fā)過程期間執(zhí)行的一些基本的 Ant 任務(wù)。

          Ant 入門第 2 部分
          這里是我們的系列中的第 2 部分,這個(gè)系列介紹用于構(gòu)建和部署 Java 項(xiàng)目的一個(gè)非常有用的工具。本文討論在 Ant 的兩個(gè)任務(wù)程序包(核心的任務(wù)程序包和可選的任務(wù)程序包)中提供的一些 Ant 的更高級的特性。

          在 Linux 上創(chuàng)建 Java 應(yīng)用程序的命令行方法
          本文可用作使用 Ant 在 Linux 上開發(fā)和部署 Java 客戶端應(yīng)用程序的一個(gè)不錯(cuò)的上機(jī)操作指南。

          閱讀關(guān)于 Ant 的更多信息
          訪問官方 Apache Ant 站點(diǎn),獲取更多的項(xiàng)目詳細(xì)信息。

          相關(guān)文章與下載

          Blog:到 OC4J 的 Ant 部署

          Blog: 如何從一個(gè) JDeveloper 項(xiàng)目文件中將屬性動態(tài)檢索到一個(gè) ant 編譯文件中?

          Viewlet:將 CVS 用于軟件配置

          在 Ant 1.6 之前構(gòu)建主編譯文件

          在導(dǎo)入部分中討論的例子使用了這樣一個(gè)主編譯文件。

            <target name="build-all">
              <ant dir="module-A" target="jar"/>
              <ant dir="module-B" target="jar"/>
          </target>
          

          在 Ant 1.6 之前的 Ant 中。

          使用 Ant 1.6 構(gòu)建主編譯文件

          在 Ant 1.6 中使用 <subant>,這可以重寫為

           
            <target name="build-all">
              <subant target="jar">
                <filelist dir=".">
                  <file name="module-A/build.xml"/>
                  <file name="module-B/build.xml"/>
                </filelist>
              </subant>
          </target>
          

          這看起來并沒有很大的改善,因?yàn)槟匀槐仨殕为?dú)指定每一個(gè)子編譯文件。相反如果您轉(zhuǎn)用 <fileset>,那么情況將有所改觀。

            <target name="build-all">
              <subant target="jar">
                <fileset dir="." includes="module-*/build.xml"/>
              </subant>
          </target>
          

          這將自動發(fā)現(xiàn)所有模塊的編譯文件。如果您增加了一個(gè)模塊 C,主編譯文件中的目標(biāo)不需要修改。

          但小心。與 <filelist> 或 <path>(也被 <subant> 支持)不同,<fileset> 是無序的。在我們的例子中,模塊 B 依賴于模塊 A,因此我們需要確保首先編譯模塊 A,而使用 <fileset> 沒有辦法這么做。

          如果編譯完全彼此獨(dú)立或者它們對于一個(gè)給定的操作彼此獨(dú)立,那么 <fileset> 仍然有用。模塊 B 的文檔目標(biāo)可能完全不依賴于模塊 A,同樣還有從您的 SCM 系統(tǒng)中更新源代碼的目標(biāo)。

          如果您想將編譯文件的自動發(fā)現(xiàn)與根據(jù)編譯的相互依賴性對編譯進(jìn)行排序結(jié)合在一起,那么您將必須編寫一個(gè)定制的 Ant 任務(wù)。基本的想法是編寫一個(gè)使用 <fileset> 的任務(wù)(讓我們目前稱之為 <buildlist>),確定依賴關(guān)系并計(jì)算 <subant> 必須使用的順序。然后它創(chuàng)建一個(gè)以正確的順序包含編譯文件的 <path>,然后將對這個(gè)路徑的一個(gè)引用放到項(xiàng)目中。調(diào)用將類似于

            <target name="build-all">
              <buildlist reference="my-build-path">
                <fileset dir="." includes="module-*/build.xml"/>
              </buildlist>
              <subant target="jar">
                <buildpath refid="my-build-path"/>
              </subant>
          </target>

          這個(gè)假想的 buildlist 任務(wù)已經(jīng)在 Ant 用戶郵件列表和 bug 跟蹤系統(tǒng)中進(jìn)行了討論。很有可能 Ant 的一個(gè)將來的版本中將包含這樣的一個(gè)任務(wù)。

          在 Ant 1.6 中已經(jīng)增加了大量的新特性。這些新功能中的許多功能使得編譯模板易于創(chuàng)建、構(gòu)造和定制。特別是 <import> 和 <target> 進(jìn)行了覆蓋。<import>、<macrodef> 和 <subant> 特性很有可能使得 Ant 編譯可高度重用。<scriptdef>(本文中未討論)對于需要一些腳本但不想用 Java 編寫定制任務(wù)的人而言可能非常有吸引力。

          posted on 2005-06-14 12:22 笨笨 閱讀(694) 評論(0)  編輯  收藏 所屬分類: J2EEHibernateAndSpringALLAppFuse
          主站蜘蛛池模板: 康乐县| 青州市| 盈江县| 若羌县| 昂仁县| 长葛市| 岢岚县| 贵定县| 镇雄县| 文水县| 石台县| 依安县| 图们市| 绍兴市| 孙吴县| 石河子市| 修文县| 阳山县| 南部县| 漯河市| 深水埗区| 长顺县| 黄骅市| 河池市| 裕民县| 昌平区| 永顺县| 玉溪市| 门头沟区| 运城市| 天门市| 双桥区| 长治县| 休宁县| 辽宁省| 滨海县| 玉田县| 高碑店市| 屏东县| 康乐县| 岳阳县|