1. 程式人生 > >用Ant來打包

用Ant來打包

Eclipse 內建了 Ant 。 Ant 是一種類似於批處理程式的軟體包,它主要繁瑣的工作是編寫和除錯自動處理指令碼(一個 XML 檔案),但只要有了這個指令碼,我們就可以一鍵完成所有的設定工作。 本節還是以 myswt 這個應用程式專案的打包為例,用 Ant 來完成“編譯->打成 JAR 包->複製專案引用庫->複製本地化檔案 swt-win32-3063.dll ->輸出 API 文件”這五步。 1 、在 myswt 專案根目錄下,建立最主要的 build.xml 檔案 <?xml version=1.0?> <project name=myswt project default=api_doc>     <!-- 定義目錄變數 -->     <property name=src.dir value=src />     <property name=bin.dir value=bin />     <property name=eclipse_plugins.dir value=c:/eclipse/plugins />     <property name=dist.dir value=d:/dist />     <property name=doc.dir value=${dist.dir}/api />     <property name=swt.dll value=swt-win32-3063.dll />     <!-- 定義編譯檔案時所引用的庫 -->     <path id=master-classpath>         <fileset dir=${eclipse_plugins.dir} id=project_lib>             <include name=org.eclipse.ui.workbench_3.0.1/workbench.jar/>             <include name=org.eclipse.swt.win32_3.0.1/ws/win32/swt.jar/>             <include name=org.eclipse.jface_3.0.0/jface.jar/>             <include name=org.eclipse.osgi_3.0.1/osgi.jar/>             <include name=org.eclipse.osgi_3.0.1/core.jar/>             <include name=org.eclipse.osgi_3.0.1/resolver.jar/>             <include name=org.eclipse.osgi_3.0.1/defaultAdaptor.jar/>             <include name=org.eclipse.osgi_3.0.1/eclipseAdaptor.jar/>             <include name=org.eclipse.osgi_3.0.1/console.jar/>             <include name=org.eclipse.core.runtime_3.0.1/runtime.jar/>             <include name=org.eclipse.jface.text_3.0.1/jfacetext.jar/>             <include name=org.eclipse.ui.workbench.compatibility_3.0.0/compatibility.jar/>         </fileset>     </path>     <!-- 首任務(空) -->     <target name=init/>     <!-- 編譯 -->     <target name=compile depends=init>         <delete dir=${bin.dir}/>         <mkdir dir=${bin.dir}/>         <!-- 編譯源程式 -->         <javac srcdir=${src.dir} destdir=${bin.dir} target=1.4>             <classpath refid=master-classpath/>         </javac>         <!-- 複製圖示目錄 -->         <mkdir dir=${bin.dir}/icons/>         <copy todir=${bin.dir}/icons>             <fileset dir=icons/>         </copy>     </target>     <!-- 打包 -->     <target name=pack depends=compile>         <!-- bin 目錄壓縮成 JAR 包 -->         <delete dir=${dist.dir}/>         <mkdir dir=${dist.dir} />         <jar basedir=${bin.dir} destfile=${dist.dir}/myswt.jar manifest=ant_manifes.txt>             <exclude name=**/*Test.* />             <exclude name=**/Test*.* />         </jar>         <!-- 複製用到的庫 -->         <mkdir dir=${dist.dir}/lib />         <copy todir=${dist.dir}/lib>             <fileset refid=project_lib/>         </copy>         <!-- 複製本地化檔案 -->         <copy todir=${dist.dir} file=${swt.dll}/>     </target>     <!-- 輸出 api 文件 -->     <target name=api_doc depends=pack>         <delete dir=${doc.dir}/>         <mkdir dir=${doc.dir} />         <javadoc destdir=${doc.dir} author=true version=true use=true windowtitle=MySWT API>             <packageset dir=${src.dir} defaultexcludes=yes/>             <doctitle><![CDATA[<h1>MySWT Project</h1>]]></doctitle>             <bottom><![CDATA[<i>Document by ChenGang 2005.</i>]]></bottom>         </javadoc>     </target> </project> 程式碼說明: ( 1 ) property 項是定義變數,比如 <property name=swt.dll value=swt-win32-3063.dll /> ,就是定義一個變數: swt.dll=swt-win32-3063.dll 。以後用這個變數則是這樣: ${swt.dll} 。 一般儘量將今後可能會變動的目錄、檔案等定義成變數,以方便維護。不象 Java 變數有型別的區分, Ant 變數是不區別目錄、檔案等的,所以為了見名知意,在取變數名時,目錄都加“ dir ”字尾,這個字尾是可以任取名的。 下面給出本例用到的變數的含義: l            src.dir - Java 原始檔路徑。 value=src 的 src 是一個相對路徑,它相對的是 build.xml 的所在目錄位置(即專案根目錄)。 l            bin.dir - Java 編譯檔案的輸出路徑 l            eclipse_plugins.dir - eclipse 的 plugins 目錄 l            dist.dir - 打包檔案的存放目錄 l            doc.dir - API 文件的存放目錄,這裡用到了 dist.dir 變數,直接寫 value=d:/dist/api 也未嘗不可。 l            swt.dll - SWT 本地化檔案。 ( 2 ) <path id=master-classpath> ,定義編譯檔案時所引用的庫,相當於 classpath 。 <fileset> 項表示一個檔案集,再深入一層的 <include> 項,則表示此檔案集下的檔案,它們的路徑定位相對於 <fileset> 的 dir 屬性。 <fileset> 還有一個 id 屬性,在後面複製引用庫時會用到。 也許有讀者會問:“你是怎麼知道要引用這些檔案的?”回答:看專案根目錄下的“ .classpath ”檔案,就可以知道本專案要引用那些庫了。實際上筆者是把 .classpath 複製一份後,然後用 Editplus 編輯而得。 ( 3 )接下來開始定義一些任務。首任務一般都讓它為空(沒有具體任務內容): <target name=init/> 。 ( 4 ) Ant 中的任務有著相互的依賴( depends )關係,這些依賴關係是通過 depends 屬性來定義的。當要執行一個任務時, Ant 先去執行這個任務的 depends 任務,……, Ant 就這樣一直往回找下去。比如:在本例的第二行 default=api_doc ,它定義了預設任務是 api_doc (輸出 api 文件)->此任務的 depends = pack (打包)-> pack 的 depends = compile (編譯)-> compile 的 depends=init (首任務), init 沒有 depends 。於是, Ant 就從 init 開始依次往回執行任務: init -> compile -> pack -> api_doc 。 如果你不想“輸出 api 文件”,則將第二行的預設任務定義成 default=pack 即可,這時整個任務鏈就拋開了 api_doc 。 ( 5 ) <delete dir=${bin.dir}/> 刪除目錄。 <mkdir dir=${bin.dir}/> 新建目錄 ( 6 )編譯源程式,如下 <javac srcdir=${src.dir} destdir=${bin.dir} target=1.4>     <classpath refid=master-classpath/> </javac> l            srcdir - 原始檔目錄,其子目錄中的原始檔也會被 javac.exe 編譯。 l            destdir - 編譯檔案輸出目錄。 l            target - 以 JDK1.4 為編譯目標。 l            classpath - 編譯的 classpath 設定, refid 是指引用前面設定的 master-classpath 。 ( 7 )將 icons (即 myswt/icons )目錄的檔案,複製到 myswt/bin/icons 目錄中,如下: <copy todir=${bin.dir}/icons>     <fileset dir=icons/> </copy> ( 8 )將檔案打成 JAR 包 <jar basedir=${bin.dir} destfile=${dist.dir}/myswt.jar manifest=ant_manifes.txt>     <exclude name=**/*Test.* />     <exclude name=**/Test*.* /> </jar> l            basedir - 源目錄。 l            destfile - 目標目錄和打成 JAR 包名。 l            manifest - 打包清單檔案(後面給出其內容)。 l            exclude - 使用了萬用字元將某一些檔案排除不打包(主要是一些測試檔案)。 ( 9 )如下,將 project_lib 的檔案複製到 d:/dist/lib 目錄中。 project_lib 是前面“定義編譯檔案時所引用的庫”中的檔案集的 id 。結果引數下圖 21.25 <copy todir=${dist.dir}/lib>     <fileset refid=project_lib/> </copy> ( 10 )將本地化檔案複製到 d:/dist 目錄中,如下: <copy todir=${dist.dir} file=${swt.dll}/>  ( 11 )輸出 API 文件(結果引數下圖 21.26 ) <javadoc destdir=${doc.dir} author=true version=true use=true windowtitle=MySWT API>     <packageset dir=${src.dir} defaultexcludes=yes/>     <doctitle><![CDATA[<h1>MySWT Project</h1>]]></doctitle>     <bottom><![CDATA[<i>Document by ChenGang 2005.</i>]]></bottom> </javadoc> l            destdir - 目標路徑 d:/dist/api l            packageset - 原始檔目錄 l            doctitle - 標題 l            bottom - 標尾。 2 、建立打包清單 為了避免和原來的 manifes.txt 同名,在專案根目錄建立一個名為 ant_manifes.txt 的檔案。這個檔案內容中最長的是 Class-Path 項,沒有必要一個個字元的敲入,它可以由專案根目錄下的“ .classpath ”編輯而得。 ant_manifes.txt 內容如下: Manifest-Version: 1.0 Main-Class: jface.dialog.wizard.WizardDialog1 Class-Path: ./lib/org.eclipse.ui.workbench_3.0.1/workbench.jar ./lib/org.eclipse.swt.win32_3.0.1/ws/win32/swt.jar
./lib/org.eclipse.jface_3.0.0/jface.jar ./lib/org.eclipse.osgi_3.0.1/osgi.jar ./lib/org.eclipse.osgi_
3.0.1/core.jar ./lib/org.eclipse.osgi_3.0.1/resolver.jar ./lib/org.eclipse.osgi_3.0.1/defaultAdaptor.ja
r ./lib/org.eclipse.osgi_3.0.1/eclipseAdaptor.jar ./lib/org.eclipse.osgi_3.0.1/console.jar ./lib/org.ecl
ipse.core.runtime_3.0.1/runtime.jar ./lib/org.eclipse.jface.text_3.0.1/jfacetext.jar ./lib/org.eclipse.u
i.workbench.compatibility_3.0.0/compatibility.jar 3 、如下圖 21.23 所示,選擇“ Ant 構建”來執行 Ant 。
圖 21.23  執行“ Ant 構建” 執行“ Ant 構建”後的結果如下圖 21.23 - 26 所示。 圖 21.24  控制檯的輸出 圖 21.25  輸出檔案的目錄結構圖 圖 21.26  輸出的 API 文件效果圖 4 、執行打包結果 除了清單檔案 MANIFEST.MF 之外, myswt.jar 檔案和 21.1 節所得的 myswt.jar 一樣。本節沒有建立 run.bat 批處理檔案,而是用下圖 21.27 所示的“右擊 myswt.jar ->開啟方式-> javaw ”的方式來執行 myswt.jar 。 圖 21.27  執行 myswt.jar