內容:
-. Ant簡介
二.Ant的安裝及配置
三:用ant管理enhydra項目
四:小技巧
參考文獻
個人簡介
宗鋒 (zong_feng@263.net)
西北大學計算機系碩士研究生
2001 年 7 月
本文描述了ant的基本語法及其如何應用于enhydra項目的管理
-. Ant簡介
可能有許多讀者并不了解什么是ant,以及如何使用它。但只要你是用過linux,你應該知道make為何物,當我們編譯linux內核及一些軟件的源程序時,我們經常需要在控制臺下輸入make。Make其實就是一個項目管理工具,而ant所實現的功能與make差不多。Ant是apache軟件基金會jakarta項目中的一個子項目,由于是基于java編寫的,因此具有很好的跨平臺性。Ant由一些內置任務(task)和可選擇的任務組成(當然你還可以編寫自己的任務),使用Make時,你需要寫一個Makefile文件,而用ant時則需要寫一個build.xml文件。由于采用xml的語法,所以build.xml文件很容易書寫和維護,且結構很清晰,而不像Makefile文件有那么多的限制(例如在tab符號前有一個空格的話,命令就不會執行)。Ant的優點遠不止這些,它還很容易的集成到一些開發環境中(例如visual age,jbuilder,netbeans)。
二.Ant的安裝及配置
安裝
Ant目前的版本是1.3,首先到http://jakarta.apache.org/ant/index.html下載ant最新版本1.3,解壓到C:/ant(window操作系統) 或者/usr/local/ant(linux操作系統),由于我們要用到xmlc ,而ant1.3中并沒有包含它,所以我們需要David.Li為ant寫的xmlc任務。具體url為http://www.digitalsesame.com/enhydra/EnhydraAnt20001213.tar.gz。將下載后的文件中的ant.jar替換掉ant1.3中ant.jar.這樣ant的版本變為1.2.
2.設置路徑
(1):windows98操作系統
編輯C:\enhydra\.bashrc,加入下面三行
export ANT_HOME=/ant
export JAVA_HOME=/jdk-1.2.2
export PATH=${PATH}:${ANT_HOME}/bin
(2):Linux操作系統
編輯/etc/profile或者 用戶目錄下的.bashrc文件,加入下面三行
export ANT_HOME=/usr/local/ant
export JAVA_HOME=/usr/local/jdk-1.2.2
export PATH=${PATH}:${ANT_HOME}/bin
三:用ant管理enhydra項目
1:基本的文件目錄結構
enhydra這里不必多介紹了,要想了解它可以到http://www.linuxaid.com.cn/ 和http://www.cn.ibm.com/developerWorks/linux/sdk/ant/www.linuxforum.net上讀一些與此相關的文章。
我們以David.Li寫的AntDemo項目作為示例來講述怎樣用ant管理enhydra項目,首先下載此示例,url為http://www.digitalsesame.com/enhydra/AntDemo.tar.gz,解壓到任意目錄,我們可以看到目錄樹結構如下
在這個目錄樹結構中,與傳統的enhydra 項目不同的是,我們用build.xml取代了Makefile,在講述這個build.xml文件前,我們先了解一個基本的 build.xml文件的結構。
2:build.xml的基本書寫規范
下面我們就來講述這個文件的書寫方法,下面是這個文件的全部內容
1.<?xml version="1.0"?>
2.<project name="MyProject" default="dist" basedir=".">
3.<property name="dist" value="dist"/>
4.<target name="init">
5.<mkdir dir="${dist}"/>
6.</target>
7.</project>
為了方便說明,我們為每一行加了行號,第一行是xml文件的基本要素,第二行說明這是一個項目,第七行說明項目的結束 ,在第二行中,name="MyProject"說明此項目的名稱,這個屬性可有可無。basedir="."說明基本目錄,此屬性可有可無。default="dist"說明項目的缺省目標(target)是什么,這個屬性必須有。所謂目標(target)就是一系列任務(task)組成的一個集合。每個任務(task)的書寫方法如下:
<任務名 屬性1="屬性1的值" 屬性2="屬性2的值" ....... />
第三行定義了一些屬性(property),以便后面使用,這非常類似于編程中定義的全局變量。從第四行開始定義目標(target),name="init"指明了此目標的名稱,name屬性在定義目標時必須有,當然定義目標時還有其他一些屬性可選,例如depends,unless,具體請參考ant的文檔。第五行開始定義此目標內的任務,其中mkdir時ant的內部任務名,dir是此任務的屬性,其值為${dist}。此任務就是創建一個目錄。其中${dist}是獲取dist屬性的值(就是我們在第三行定義的)。如上就是一個基本的build.xml文件的寫法。你可以在命令行上輸入 ant -buildfile build.xml
看一下你的當前目錄下是否多了一個dist目錄。如果出錯,則可能是你沒有把ant配置好,參見前面講的安裝及配置,看一下哪兒出了錯。
3:build.xml文件
build.xml文件如下,其中有的注釋和無關的代碼刪掉了,且做了一下小小的改動
1:<?xml version="1.0"?>
2: <project default="app" basedir=".">
3:<!-- 加入 xmlc 任務-->
4:<taskdef name="xmlc"classname="org.apache.tools.ant.taskdefs.optional.enhydra.Xmlc"/>
5:<!-- =================================================================== -->
6:<!-- 設置編譯的類路徑 -->
7:<!-- =================================================================== -->
8:<path id="build.classpath">
9:<pathelement path="${build.classes}"/>
10:</path>
11:<!-- =================================================================== -->
12:<!-- 初始化基本屬性 -->
13:<!-- =================================================================== -->
14:<target name="init">
15:<!-- Set up application info -->
16:<property name="app.Name" value="AntDemo"/>
17:<property name="app.name" value="antDemo"/>
18:<property name="app.version" value="0.0.1"/>
19:<property name="app.year" value="2000"/>
20:<!-- source code and document info -->
21:<property name="src.dir" value="."/>
22:<property name="doc.dir" value="./doc"/>
23:<property name="lib.dir" value="./lib"/>
24:<!-- package to be javadocs -->
25:<property name="packages" value="antDemo.*"/>
26:<!-- build info -->
27:<property name="build.dir" value="ant.build"/>
28:<property name="build.classes" value="${build.dir}/classes"/>
29:<property name="build.lib" value="${build.dir}/lib"/>
30:<property name="build.javadocs" value="${build.dir}/javadocs"/>
31:<property name="build.xmlc.dir" value="${build.dir}/xmlcout/"/>
32:<property name="build.debug" value="on"/>
33:<property name="dist.dir" value="./${app.name}-${app.version}"/>
34: </target>
35:<!-- =================================================================== -->
36:<!-- 創建要存放編譯厚的文件的目錄 -->
37:<!-- =================================================================== -->
38:<target name="prepare" depends="init">
39:<mkdir dir="${build.dir}"/>
40:</target>
41:<!-- =================================================================== -->
42:<!-- 用XMLC工具編譯 html文件-->
43:<!-- =================================================================== -->
44:<target name="xmlc" depends="prepare">
45:<mkdir dir="${build.xmlc.dir}"/>
46:<xmlc srcdir="${src.dir}"
47:sourceout="${build.xmlc.dir}"
48:includes="**/*.html">
49:<!-- element name is same as command line parameter -->
50:<warnings param1="false"/>
51:<generate param1="both"/>
52:<html_encoding param1="gb2312"/>
53:<!-- the old arg element is still supported -->
54:<arg name="ssi"/>
55:<arg name="keep"/>
56:<!-- prefixmap do package name mapping -->
57:<prefixmap old="antDemo.presentation.html" new="antDemo.presentation"/>
58:</xmlc>
59:</target>
60:<!-- =================================================================== -->
61:<!-- 編譯 -->
62:<!-- =================================================================== -->
63:<target name="compile" depends="xmlc,prepare">
64:<mkdir dir="${build.classes}"/>
65:<!-- compile XMLC generated java -->
66:<javac srcdir="${build.xmlc.dir}"
67:destdir="${build.classes}"
68:classpathref="build.classpath"
69:debug="${build.debug}"/>
70:<!-- compile java codes -->
71:<javac srcdir="${src.dir}"
72:destdir="${build.classes}"
73:classpathref="build.classpath"
74:debug="${build.debug}"
75:includes="${app.name}/**"
76:/>
77:</target>
78:<!-- =================================================================== -->
79:<!-- 復制 -->
80:<!-- =================================================================== -->
81:<target name="extra" depends="init">
82:<mkdir dir="${build.classes}/${app.name}/presentation"/>
83:<copy todir="${build.classes}/${app.name}/presentation">
84:<fileset dir="${src.dir}/${app.name}/presentation">
85:<include name="**/*.gif"/>
86:<include name="**/*.jpg"/>
87:<include name="**/*.js"/>
88:<include name="**/*.css"/>
89:</fileset>
90:</copy>
91:</target>
92:<!-- =================================================================== -->
93:<!-- 創建lib目錄,class文件及其他文件打包 -->
94:<!-- =================================================================== -->
95:<target name="jar" depends="extra,compile">
96:<mkdir dir="${build.lib}"/>
97:<jar jarfile="${build.lib}/${app.name}.jar" basedir="${build.classes}" />
98:</target>
99:<!-- =================================================================== -->
100:<!-- 復制應用程序的配置文件 -->
101:<!-- =================================================================== -->
102:<target name="app" depends="jar,extra">
103:<!-- do the app.conf -->
104:<copy file="${src.dir}/${app.name}/${app.Name}.conf" todir="${build.dir}"/>
105:<!-- do the multiserver.conf -->
106:<filter token="OUTPUT" value="./" />
107:<copy file="${src.dir}/${app.name}/multiserver.conf.in"
108:tofile="${build.dir}/multiserver.conf"
109:filtering="on"/>
110:<!-- do the start script -->
111:<copy file="${src.dir}/${app.name}/start" todir="${build.dir}"/>
112:<chmod file="${build.dir}/start" perm="ugo+rx"/>
113:</target>
114:</project>
4:build.xml詳細說明
下面我們將詳細講述這個文件,同樣為了方便,我加了行號,當然一些基本的東西我就不再重復了。第四行taskdef任務(task)屬于ant的內部任務,它的作用是定義一個任務,其基本屬性有name,classname,在定義時這兩個屬性都必需有。第八行開始定義一個path,它有一個屬性id,通過這個id的值我們可以在后面引用這個path,參見第68行。目標(target)init(從14行到34行)定義了一些基本屬性(property),主要是為了后面的target使用。在第38行,你會看到depends="init",depends是定義一個目標時的可選屬性,它的意思是如果init目標沒有執行(出錯或其他原因),這個目標也不會被執行。
從第46行開始定義xmlc任務,到第58行結束,中間有很多參數嵌套在其中,srcdir指定源文件目錄,sourceout指定輸出目錄,includes屬性將源文件目錄中的所有html文件包括進來。*為通配符。
<warnings param1="false"/>表示取消警告,<generate param1="both"/>表示同時產生接口和實現代碼,例如:一個welcome.html,它會產生兩個文件:WelcomeHTMLImpl.java,WelcomeHTML.java,WelcomeHTML.java中只定義了一個接口WelcomeHTML,真正的實現在WelcomeHTMLImpl.java中。<html_encoding param1="gb2312"/>表示設置編碼,由于xmlc將html文件編譯為java類,即使你在html文件中已經設置了編碼,在java類中也不會有作用,必須在編譯時設置編碼。<arg name="ssi"/> <arg name="keep"/>這兩句相當于在命令行上輸入-ssi -keep.其中ssi參數是在編譯html文件時將定義的ssi文件包括進來,見html目錄下的welcome2.html源代碼中有一行:<!--#include file="welcome.ssi"-->。keep參數會保留編譯html文件后產生的java文件。第57行意思是將包更名,由于html文件在antDemo/presentation/html目錄下,因此產生的java類屬于antDemo.presentation.html包,我們通過new屬性的值將屬于此包的類改為屬于新的包,使用xmlc時,一般以上幾個參數就足夠了,要想使用更多的參數,請參見xmlc task定義的源代碼 。
從第63行到77行,目標(target)定義了編譯時的細節,編譯分為兩部分,分別編譯xmlc產生的java類和項目中的java類(表現層,商務層,數據層中的代碼)。javac這個任務中,srcdir屬性指定java文件存放位置,destdir屬性指定編譯后的class文件存放位置,classpathref屬性指定classpath,debug屬性設置關閉還是打開調試信息,includes屬性起一個過濾作用,它指定編譯那些文件,否則javac將會編譯srcdir屬性指定的目錄下的所有java文件。
81行到91行開始將將程序中用到的其他文件也復制到目標目錄,以便下一步打包。在copy任務中,todir屬性指定目標目錄,至于復制那些文件,則由嵌套在copy任務中的fileset任務來指定。在fileset中,dir指定基本目錄,include和exclude屬性用來過濾文件,符合條件的文件將會被復制到目標目錄。
95行到98行開始將程序打包,jarfile屬性指定打包后的文件名,basedir指定基本目錄,基本目錄下的文件及子目錄都會按照其本來的組織結構放到jar文件中。
102行到113行,開始復制配置文件,配置文件包括AntDemo.conf,multiserver.conf,start.其中第112行,chmod任務將start文件的屬性改為對任何人可執行和可讀。
通過上面的講解,你可能看出使用ant的優越性,ant可以方便的管理一個大型的enhydra項目,當然其他的項目也可以,重要的是,你可以很容易的對它的task進行擴充。相信越來越多的人會使用ant來進行項目的管理。
四:小技巧:
由于使用ant時可能出錯,而屏幕不夠大的話,可能看不清,最好將編譯出錯信息放入一個文件中,如下這樣使用ant:
ant -buildfile build.xml -logfile error.log
就會將出錯信息放入error.log中,由于使用buildfile參數,因此xml文件名不一定時build.xml,可以為任意xml 文件,如project.xml
本人的開發環境為:windows98+enhydra3.1+ant1.2+jdk1.2.2,redhat6.2+enhydra3.11b+ant1.2+jdk1.31。
延伸閱讀
文章來源于領測軟件測試網 http://www.kjueaiud.com/