-. Ant簡介
Ant是一款類似make的工具,用來編譯/運行/打包Java程序。在構建、包裝和發佈過程中幾乎每一件事都可以由Ant的任務來處理。
二.搭建ANT運行環境
1、將ant1.6.1解壓縮到任意目錄,假設解壓縮到C:/apache-ant-1.6.1目錄中
2、然後在path路徑中添加 C:/apache-ant-1.6.1/bin
3、再classpath中添加 C:/apache-ant-1.6.1/lib
三、ANT的組成(主要由三部分組成:Project、Target、Task)
1、Project(項目)。基本屬性:name、default、basedir。一個build.xml只能存在一個Project工程。
name :項目名稱
default :缺省開始執行的Target
basedir :用於計算所有其他路徑的基路徑。
例1:<project name="dev" basedir="." default="dist">
2、Target。一個項目可以定義一個或多個Target、一個Target是一系列你想要執行的任務,如編譯任務、打包任務、混淆任務。
Target的基本屬性: name:target的名字,depends:該target依賴關係,description: target的描述信息。
例2:<target name="clean" depends="init" description="Clean dist and temp directories">
Ant在執行時以Target爲單位,Target的depends屬性又決定了哪個Target先執行,因此我們可以通過Target來構造編譯順序。
例3:<target name="copy" >
<target name="javac" depends="copy">
<target name="jar" depends="javac">
執行順序是從下至上,依次執行,如果某個Target沒有depends屬性,那麼就順序執行。
例4:一個完整的Target:
<target name="compile" depends="replacesrc" description="Compiling Java source files">
<javac srcdir="temp/src"
destdir="temp/build"
debug="on"
deprecation="false"
optimize="true">
<classpath refid="classpath"/>
</javac>
</target>
3、Task。Ant執行的一系列任務是由Target構成的,而Target又是由數個小的Task構成的,task任務是最小的運行單位,我們可以把copy、delete、mkdir等操作認爲是一個小任務。
(1)copy任務。
A.拷貝單個文件:
<copy file="Demo/manifest.mf" todir="temp/build/META-INF" />
解釋:把一個文件拷貝到拷貝相關文件夾中。
B.拷貝文件夾:
<copy todir="temp/build">
<fileset dir="temp/classes"/>
</copy>
解釋:把temp/build目錄下的所有文件,拷貝到temp/classes目錄中去
C.替換拷貝
<copy todir="temp/build">
<fileset dir="temp/classes" includes="*.class" />
<filterset>
<filter token="@Time@" value="${app.time}"/>
</filterset>
</copy>
解釋: <filterset>過濾集,可以將temp/classes文件夾下的存在@Time@標記的文件,替換爲變量${app.time}值。這樣在完成拷貝的同時也完成了替換任務。
(2)mkdir任務和delete任務
A.單獨的delete和mkdir任務
<delete dir="temp/src"/>
<delete file="temp/build/Thumbs.db" />
<mkdir dir="temp/src"/>
B. 帶有條件的刪除任務
<delete>
<fileset dir="store" includes="*.*"/>
<fileset dir="source" excludes="*.java"/> </delete>
解釋:include表示要刪除哪些文件;而excludes表示排除的文件;
(3)replace替換任務
A.替換某一文件中的字符串
<replace file ="base/testing.txt">
token="@temp@"
value="${newstring}"
</replace>
解釋:token是需要替換的標記;value是新值,將testing.txt文件中的@temp@替換爲新值。
B.替換某個文件夾中存在特定標記的文件
<replace dir="temp" token="@CHARSET@" value="${webapp.charset}"/>
解釋:temp目錄中文件,如果有存在@CHARSET@標記的,將被替換爲${webapp.charset}變量值。
C.批量替換
<replace dir="dist" includes="${app.project}.jad" encoding="UTF-8">
<replacefilter token="@NAME@" value="${app.name}"/>
<replacefilter token="@VENDOR@" value="${app.vendor}"/>
<replacefilter token="@MIDLET@" value="${app.midlet}"/>
<replacefilter token="@JAR@" value="${app.project}"/>
<replacefilter token="@FILESIZE@" value="${size}"/>
<replacefilter token="@DESCRIPTION@" value="${app.description}"/> <replacefilter token="@PRICE@" value="${app.price}"/>
</replace>
(4) javac任務 ,編譯源程序
<target name="Compile" description="Compile Java source files">
<javac srcdir="src" destdir="temp/classes" bootclasspath="${compile.classpath}" target="1.1" debug="on" deprecation="on" includes="*.java" optimize="true" encoding="UTF-8"/>
</target>
解釋:bootclasspath參數(啓動類庫):它已經包含了jre/lib目錄下的rt.jar,以及我們自定義的類庫。如果使用classpath參數,僅指我們定義的類庫;
(5) java任務 。爲運行Java應用程序,需要使用java任務
A.運行一個類
<target name="run" description="Run the program">
<java classname="${main}" classpath="${classpath}"/>
</target>
解釋:classname表示要運行的主類。
B.運行某一特定類,並加上運行參數。
<java fork="true" classname="proguard.ProGuard" classpath="${proguard.classpath}">
<arg line="-libraryjars ${proguard.classpath}"/>
<arg line="-injars temp/${app.project}_tmp.jar"/>
<arg line="-outjar temp/${app.project}_obf.jar"/>
<arg line="-defaultpackage ''"/>
<arg line="-dontusemixedcaseclassnames"/>
<arg line="-keep public class ${app.midlet}"/>
</java>
解釋:fork參數:爲true時,在新的JVM實例中運行,不影響當前JVM工作
如何減少文件的size?
使用3.3.2版本的proguard.jar,然後在混淆參數中添加兩行代碼:
<arg line = "-overloadaggressively"/>
<arg line="-keepclasseswithmembers public class ${app.midlet} {public void startApp();public void destroyApp(boolean);}"/>
這樣可以保證startApp和destroyApp不被打上Final修飾符,同時還能更大的壓縮代碼,不過要求Midlet類中startApp和destroyApp方法保持上面的形式。
(6)JAR任務
將編譯好的CLASS文件打成JAR包,這是JAR任務的工作:
<target name="jar" depends="Compile" description="Build jar file">
<jar jarfile="dist/${name}.jar" basedir="${tmp/class}" manifest="tmp/res/manifest.mf" manifestencoding="UTF-8">
<fileset dir="res" includes="*.*"/> <!-- 將res目錄中的文件也打進JAR包 -->
</jar>
</target>
(7)exec任務,用以調用外部程序
<exec executable="${LIB_PATH}/preverify.exe">
<arg line="-classpath ${compile.classpath} -d temp/build temp/obfuscate"/>
</exec>
四、ANT的參數部分:
-quiet(不顯示大多數build信息)
-verbose(顯示構建過程的每個操作的詳細信息)
-buildfile filename.xml 構建特定的xml文件
-Dproperty=value 設定特別的外部參數,外部參數可以傳遞給內部變量
-find filename.xml 它會讓ANT自動查找當前的目錄、父目錄中的xml文件,直到失敗
例:
ant -buildfile test.xml
使用當前目錄下的test.xml運行Ant
ant -buildfile test.xml dist
使用當前目錄下的test.xml運行Ant,執行一個叫做dist的target。
ant -buildfile test.xml -Dbuild=build/classes dist
使用當前目錄下的test.xml運行Ant,執行一個叫做dist的target,並設定build變量的值爲build/classes。
五、自定義TASK
ANT已經內置了不少task,像copy、replace、javac等等,但是有時候還需要一些特定的任務來完成操作,比如在生成JAD文件時,需要一個Midlet-Jar-Size的參數,得到JAR文件的大小,但是通過內部的task無法實現,因此可以自己編寫類來實現此功能,但必須保證該類是從Task類繼承過來的。
例:
<taskdef name="filesize" classname="ant.FileSizeTask" classpath="${LIB_PATH}/FileSizeTask.jar" />
<filesize file="${Base}/Demo_Build/${jarName}" property="size" />
<replace dir="store" includes="${jadName}" encoding="UTF-8">
<replacefilter token="@FILESIZE@" value="${size}" />
</replace>
解釋:taskdef:自定義任務,name:任務名
編寫Ant 自定義任務很簡單,Ant 能夠使用生成文件中指定的對應屬性的值來調用這個方法,這個方法的名稱需要是 set 加上屬性的名稱,因此在下面的例子中,我們需要名爲 setFile() 和 setTofile() 的兩個方法。
當 Ant 遇到生成文件中的一個屬性設置時,它會尋找相關任務中具有適當名稱的方法(稱爲 setter 方法)。
生成文件中的屬性是作爲字符串來指定的,因此我們的 setter 方法的參數可以是一個字符串。在這樣的情況下,Ant 將在展開值所引用的任何屬性之後,使用該屬性的字符串值來調用我們的方法。
但有時我們想把屬性的值看作是一種不同的類型。這裏的示例任務就是這種情況,其中的屬性值引用文件系統上的文件,而不只是引用任意的字符串。可以通過將方法參數聲明爲 java.io.File 類型來容易地做到這點。
Ant 將接受屬性的字符串值,並把它解釋爲一個文件,然後傳遞給我們的方法。Ant 能夠對其他類型執行類似的轉換,比如 boolean 和 int 類型。但如果提供具有相同名稱但是具有不同參數的兩個方法,Ant 將使用更明確的那一個方法,因此文件類型將優先於字符串類型。
例:一個排序的task任務
使用這個自定義任務:
<taskdef name="filesorter" classname=" FileSorter" classpath="filesorter"/>
<target name="main">
<filesorter file="input.txt" tofile="output.txt"/>
</target>
解釋:file和tofile分別是程序入口、出口。