一個適合初學者的Ant教程

一,構建ant環境

要使用ant首先要構建一個ant環境,步驟很簡單:

1),安裝jdk,設置JAVA_HOME ,PATH ,CLASS_PATH(這些應該是看這篇文章的人應該知道的)

2),下載ant 地址www.apache.org找一個你喜歡的版本,或者乾脆最新的版本

3),解壓ant 你得到的是一個壓縮包,解壓縮它,並把它放在一個儘量簡單的目錄,例如D:\ant-1.6雖然你不一 定要這麼做,但這麼做是有好處的。

4),設置ANT_HOME PATH中添加ANT_HOME目錄下的bin目錄

5),測試一下你的設置,開始-->運行-->cmd進入命令行-->鍵入 ant 回車,如果看到

Buildfile: build.xml does not exist!

Build failed

那麼恭喜你你已經完成ant的設置

二,體驗ant

就像每個語言都有HelloWorld一樣,一個最簡單的應用能讓人感受一下Ant

1,首先你要知道你要幹什麼,我現在想做的事情是:

編寫一些程序

編譯它們

把它打包成jar包

把他們放在應該放置的地方

運行它們

這裏爲了簡單起見只寫一個程序,就是HelloWorld.java程序代碼如下:

package test.ant;

public class HelloWorld{

public static void main(String[] args){

System.out.println("Hello world1");

}

};

 

2,爲了達到上邊的目的,你可以手動的用javac 、copy 、jar、java來完成,但是考慮一下如果你有成百上千個類,在多次調試,部署的時候,一次次的javac 、copy、jar、java那將是一份辛苦的工作。現在看看ant怎麼優雅的完成它們。

 

要運行ant需要有一個build.xml雖然不一定要叫這個名字,但是建議你這麼做

下邊就是一個完整的build.xml,然後我們來詳細的解釋每一句

<?xml version="1.0" encoding="UTF-8" ?>

<project name="HelloWorld" default="run" basedir=".">

<property name="src" value="src"/>

<property name="dest" value="classes"/>

<property name="hello_jar" value="hello1.jar"/>

<target name="init">

<mkdir dir="${dest}"/>

</target>

<target name="compile" depends="init">

<javac srcdir="${src}" destdir="${dest}"/>

</target>

<target name="build" depends="compile">

<jar jarfile="${hello_jar}" basedir="${dest}"/>

</target>

<target name="run" depends="build">

<java classname="test.ant.HelloWorld" classpath="${hello_jar}"/>

</target>

<target name="clean">

<delete dir="${dest}" />

<delete file="${hello_jar}" />

</target>

<target name="rerun" depends="clean,run">

<ant target="clean" />

<ant target="run" />

</target>

</project>

 

解釋:

<?xml version="1.0" encoding="UTF-8" ?>

build.xml中的第一句話,沒有實際的意義

 

<project name="HelloWorld" default="run" basedir=".">

</project>

ant的所有內容必須包含在這個裏邊,name是你給它取的名字,basedir故名思意就是工作的根目錄 .代表當前目錄。default代表默認要做的事情。

 

<property name="src" value="src"/>

類似程序中的變量,爲什麼這麼做想一下變量的作用

 

<target name="compile" depends="init">

<javac srcdir="${src}" destdir="${dest}"/>

</target>

把你想做的每一件事情寫成一個target ,它有一個名字,depends是它所依賴的target,在執行這個target 例如這裏的compile之前ant會先檢查init是否曾經被執行過,如果執行過則直接直接執行compile,如果沒有則會先執行它依賴的target例如這裏的init,然後在執行這個target

 

如我們的計劃

編譯:

<target name="compile" depends="init">

<javac srcdir="${src}" destdir="${dest}"/>

</target>

 

做jar包:

<target name="build" depends="compile">

<jar jarfile="${hello_jar}" basedir="${dest}"/>

</target>

運行:

<target name="run" depends="build">

<java classname="test.ant.HelloWorld" classpath="${hello_jar}"/>

</target>

爲了不用拷貝,我們可以在最開始定義好目標文件夾,這樣ant直接把結果就放在目標文件夾中了

新建文件夾:

<target name="init">

<mkdir dir="${dest}"/>

</target>

爲了更多一點的功能體現,又加入了兩個target

刪除生成的文件

<target name="clean">

<delete dir="${dest}" />

<delete file="${hello_jar}" />

</target>

再次運行,這裏顯示瞭如何在一個target裏邊調用其他的target

<target name="rerun" depends="clean,run">

<ant target="clean" />

<ant target="run" />

</target>

 

好了,解釋完成了,下邊檢驗一下你的ant吧

新建一個src的文件夾,然後把HelloWorld.java按照包目錄放進去

做好build.xml文件

在命令行下鍵入ant ,你會發現一個個任務都完成了。每次更改完代碼只需要再次鍵入ant

 

有的時候我們可能並不想運行程序,只想執行這些步驟中的某一兩個步驟,例如我只想重新部署而不想運行,鍵入

ant build

 

ant中的每一個任務都可以這樣調用ant + target name

好了,這樣一個簡單的ant任務完成了。

 

本文以最新發布的Ant 1.5.1爲例,介紹這款優秀的Build工具的安裝配置、基本應用和一些高級話題。最新的Ant下載地址是 http://jakarta.apache.org/ant/ 。

 

 

 

Ant是一種基於Java的Build工具。理論上來說,它有些類似於C中的make,但比make優越。現在存在的大多數Build工具,如make、gnumake、nmake、jam等都存在這樣或那樣的不足,比如依賴於特定的平臺、配置文件過於複雜或者對格式無法檢查而容易出錯等。與這些工具相比較,Ant的兩個特性決定了它是一款優秀的Build工具:

 

1. 基於Java的實現。具有良好的跨平臺性,同時可以通過增加新的Java類來擴展Ant的功能,而無需去了解不同平臺上不同的腳本語言。

 

2.基於XML的配置文件。Ant以XML樹來描述Target/Task的關係,文件結構清晰、易讀易寫,並且利用XML對格式的控制來避免由於配置文件的錯誤造成的Build操作失敗。

 

安裝與配置

 

Ant的安裝非常簡單,把從網上下載的jakarta-ant-1.5.1-bin.zip解開到一個目錄下即可(以下假定安裝在目錄D:\jakarta-ant-1.5.1)。接下來需要進行環境變量配置:SET ANT_HOME=D:\jakarta-ant-1.5.1 //注意是Ant的安裝目錄,不是bin子目錄

SET PATH=%PATH%;%ANT_HOME%\bin;

 

 

 

在配置環境變量之前,請確認已經正確設置了JAVA_HOME系統變量。輸入ant命令,看到如下輸出說明已成功安裝了Ant工具:

Buildfile: build.xml does not exist!

Build failed

 

 

 

提示信息表明在當前目錄不存在build.xml配置文件,但這本身已經說明Ant成功運行了。

 

快速入門

 

下面用一個最簡單也是最經典的例子-HelloWorld來感受一下Ant吧。

//HelloWorld.java

package com.sharetop.antdemo;

public class HelloWorld {

public static void main( String args[] ) {

System.out.println("Hello world. ");

}

}

 

 

 

要讓Ant編譯這個文件,首先需要編寫一個Build配置文件。在一般情況下,這個文件被命名爲build.xml。

<?xml version="1.0" encoding="UTF-8" ?>

<project name="HelloWorld" default="run" basedir="." >

<property name="src" value="src"/>

<property name="dest" value="classes"/>

<property name="hello_jar" value="hello.jar" />

<target name="init">

<mkdir dir="${dest}"/>

</target>

<target name="compile" depends="init">

<javac srcdir="${src}" destdir="${dest}"/>

</target>

<target name="build" depends="compile">

<jar jarfile="${hello_jar}" basedir="${dest}"/>

</target>

<target name="run" depends="build">

<java classname="com.sharetop.antdemo.HelloWorld" classpath="${hello_jar}"/>

</target>

</project>

 

 

 

來看一下這個文件的內容,它描述了以下信息:工程的名字爲HelloWorld,工程有四個target,分別是init、compil、build和run,缺省是run。compile只有一個任務javac,源文件位於src目錄下,輸出的類文件要放在classes目錄下。build的任務是jar,生成的jar文件爲hello.jar,它打包時以classes爲根目錄。而run則是執行這個HelloWorld類,用hello.jar作爲classpath。這四個target之間有一個依賴關係,這種關係用depends來指定。即如果Target A依賴於Target B,那麼在執行Target A之前會首先執行Target B。所以從下面運行缺省Target(run)的輸出看,這四個Target的執行順序是:init→compile→build→run。文件目錄結構如圖1所示。HelloWorld.java文件在src\com\sharetop\antdemo子目錄下。

 

 

圖1 ant_demo應用的目錄結構

 

在命令行輸入命令:ant,然後運行,可以看到如下輸出:

 

如果配置文件名不是build.xml,比如是build_front.xml,那麼,可以使用-buildfile命令參數指定:

G:\myDoc\ant_demo>ant -buildfile build_front.xml

 

 

 

也可以單獨執行指定的某個target,比如,只編譯不打包執行,可以使用下面輸入命令即可:

G:\myDoc\ant_demo>ant compile

 

 

在相應的目錄下會找到編譯出的HelloWorld.class文件。

 

 

再看看上面的build.xml配置文件,文件開頭定義了3個屬性,分別指定了源文件輸出路徑、類文件輸出路徑和生成的Jar文件名,後面對這些路徑的引用都通過一個${property name}來引用。所以,要注意這樣一個原則“目錄的定義與目錄的引用應該分開”。

 

 

 

 

 

第二部分

 

基本應用

 

建立工程的目錄

 

一般要根據工程的實際情況來建立工程的目錄結構。但是,有一些比較通用的組織形式可供參考,比如所有的jakarta項目都使用類似的目錄結構。下面讓我們來看一下這種目錄結構的特點。

 

表1

目錄 文件

bin 公共的二進制文件,以及運行腳本

build 臨時創建的文件,如類文件等

dist 目標輸出文件,如生成Jar文件等。

doc/javadocs 文檔。

lib 需要導出的Java包

src 源文件

 

 

對於一個簡單的工程,一般包括表1的幾個目錄。其中bin、lib、doc和src目錄需要在CVS的控制之下。當然在這樣的目錄結構上,也可以做一些調整,例如,可以建立一個extra目錄來放置需要發佈的Jar文件、Inf文件及圖像文件等。同樣,如果開發Web應用可以建立一個Web目錄放置JSP、HTML等文件。

 

如果我們開發的是一個比較複雜的項目,包括多個子項目,並且各個子項目是由不同的開發人員來完成的,那麼要如何來設計它的目錄結構?首先有一點是需要確定的,不同的子項目應該擁有不同的Build文件,並且整個項目也應該有一個總的Build文件。可以通過Ant任務或是AntCall任務調用子項目的Build文件,如下例:

<target name="core" depends="init">

<ant dir="components" target="core"/>

<ant dir="waf/src" target="core"/>

<ant dir="apps" target="core"/>

</target>

 

 

 

在各個子項目的耦合不是非常緊密的情況下,各個子項目應該有各自獨立的目錄結構,也就是說它們可以有自己的src、doc、build、dist等目錄及自己的build.xml文件,但是可以共享lib和bin目錄。而對於那些耦合緊密的子項目,則推薦使用同一個src目錄,但是不同的子項目有不同的子目錄,各個子項目的build.xml文件可以放在根目錄下,也可以移到各個子項目的目錄下。

 

編寫Build文件

 

要用好Ant工具,關鍵是要編寫一個build.xml文件。要編寫出一個結構良好、靈活可擴展的Build文件,有兩個問題要考慮,一是瞭解Build文件的基本結構,二是瞭解Ant定義的大量任務。

 

Ant的Build文件是一個標準的XML文件,它包含一個根節點Project,每個Project定義了至少一個或多個Target,每個Target又是一系列Task的集合。它們之間的關係如圖2所示。

 

 

圖2 build.xml文件的結構

 

每個Task是一段可被執行的代碼,比如,前例中的javac、jar就是兩個最常用的Task。Ant定義了大量的核心Task,我們要考慮的第二個問題正是如何去掌握這大量的Task。其實唯一的方法就是邊學習邊實踐,這方面最好的參考就是官方的Ant使用手冊。

 

外部文件的使用

 

使用外部的Property文件可以保存一些預設置的公共屬性變量。這些屬性可以在多個不同的Build文件中使用。

 

可以將一個外部的XML文件導入Build文件中,這樣多個項目的開發者可以通過引用來共享一些代碼,同樣,這也有助於Build文件的重用,示例代碼如下所示:

<!DOCTYPE project [

<!ENTITY share-variable SYSTEM "file:../share-variable.xml">

<!ENTITY build-share SYSTEM "file:../build-share.xml">

]>

<project name="main" default="complie" basedir=".">

&share-variable;

&build-share;

... ...

 

 

 

在J2EE項目中的應用

 

只要掌握了Ant的使用方法,在J2EE項目中的應用與在其它項目中的應用並沒有太大的不同,但是仍有幾點是需要注意的。

 

一是要清楚War和Jar文件的目錄結構,主要是War的配置文件web.xml文件的位置和EJB的配置文件(ejb-jar.xml和weblogic-ejb-jar.xml等)的位置,在調用Jar任務打包文件時一定要記得把它們也包含進來。一般在編譯之前就要注意把這些需打包的文件拷入相應目錄下。二是在J2EE項目中可能會涉及到一些特殊的任務,比如在Weblogic中會調用ejbc預編譯EJB的代碼存根,或者需要在Ant中同時發佈Jar到相應的服務器中等。可以用兩種途徑實現這些任務,一是擴展Ant任務實現這些任務,二是直接用Java任務來執行這些命令。下面是打包、發佈一個EJB的build.xml配置文件片斷,代碼如下:

<target name="deploy_HelloEJB" depends="compile">

<delete dir="${temp}/ejb_make"/> <!-- 首先刪除臨時目錄 -->

<delete file="${temp}/helloEJB.jar"/>

<!-- 刪除WebLogic域中老版本的EJB -->

<delete file="${weblogic.deploy.dest}/helloEJB.jar"/>

<!-- 創建META-INF目錄,放置ejb-jar.xml和weblogic-ejb-jar.xml -->

<mkdir dir="${temp}/ejb_make/META-INF"/>

<!-- 拷貝ejb-jar.xml和weblogic-ejb-jar.xml 到臨時目錄-->

<copy todir="${temp}/ejb_make/META-INF">

<fileset dir="etc/baseinfo">

<include name="*.xml"/>

</fileset>

</copy>

<!-- 拷貝所有的helloEJB類到臨時目錄 -->

<copy todir="${temp}/ejb_make/">

<fileset dir="${dest.classes}/"> <!-- dest.classes是輸出的類文件目錄 -->

<include name="${dest.classes}/helloEJB/**"/>

</fileset>

</copy>

<!-- 將所有這些文件打包成helloEJB.jar -->

<jar jarfile="${temp}/helloEJB.jar" basedir="${temp}/ejb_make"/>

<!-- 進行weblogic.ejbc編譯 -->

<java classpath="${wl_cp}" classname="weblogic.ejbc" fork="yes" >

<classpath>

<fileset dir="lib">

<include name="*.jar" />

</fileset>

</classpath>

<arg value="${temp}/helloEJB.jar" />

<arg value="${temp}/helloEJB_deploy.jar" />

</java>

<!-- 拷貝/發佈到WebLogic的{DOMAIN}\applications目錄 -->

<copy file="${temp}/helloEJB_deploy.jar" todir="${weblogic.deploy.dest}"/>

</target>

 

 

 

用Ant配合JUnit實現單元測試

 

Ant 提供了JUnit任務,可以執行單元測試代碼。如何使用JUnit,以及如何編寫測試用例(TestCase),感興趣的讀者可以參閱JUnit的相關文檔。在Ant中使用JUnit的方法非常簡單,首先需要把junit.jar拷入ANT_HOME\lib下,確認在這個目錄下有optional.jar,因爲JUnit是Ant的擴展任務,需要引用這個擴展包。然後就是在Build文件中加入JUnit的任務,代碼如下:

<target name="run" depends="client">

<junit printsummary="yes" fork="yes" haltonfailure="yes">

<classpath>

<pathelement location="client.jar" />

</classpath>

<formatter type="plain" />

<test name="com.sharetop.antdemo.HelloWorldTest" />

</junit>

</target>

 

 

 

高級話題

 

爲Ant開發擴展任務

 

爲Ant實現擴展任務其實是非常容易的,只需按照以下幾個步驟即可:

 

1. 創建一個Java類繼承org.apache.tools.ant.Task類;

 

2. 對每個屬性實現set方法。Ant會根據需要自動完成類型轉換;

 

3. 如果擴展的任務需要嵌套其它的Task,那麼這個Java類必需實現接口org.apache.tools.ant.TaskContainer;

 

4. 如果擴展的任務要支持Text,需要增加一個方法void addText(String);

 

5. 對每個嵌套的元素,實現create、add 或 addConfigured 方法;

 

6. 實現public void execute方法;

 

7. 在build.xml文件中使用 <taskdef> 來引用自定義的Task。

 

下面以一個簡單的例子來說明如何爲Ant增加一個hello任務,它可以連續打印多條信息,打印的次數由屬性count指定,而打印的內容則由它內嵌的一個helloinfo任務的message屬性指定,看上去這非常類似JSP中自定義標籤的一些概念,實現代碼如下:

//HelloInfoTask.java

package com.sharetop.antdemo;

import org.apache.tools.ant.*;

public class HelloInfoTask {

private String msg;

public void execute() throws BuildException {

System.out.println(msg);

}

public void setMessage(String msg) {

this.msg = msg;

}

}

 

 

 

下面是外部Task類的代碼:

//HelloTask.java

package com.sharetop.antdemo;

import org.apache.tools.ant.*;

public class HelloTask extends Task implements org.apache.tools.ant.TaskContainer

{

private Task info;

private int count;

public void execute() throws BuildException {

for(int i=0;i<count;i++)

info.execute();

}

public void setCount(int c){

this.count=c;

}

public void addTask(Task t){

this.info=t;

}

}

 

 

 

實現了這兩個Task,在build.xml文件中定義它的task name,就可以在Target中執行它了。如果你不想使用 <taskdef> 標籤來定義Task,也可以通過修改default.properties文件來實現引入新Task,這個文件位於org.apache.tools.ant.taskdefs 包裏。下例是一個使用 標籤來引入新Task的Build文件部分:

<target name="hello" depends="client">

<taskdef name="hello"

classname="com.sharetop.antdemo.HelloTask" classpath="client.jar"/>

<taskdef name="helloinfo"

classname="com.sharetop.antdemo.HelloInfoTask" classpath="client.jar"/>

<hello count="3" >

<helloinfo message="hello world" />

</hello>

</target>

 

 

 

 

 

第三部分ant打ear包的詳細步驟

 

ant打ear包的詳細步驟

 

技術應用   2009-11-02 12:26   閱讀21   評論0   字號: 大大  中中  小小 用一個簡單的ejb3.0示例記錄ant打ear包的過程

 

源碼下載

 

環境:

apache-ant-1.6.5

jboss-4.2.1.GA

jboss-annotations-ejb3.jar

jboss-ejb3.jar

jboss-ejb3x.jar

最後三個包在jboss裏有.

 

1,建ejb3.0項目

session bean接口:HelloWorld

public interface HelloWorld {

public String sayHello(String name);

}

 

 

 

實現類:HelloWorldBean

@Stateless

@Remote ({HelloWorld.class})

public class HelloWorldBean implements HelloWorld {

public String sayHello(String name) {

//org.apache.commons.collections,這裏假設用到了其它包中的類

CollectionUtils c=new CollectionUtils();

//org.apache.commons.lang

StringUtils s=new StringUtils();

return "hello,i am "+name;

}

}

 

 

 

調用session bean的jsp:

<%

//org.apache.commons.collections,這裏假設用到了其它包中的類

CollectionUtils c=new CollectionUtils();

//org.apache.commons.lang

StringUtils s=new StringUtils();

%>

<%

Properties props = new Properties();

props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");

props.setProperty("java.naming.provider.url", "localhost:1099");

props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");

 

InitialContext ctx;

try {

ctx = new InitialContext(props);

HelloWorld helloworld = (HelloWorld) ctx.lookup("myproject/HelloWorldBean/remote");

out.println(helloworld.sayHello("mashiguang"));

} catch (NamingException e) {

out.println(e.getMessage());

}

 

%>

 

 

 

 

 

把一些公用的jar包都放到ear下,而不是分別在ejb jar包和war包裏,減少jar包的冗餘.

<project name="ear" default="deploy" basedir=".">

 

<property environment="env" />

<property name="app.dir" value="${basedir}" />

<property name="src.dir" value="${app.dir}\src" />

<property name="classes.dir" value="${app.dir}\build\classes" />

<property name="webcontent.dir" value="${app.dir}\WebContent" />

<property name="jboss.home" value="${env.JBOSS_HOME}" />

<property name="jboss.server.config" value="default" />

 

<path id="build.classpath" description="編譯時classpath">

<fileset dir="${webcontent.dir}\WEB-INF\lib">

<include name="*.jar" />

</fileset>

<pathelement location="${classes.dir}" />

</path>

 

<target name="prepare" depends="clean" description="創建classes文件夾">

<mkdir dir="${classes.dir}" />

</target>

 

<target name="compile" depends="prepare" description="編繹">

<javac srcdir="${src.dir}" destdir="${classes.dir}" debug="on" deprecation="on" optimize="off" includes="**">

<classpath refid="build.classpath" />

</javac>

</target>

 

<target name="sessionInterface" depends="compile" description="創建session bean接口包">

<jar destfile="${app.dir}/interface.jar">

<fileset dir="${classes.dir}">

<include name="com/mashiguang/ejb3/*.class" />

</fileset>

</jar>

</target>

 

<target name="ejb_jar" depends="sessionInterface" description="創建ejb jar包">

<jar destfile="${app.dir}/ejb.jar">

<fileset dir="${classes.dir}">

<include name="com/mashiguang/ejb3/impl/**" />

</fileset>

<manifest>

<attribute name="Class-Path" value="interface.jar commons-collections-3.2.jar commons-lang-2.3.jar"/>

</manifest>

</jar>

</target>

 

<target name="web-war" depends="ejb_jar" description="創建WEB發佈包">

<war destfile="${app.dir}/web.war" webxml="${webcontent.dir}/WEB-INF/web.xml">

<fileset dir="${webcontent.dir}">

<include name="*.jsp"/>

<exclude name="WEB-INF/web.xml"/>

<exclude name="WEB-INF/lib/**"/>

</fileset>

<manifest>

<attribute name="Class-Path" value="interface.jar commons-collections-3.2.jar commons-lang-2.3.jar"/>

</manifest>

</war>

</target>

 

<target name="ear" depends="web-war" description="創建WEB發佈包">

<ear destfile="${app.dir}/myproject.ear" appxml="${src.dir}/META-INF/application.xml">

<fileset dir="${app.dir}">

<include name="ejb.jar"/>

<include name="web.war"/>

<include name="interface.jar"/>

</fileset>

<fileset dir="${webcontent.dir}/WEB-INF/lib" >

<include name="commons*.jar"/>

</fileset>

</ear>

</target>

 

<target name="deploy" depends="ear">

<copy file="${app.dir}/myproject.ear" todir="${jboss.home}/server/${jboss.server.config}/deploy" />

</target>

 

<target name="clean">

<delete>

<fileset dir="${app.dir}">

<include name="ejb.jar"/>

<include name="web.war"/>

<include name="interface.jar"/>

</fileset>

</delete>

<delete dir="${classes.dir}" />

<!-- -->

<delete file="${jboss.home}/server/${jboss.server.config}/deploy/myproject.ear" />

 

</target>

 

</project>

Ant學習教程 http://www.uml.org.cn/j2ee/j2ee091302.htm

 

Ant實踐

eric

目錄

1. Ant是什麼?

2. 安裝Ant

3. 運行Ant

4. 編寫build.xml

5. 內置task(internet)

6. EAR task(internet)

7. WAR task(internet)

8. JUnit task(internet)

 

1. Ant是什麼?

Ant是一種基於Java的build工具。理論上來說,它有些類似於(Unix)C中的make ,但沒有make的缺陷。

 

既然我們已經有了make, gnumake, nmake, jam以及其他的build工具爲什麼還要要一種新的build工具呢?因爲Ant的原作者在多種(硬件)平臺上開發軟件時,無法忍受這些工具的限制和不便。類似於make的工具本質上是基於shell(語言)的:他們計算依賴關係,然後執行命令(這些命令與你在命令行敲的命令沒太大區別)。這就意味着你可以很容易地通過使用OS特有的或編寫新的(命令)程序擴展該工具;然而,這也意味着你將自己限制在了特定的OS,或特定的OS類型上,如Unix。

 

Makefile也很可惡。任何使用過他們的人都碰到過可惡的tab問題。Ant的原作者經常這樣問自己:“是否我的命令不執行只是因爲在我的tab前有一個空格?!!”。類似於jam的工具很好地處理了這類問題,但是(用戶)必須記住和使用一種新的格式。

 

Ant就不同了。與基於shell命令的擴展模式不同,Ant用Java的類來擴展。(用戶)不必編寫shell命令,配置文件是基於XML的,通過調用target樹,就可執行各種task。每個task由實現了一個實現了特定Task接口的對象來運行。(如果你對Ant一點概念都沒有的話,可能看不懂這一節,沒有關係,後面會對target,task做詳細的介紹。你如果沒有太多的時間甚至可以略過這一節,然後再回來瀏覽一下這裏的介紹,那時你就會看懂了。同樣,如果你對make之類的工具不熟悉也沒關係,下面的介紹根本不會用到make中的概念。)

 

必須承認,這樣做,在構造shell命令時會失去一些特有的表達能力。如`find . -name foo -exec rm {}`,但卻給了你跨平臺的能力-你可以在任何地方工作。如果你真的需要執行一些shell命令,Ant有一個<exec> task,這個task允許執行特定OS上的命令。

 

返回

2. 安裝Ant

由於Ant是一個Open Source的軟件,所以有兩種安裝Ant的方式,一種是用已編譯好的binary 文件安裝Ant,另一種是用源代碼自己build Ant。

 

binary 形式的Ant可以從http://jakarta.apache.org/builds/ant/release/v1.4.1/bin下載。如果你希望你能自己編譯Ant,則可從 http://jakarta.apache.org/builds/ant/release/v1.4.1/src。注意所列出的連接都是最新發行版的Ant。如果你讀到此文時,發現已經有了更新的版本,那麼請用新版本。如果你是一個瘋狂的技術追求者,你也可以從Ant CVS repository下載最新版本的Ant。

 

系統需求

 

要想自己build Ant。你需要一個JAXP兼容的XML解析器(parser)放在你的CLASSPATH系統變量中。

 

binary 形式的Ant包括最新版的Apache Crimson XML解析器。你可以從http://java.sun.com/xml/ 得到更多的關於JAXP的信息。如果你希望使用其他的JAXP兼容的解析器。你要從Ant的lib目錄中刪掉jaxp.jar以及crimson.jar。然後你可將你心愛的解析器的jar文件放到Ant的lib目錄中或放在你的CLASSPATH系統變量中。

 

對於當前版本的Ant,需要你的系統中有JDK,1.1版或更高。未來的Ant版本會要求使用JDK 1.2或更高版本。

 

安裝Ant

 

binary 版的Ant包括三個目錄:bin, docs 和lib。只有bin和lib目錄是運行Ant所需的。要想安裝Ant,選擇一個目錄並將發行版的文件拷貝到該目錄下。這個目錄被稱作ANT_HOME。

 

在你運行Ant之前需要做一些配置工作。

將bin目錄加入PATH環境變量。

設定ANT_HOME環境變量,指向你安裝Ant的目錄。在一些OS上,Ant的腳本可以猜測ANT_HOME(Unix和Windos NT/2000)-但最好不要依賴這一特性。

可選地,設定JAVA_HOME環境變量(參考下面的高級小節),該變量應該指向你安裝JDK的目錄。

注意:不要將Ant的ant.jar文件放到JDK/JRE的lib/ext目錄下。Ant是個應用程序,而lib/ext目錄是爲JDK擴展使用的(如JCE,JSSE擴展)。而且通過擴展裝入的類會有安全方面的限制。

 

可選Task

 

Ant支持一些可選task。一個可選task一般需要額外的庫才能工作。可選task與Ant的內置task分開,單獨打包。這個可選包可以從你下載Ant的同一個地方下載。目前包含可選task的jar文件名叫jakarta-ant-1.4.1-optional.jar。這個jar文件應該放到Ant安裝目錄的lib目錄下。

 

每個可選task所需的外部庫可參看依賴庫小節。這些外部庫可以放到Ant的lib目錄下,這樣Ant就能自動裝入,或者將其放入環境變量中。

 

Windows

 

假定Ant安裝在c:\ant\目錄下。下面是設定環境的命令:

set ANT_HOME=c:\ant

set JAVA_HOME=c:\jdk1.2.2

set PATH=%PATH%;%ANT_HOME%\bin

Unix (bash)

 

假定Ant安裝在/usr/local/ant目錄下。下面是設定環境的命令:

export ANT_HOME=/usr/local/ant

export JAVA_HOME=/usr/local/jdk-1.2.2

export PATH=${PATH}:${ANT_HOME}/bin

高級

 

要想運行Ant必須使用很多的變量。你至少參考需要下面的內容:

Ant的CLASSPATH必須包含ant.jar以及你所選的JAXP兼容的XML解析器的jar文件。

當你需要JDK的功能(如javac或rmic task)時,對於JDK 1.1,JDK的classes.zip文件必須放入CLASSPATH中;對於JDK 1.2或JDK 1.3,則必須加入tools.jar。如果設定了正確的JAVA_HOME環境變量,Ant所帶的腳本,在bin目錄下,會自動加入所需的JDK類。

當你執行特定平臺的程序(如exec task或cvs task)時,必須設定ant.home屬性指向Ant的安裝目錄。同樣,Ant所帶的腳本利用ANT_HOME環境變量自動設置該屬性。

Building Ant

 

要想從源代碼build Ant,你要先安裝Ant源代碼發行版或從CVS中checkout jakarta-ant模塊。

 

安裝好源代碼後,進入安裝目錄。

 

設定JAVA_HOME環境變量指向JDK的安裝目錄。要想知道怎麼做請參看安裝Ant小節。

 

確保你已下載了任何輔助jar文件,以便build你所感興趣的task。這些jar文件可以放在CLASSPATH中,也可以放在lib/optional目錄下。參看依賴庫小節可知不同的task需要那些jar文件。注意這些jar文件只是用作build Ant之用。要想運行Ant,你還要像安裝Ant小節中所做的那樣設定這些jar文件。

 

現在你可以build Ant了:

build -Ddist.dir=<directory_to_contain_Ant_distribution> dist (Windows)

build.sh -Ddist.dir=<directory_to_contain_Ant_distribution> dist (Unix)

這樣就可你指定的目錄中創建一個binary版本。

 

上面的命令執行下面的動作:

如果有必要可以bootstrap Ant的代碼。bootstrap 包括手工編輯一些Ant代碼以便運行Ant。bootstrap 用於下面的build步驟。

向build腳本傳遞參數以調用bootstrap Ant。參數定義了Ant的屬性值並指定了Ant自己的build.xml文件的"dist" target。

大多數情況下,你不必直接bootstrap Ant,因爲build腳本爲你完成這一切。運行bootstrap.bat (Windows) 或 bootstrap.sh (UNIX) 可以build一個新的bootstrap版Ant。

 

如果你希望將Ant安裝到ANT_HOME目錄下,你可以使用:

build install (Windows)

build.sh install (Unix)

如果你希望跳過冗長的Javadoc步驟,可以用:

build install-lite (Windows)

build.sh install-lite (Unix)

這樣就只會安裝bin和lib目錄。

 

注意install和install-lite都會覆蓋ANT_HOME中的當前Ant版本。

 

依賴庫

 

如果你需要執行特定的task,你需要將對應的庫放入CLASSPATH或放到Ant安裝目錄的lib目錄下。注意使用mapper時只需要一個regexp庫。同時,你也要安裝Ant的可選jar包,它包含了task的定義。參考上面的安裝Ant小節。

Jar Name Needed For Available At

An XSL transformer like Xalan or XSL:P style task http://xml.apache.org/xalan-j/index.html or http://www.clc-marketing.com/xslp/

jakarta-regexp-1.2.jar regexp type with mappers jakarta.apache.org/regexp/

jakarta-oro-2.0.1.jar regexp type with mappers and the perforce tasks jakarta.apache.org/oro/

junit.jar junit tasks www.junit.org

stylebook.jar stylebook task CVS repository of xml.apache.org

testlet.jar test task java.apache.org/framework

antlr.jar antlr task www.antlr.org

bsf.jar script task oss.software.ibm.com/developerworks/projects/bsf

netrexx.jar netrexx task www2.hursley.ibm.com/netrexx

rhino.jar javascript with script task www.mozilla.org

jpython.jar python with script task www.jpython.org

netcomponents.jar ftp and telnet tasks www.savarese.org/oro/downloads

 

 

返回

3. 運行Ant

運行Ant非常簡單,當你正確地安裝Ant後,只要輸入ant就可以了。

 

沒有指定任何參數時,Ant會在當前目錄下查詢build.xml文件。如果找到了就用該文件作爲buildfile。如果你用 -find 選項。Ant就會在上級目錄中尋找buildfile,直至到達文件系統的根。要想讓Ant使用其他的buildfile,可以用參數 -buildfile file,這裏file指定了你想使用的buildfile。

 

你也可以設定一些屬性,以覆蓋buildfile中指定的屬性值(參看property task)。可以用 -Dproperty=value 選項,這裏property是指屬性的名稱,而value則是指屬性的值。也可以用這種辦法來指定一些環境變量的值。你也可以用property task來存取環境變量。只要將 -DMYVAR=%MYVAR% (Windows) 或 -DMYVAR=$MYVAR (Unix) 傳遞給Ant -你就可以在你的buildfile中用${MYVAR}來存取這些環境變量。

 

還有兩個選項 -quite,告訴Ant運行時只輸出少量的必要信息。而 -verbose,告訴Ant運行時要輸出更多的信息。

 

可以指定執行一個或多個target。當省略target時,Ant使用標籤<project>的default屬性所指定的target。

 

如果有的話,-projecthelp 選項輸出項目的描述信息和項目target的列表。先列出那些有描述的,然後是沒有描述的target。

 

命令行選項總結:

ant [options] [target [target2 [target3] ...]]

Options:

-help print this message

-projecthelp print project help information

-version print the version information and exit

-quiet be extra quiet

-verbose be extra verbose

-debug print debugging information

-emacs produce logging information without adornments

-logfile file use given file for log output

-logger classname the class that is to perform logging

-listener classname add an instance of class as a project listener

-buildfile file use specified buildfile

-find file search for buildfile towards the root of the filesystem and use the first one found

-Dproperty=value set property to value

例子

ant

使用當前目錄下的build.xml運行Ant,執行缺省的target。

ant -buildfile test.xml

使用當前目錄下的test.xml運行Ant,執行缺省的target。

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。

 

文件

 

在Unix上,Ant的執行腳本在做任何事之前都會source(讀並計算值)~/.antrc 文件;在Windows上,Ant的批處理文件會在開始時調用%HOME%\antrc_pre.bat,在結束時調用%HOME%\antrc_post.bat。你可以用這些文件配置或取消一些只有在運行Ant時才需要的環境變量。看下面的例子。

 

環境變量

 

包裹腳本(wrapper scripts)使用下面的環境變量(如果有的話):

JAVACMD Java可執行文件的絕對路徑。用這個值可以指定一個不同於JAVA_HOME/bin/java(.exe)的JVM。

ANT_OPTS 傳遞給JVM的命令行變量-例如,你可以定義屬性或設定Java堆的最大值

手工運行Ant

 

如果你自己動手安裝(DIY)Ant,你可以用下面的命令啓動Ant:

java -Dant.home=c:\ant org.apache.tools.ant.Main [options] [target]

這個命令與前面的ant命令一樣。選項和target也和用ant命令時一樣。這個例子假定你的CLASSPATH包含:

ant.jar

jars/classes for your XML parser

the JDK's required jar/zip files

返回

4. 編寫build.xml

Ant的buildfile是用XML寫的。每個buildfile含有一個project。

 

buildfile中每個task元素可以有一個id屬性,可以用這個id值引用指定的任務。這個值必須是唯一的。(詳情請參考下面的Task小節)

 

Projects

 

project有下面的屬性:

Attribute Description Required

name 項目名稱. No

default 當沒有指定target時使用的缺省target Yes

basedir 用於計算所有其他路徑的基路徑。該屬性可以被basedir property覆蓋。當覆蓋時,該屬性被忽略。如果屬性和basedir property都沒有設定,就使用buildfile文件的父目錄。 No

 

項目的描述以一個頂級的<description>元素的形式出現(參看description小節)。

 

一個項目可以定義一個或多個target。一個target是一系列你想要執行的。執行Ant時,你可以選擇執行那個target。當沒有給定target時,使用project的default屬性所確定的target。

 

Targets

 

一個target可以依賴於其他的target。例如,你可能會有一個target用於編譯程序,一個target用於生成可執行文件。你在生成可執行文件之前必須先編譯通過,所以生成可執行文件的target依賴於編譯target。Ant會處理這種依賴關係。

 

然而,應當注意到,Ant的depends屬性只指定了target應該被執行的順序-如果被依賴的target無法運行,這種depends對於指定了依賴關係的target就沒有影響。

 

Ant會依照depends屬性中target出現的順序(從左到右)依次執行每個target。然而,要記住的是隻要某個target依賴於一個target,後者就會被先執行。

<target name="A"/>

<target name="B" depends="A"/>

<target name="C" depends="B"/>

<target name="D" depends="C,B,A"/>

假定我們要執行target D。從它的依賴屬性來看,你可能認爲先執行C,然後B,最後A被執行。錯了,C依賴於B,B依賴於A,所以先執行A,然後B,然後C,最後D被執行。

 

一個target只能被執行一次,即時有多個target依賴於它(看上面的例子)。

 

如果(或如果不)某些屬性被設定,才執行某個target。這樣,允許根據系統的狀態(java version, OS, 命令行屬性定義等等)來更好地控制build的過程。要想讓一個target這樣做,你就應該在target元素中,加入if(或unless)屬性,帶上target因該有所判斷的屬性。例如:

<target name="build-module-A" if="module-A-present"/>

<target name="build-own-fake-module-A" unless="module-A-present"/>

如果沒有if或unless屬性,target總會被執行。

 

可選的description屬性可用來提供關於target的一行描述,這些描述可由-projecthelp命令行選項輸出。

 

將你的tstamp task在一個所謂的初始化target是很好的做法,其他的target依賴這個初始化target。要確保初始化target是出現在其他target依賴表中的第一個target。在本手冊中大多數的初始化target的名字是"init"。

 

target有下面的屬性:

Attribute Description Required

name target的名字 Yes

depends 用逗號分隔的target的名字列表,也就是依賴表。 No

if 執行target所需要設定的屬性名。 No

unless 執行target需要清除設定的屬性名。 No

description 關於target功能的簡短描述。 No

 

 

Tasks

 

一個task是一段可執行的代碼。

 

一個task可以有多個屬性(如果你願意的話,可以將其稱之爲變量)。屬性只可能包含對property的引用。這些引用會在task執行前被解析。

 

下面是Task的一般構造形式:

<name attribute1="value1" attribute2="value2" ... />

這裏name是task的名字,attributeN是屬性名,valueN是屬性值。

 

有一套內置的(built-in)task,以及一些可選task,但你也可以編寫自己的task。

 

所有的task都有一個task名字屬性。Ant用屬性值來產生日誌信息。

 

可以給task賦一個id屬性:

<taskname id="taskID" ... />

這裏taskname是task的名字,而taskID是這個task的唯一標識符。通過這個標識符,你可以在腳本中引用相應的task。例如,在腳本中你可以這樣:

<script ... >

task1.setFoo("bar");

</script>

設定某個task實例的foo屬性。在另一個task中(用java編寫),你可以利用下面的語句存取相應的實例。

project.getReference("task1").

注意1:如果task1還沒有運行,就不會被生效(例如:不設定屬性),如果你在隨後配置它,你所作的一切都會被覆蓋。

 

注意2:未來的Ant版本可能不會兼容這裏所提的屬性,因爲很有可能根本沒有task實例,只有proxies。

 

Properties

 

一個project可以有很多的properties。可以在buildfile中用property task來設定,或在Ant之外設定。一個property有一個名字和一個值。property可用於task的屬性值。這是通過將屬性名放在"${"和"}"之間並放在屬性值的位置來實現的。例如如果有一個property builddir的值是"build",這個property就可用於屬性值:${builddir}/classes。這個值就可被解析爲build/classes。

 

內置屬性

 

如果你使用了<property> task 定義了所有的系統屬性,Ant允許你使用這些屬性。例如,${os.name}對應操作系統的名字。

 

要想得到系統屬性的列表可參考the Javadoc of System.getProperties。

 

除了Java的系統屬性,Ant還定義了一些自己的內置屬性:

 basedir   project基目錄的絕對路徑 (與<project>的basedir屬性一樣)。

 ant.file   buildfile的絕對路徑。

 ant.version  Ant的版本。

 ant.project.name  當前執行的project的名字;由<project>的name屬性設定.

 ant.java.version  Ant檢測到的JVM的版本; 目前的值有"1.1", "1.2", "1.3" and "1.4".

   

例子

<project name="MyProject" default="dist" basedir=".">

 

 <!-- set global properties for this build -->

 <property name="src" value="."/>

 <property name="build" value="build"/>

 <property name="dist" value="dist"/>

   

 <target name="init">

  <!-- Create the time stamp -->

  <tstamp/>

  <!-- Create the build directory structure used by compile -->

  <mkdir dir="${build}"/>

 </target>

  

 <target name="compile" depends="init">

  <!-- Compile the java code from ${src} into ${build} -->

  <javac srcdir="${src}" destdir="${build}"/>

 </target>

 

 <target name="dist" depends="compile">

  <!-- Create the distribution directory -->

  <mkdir dir="${dist}/lib"/>

  <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->

  <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>

 </target>

 

 <target name="clean">

  <!-- Delete the ${build} and ${dist} directory trees -->

  <delete dir="${build}"/>

  <delete dir="${dist}"/>

 </target>

 

</project>

Token Filters

 

一個project可以有很多tokens,這些tokens在文件拷貝時會被自動擴展,這要求在支持這一行爲的task中選擇過濾拷貝功能。這一功能可用filter task在buildfile中設定。

 

既然這很可能是一個有危害的行爲,文件中的tokens必須採取@token@的形式,這裏token是filter task中設定的token名。這種token語法與其他build系統執行類似filtering的語法相同,而且與大多數的編程和腳本語言以及文檔系統並不衝突,

 

注意:如果在一個文件中發現了一個@token@形式的token,但沒有filter與這個token關連,則不會發生任何事;因此,沒有轉義方法-但只要你爲token選擇合適的名字,就不會產生問題。

 

警告:如果你在拷貝binary文件時打開filtering功能,你有可能破壞文件。這個功能只針對文本文件。

 

Path-like Structures

你可以用":"和";"作爲分隔符,指定類似PATH和CLASSPATH的引用。Ant會把分隔符轉換爲當前系統所用的分隔符。

 

當需要指定類似路徑的值時,可以使用嵌套元素。一般的形式是

 <classpath>

  <pathelement path="${classpath}"/>

  <pathelement location="lib/helper.jar"/>

 </classpath>

location屬性指定了相對於project基目錄的一個文件和目錄,而path屬性接受逗號或分號分隔的一個位置列表。path屬性一般用作預定義的路徑--其他情況下,應該用多個location屬性。

 

爲簡潔起見,classpath標籤支持自己的path和location屬性。所以:

 <classpath>

  <pathelement path="${classpath}"/>

 </classpath>

可以被簡寫作:

 <classpath path="${classpath}"/>

也可通過<fileset>元素指定路徑。構成一個fileset的多個文件加入path-like structure的順序是未定的。

 <classpath>

  <pathelement path="${classpath}"/>

  <fileset dir="lib">

   <include name="**/*.jar"/>

  </fileset>

  <pathelement location="classes"/>

 </classpath>

上面的例子構造了一個路徑值包括:${classpath}的路徑,跟着lib目錄下的所有jar文件,接着是classes目錄。

 

如果你想在多個task中使用相同的path-like structure,你可以用<path>元素定義他們(與target同級),然後通過id屬性引用--參考Referencs例子。

 

path-like structure可能包括對另一個path-like structurede的引用(通過嵌套<path>元素):

 <path id="base.path">

  <pathelement path="${classpath}"/>

  <fileset dir="lib">

   <include name="**/*.jar"/>

  </fileset>

 <pathelement location="classes"/>

 </path>

  <path id="tests.path">

  <path refid="base.path"/>

  <pathelement location="testclasses"/>

 </path>

前面所提的關於<classpath>的簡潔寫法對於<path>也是有效的,如:

 <path id="tests.path">

    <path refid="base.path"/>

  <pathelement location="testclasses"/>

 </path>

可寫成:

 <path id="base.path" path="${classpath}"/>

命令行變量

 

有些task可接受參數,並將其傳遞給另一個進程。爲了能在變量中包含空格字符,可使用嵌套的arg元素。

Attribute Description Required

value 一個命令行變量;可包含空格字符。 只能用一個

line 空格分隔的命令行變量列表。

file 作爲命令行變量的文件名;會被文件的絕對名替代。

path 一個作爲單個命令行變量的path-like的字符串;或作爲分隔符,Ant會將其轉變爲特定平臺的分隔符。

 

 

例子

 <arg value="-l -a"/>

是一個含有空格的單個的命令行變量。

 <arg line="-l -a"/>

是兩個空格分隔的命令行變量。

 <arg path="/dir;/dir2:\dir3"/>

是一個命令行變量,其值在DOS系統上爲\dir;\dir2;\dir3;在Unix系統上爲/dir:/dir2:/dir3 。

 

References

 

buildfile元素的id屬性可用來引用這些元素。如果你需要一遍遍的複製相同的XML代碼塊,這一屬性就很有用--如多次使用<classpath>結構。

 

下面的例子:

 <project ... >

  <target ... >   

   <rmic ...>     

    <classpath>       

     <pathelement location="lib/"/>       

     <pathelement path="${java.class.path}/"/>       

     <pathelement path="${additional.path}"/>     

    </classpath>   

   </rmic> 

  </target>

  <target ... >

   <javac ...>

    <classpath>

     <pathelement location="lib/"/>

     <pathelement path="${java.class.path}/"/>

     <pathelement path="${additional.path}"/>

    </classpath>

   </javac>

  </target>

 </project>

可以寫成如下形式:

 <project ... >

  <path id="project.class.path"> 

   <pathelement location="lib/"/>

   <pathelement path="${java.class.path}/"/>  

   <pathelement path="${additional.path}"/>

  </path>

  <target ... >

   <rmic ...>

    <classpath refid="project.class.path"/>

   </rmic>

  </target>

  <target ... >

   <javac ...>

    <classpath refid="project.class.path"/>

   </javac>

  </target>

 </project>

所有使用PatternSets, FileSets 或 path-like structures嵌套元素的task也接受這種類型的引用。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章