Jenkinsant介紹(學習筆記五)

sktj發表於2018-04-26

轉載自:https://www.cnblogs.com/pixy/p/4792887.html

Ant的由來(序)

James Duncan Davidson當年用純Java開發Tomcat的時候,不僅想讓它跨平臺執行,還想要在不同的作業系統上都能夠進行開發和構建。這種較大的專案的編譯構建過程是很複雜,需要用到很多工具和指令碼(比如GNU make,Shell指令碼,批處理檔案等等)處理資源、處理依賴項、控制編譯過程、打包(Jar,War),某些特別的Java技術如EJB、RMI在編譯打包時還需要特別處理。James嘗試了很多工具和方案,最後的結論就是太TM難用了。

首先是慢。舉個例子,編譯java程式碼要用javac,javac其實就是包裝了下java用於編譯的Java工具類(JDK工具都是用純Java寫的,JDK目錄下的那些exe檔案實際上都是呼叫Java類來實現具體功能的)。但是用make,shell這些工具每次呼叫javac,都要開新程式建立新的VM例項,如果每編譯一個檔案呼叫一次javac,開銷就老大了,不慢才怪呢。呼叫命令後還必須要解析控制檯輸出資訊才能知道執行情況,更不可能使用Java提供的異常和錯誤資訊來確定執行狀態。

然後是累。make,shell指令碼要跨平臺太困難,在不同的系統上要用不同的版本;而且要編寫shell指令碼和make指令碼(make只是shell基礎上的語言擴充套件),得有linux程式設計基礎,門檻還是比較高的;這類指令碼編寫起來容易出錯(Makefile的tab問題能煩死人),難以除錯。總之,如果構建過程用了一堆這樣的指令碼,維護起來肯定是又煩又累。慢的問題還能通過一次編譯一批檔案來緩解,但這個問題可就無解了。

James實在受不了了,就自己用Java開發了一個小工具,就是Ant,用來編譯和打包Java專案。構建中用到JDK中工具時都是直接呼叫Java類,而不是從命令列呼叫,慢的問題就解決了。構建中直接向Java編譯類提供或獲取資料,編譯過程中有什麼問題,也能進行錯誤或異常處理。因為是用Java寫的,天然就是可以跨平臺的使用的。Ant從配置檔案中讀取資料來控制構建過程,剛開始的時候用Properties檔案,但是Properties檔案難用表達比較複雜的層次結構關係,當他把Ant解決方案設計成”工程-目標-任務”的層次結構時,改用XML作為構建配置檔案,XML檔案是很好理解和掌握的,學習門檻變得非常低。再後來又利用反射功能,支援自定義任務,Ant的功能就不再僅限於構建Java專案了,可以使用在更廣泛的場合。至此Ant就基本成型了。

James完成這個工具之後,自己用著很爽並且在網上共享,然後就沒怎麼再關注了,直到後來有一天忽然發現老多人都已經在用他的這個傑作了。James說他很慶幸當時沒有把精力一直花在這上面,否則可以能會不自覺的加入很多更本不必要的功能,讓Ant變得臃腫複雜,反而不好了。

這個故事除了說了Ant的來源和特點外,還有一點啟示:如果遇到問題,已有的工具都不能滿足需求,就應當另找一個。如果不存在這樣的工具,就自己動手建立一個。然後與大家共享,其他數以千計的人可能有著類似的難題。

第一章 Ant入門

ant的使用非常簡單:安裝好Ant後(最好配置Path環境變數),在構建檔案中(預設名字為build.xml)配置好構建任務,然後呼叫ant命令,配置的任務就開始執行了。

1.編寫構建檔案

建立一個用於編譯和打包Java專案的配置檔案build.xml(名字可以隨便起,如mybuild.xml,執行的時候用-f 選項指定這個檔案就可以):

這個配置檔案很好理解,用任何文字編輯器都能編寫,只要保證是一個合法的XML檔案並且用了正確的標籤和屬性,就可以使用ant執行。

根據這個配置檔案就可以看出。Ant把任何任務都分成了3層。

最頂層的Project

目標Target(可以在ant命令中呼叫的基本單位)。如clean, compile, jar 等,在命令列可以這樣呼叫:ant clean或  ant clean jar。Target之間可以存在依賴關係,一個Target執行前會先執行它依賴的那些Target。Project可以設定一個預設的Targe, ant命令中不指定任何target時就呼叫這個預設的。

任務Task。

各種Task可以執行各種不同的具體任務。如mkdir, delete, javac, jar等。Task可以分3種,核心任務和可選任務有100多種,常用的功能全都覆蓋了

核心Task。Ant內建的任務

可選任務。第三方提供的,把相應的Jar包放到Ant安裝目錄的lib目錄下就能使用。

自定義任務

Task詳細說明可以檢視官方文件:http://ant.apache.org/manual/tasklist.html

Ant檔案中還能用Property標籤配置屬性值,在定義之後的其他地方就可以引用,避免硬編碼。

所有的構建檔案都要有且只能有一個元素,其中至少要有一個 元素。project的defualt屬性沒有預設值,如果這個屬性沒有設定,不指定Target執行ant不會呼叫任何target。

2.執行Ant

ant命令語法如下,詳細選項說明列在後面。

ant [option [option…]]  [target [target…]]

呼叫Ant時預設會在當前目錄中查詢預設的構建檔名:build.xml。 

當然也可以用ant -f buildfile的方式手動指定構建檔案(-f, -buildfile, -file都是等效的)。

呼叫Ant時可以指定一個或多個要執行的Target。如果不指定就呼叫Project標籤default屬性中配置的預設Target(上面這個例子中就是compile目標)。

以上面的構建配置檔案為例,下面的幾種呼叫都可以:

ant呼叫預設構建檔案(build.xml)中的預設目標(compile)ant -f mybuild.xml  jar呼叫構建檔案mybuild.xml中的jar目標ant clean jar呼叫預設構建檔案(build.xml)中的clean和jar目標。需要注意多個目標會按呼叫先後順序執行。如果呼叫ant jar clean就是先編譯打包(jar),然後全清理掉(clean),就白乾了。

Ant執行時會按執行順序顯示每個Target的名字,也會顯示每個任務的名字([任務名])和任務中輸出的資訊。直接呼叫ant的輸出結果為:

Buildfile: e:wsJavaAntDemouild.xml

clean:

  [delete] Deleting directory e:wsJavaAntDemouild

prepare:

    [mkdir] Createddir: e:wsJavaAntDemouild

    [mkdir] Createddir: e:wsJavaAntDemouildclasses

    [mkdir] Createddir: e:wsJavaAntDemouildlib

compile:

    [javac] Compiling 2 sourcefilesto e:wsJavaAntDemouildclasses

jar:

      [jar] Building jar: e:wsJavaAntDemouildlibantDemo.jar

all:

BUILD SUCCESSFUL

Total time: 0 seconds

3.檢視構建檔案中所有目標

構建檔案中的目標description屬性可有可無,除了方便人看外沒什麼卵用。有沒有這個屬性叫法也不一樣的(沒有實際作用),有該屬性的叫主目標,沒有的叫子目標。下面這個命令可以列出構建檔案中的所有目標和description資訊。

ant [-f BUILDFILE] -projecthelp 

4.Ant命令選項

-h,  -help   檢視幫助資訊

-p,  -projecthelp  檢視構建檔案中的所有目標資訊

-version  顯示Ant版本

-q,  -quiet   抑制並非由構建檔案中echo任務所產生的大多數輸出訊息

-S,  -silent   只顯示Task輸出和構建失敗資訊

-v,  -verbose   顯示構建過程中每個操作的詳細訊息, 不能和-debug同時使用

-d,  -debug     顯示Ant和任務開發人員已經標誌位除錯資訊的訊息。不能與-verbose同時使用

-e,  -emacs     對日誌訊息進行格式化,使其能夠Emacs的shell模式解析。具體就是列印任務訊息時不縮排也不輸出前面的 [任務名]

-diagnostics    顯示對除錯有用的資訊

-f ,  -buildfile , -file 指定一個構建檔案,而不是使用預設的build.xml

-D=通過命令列向構建過程中傳遞屬性值

-propertyfile 從property檔案中載入屬性值並傳遞到構建過程

-s ,  -find     指定Ant應當使用的構建檔案,如果指定的filename檔案在當前目錄中沒找到,就到父目錄中進行搜尋,直到到達檔案系統的根,還找不到則構建失敗。

-k,  -keep-going    執行不依賴失敗目標的所有目標。

-lib  指定查詢jars和classes的目錄

-l  , -logfile   將日誌重定向到指定檔案

-logger   指定一個類來處理Ant的日誌記錄。該類必須實現了org.apache.tools.ant.BuildLogger介面

-listener   為Ant設定一個監聽類,將其增加到Ant的監聽器列表中。Ant與IDE或其他程式整合時非常有用,後面會專門寫這個。

-inputhandler  指定用於處理輸入請求的類

-main   覆蓋Ant正常的入口點

-noinput    不允許互動式輸入

-autoproxy   Java1.5+,使用OS的代理設定

-nice number

-nouserlib

-noclasspath

第二章 安裝和配置

基本使用

下載ant釋出包

解壓縮到一個目錄既可

將該目錄下的子目錄bin新增到PATH環境變數

高階配置

 留坑待填….

第三章 構建檔案

構建檔案需要根據具體專案的特性編寫,不過同一型別的專案基本上是可以使用一套構建配置的。

Java提供了用於構建的Java工具庫,使用Java語言編寫Ant是最容易實現和維護的。XML有豐富的解析類庫,並且被開發人員廣泛使用,也能夠表達Ant的資料模型,使用XML作為構建檔案時最好的選擇。

XML是一種樹形的文件物件模型(DOM),其中的Project,Target等元素與Ant的模型元件相對應。

1.Ant的構建塊

Project(工程)   任何構建檔案的第一個元素必須是標籤,而且只能有一個。

name屬性 工程的名字,也是構建檔案的識別符號。

default屬性 執行Ant不指定Target時,預設執行的Target。可以設定成一個構建檔案中定義的Target名字。推薦預設Target顯示構建檔案的幫助資訊或者執行完成的構建。

basedir屬性 定義工程的根目錄,一般情況下都是” . “,也就是構建檔案所在的目錄(不是執行Ant命令是的目錄)。在一個多層次的專案中,basedir還可以定義不同的參考點。

Target(目標) 一個Project可以包含多個Target,一個總的任務過程可以拆分成幾個target,每個Target可以單獨呼叫。可以把target理解成能夠單獨執行的一個個步驟(階段)。具體怎麼拆分這個總任務,拆分粒度是粗還是細,把哪些Task放在哪幾個Target中,都是編寫構建檔案要考慮的問題。一般來說,粒度更小可以更靈活的組合,有些target失敗也不會影響另一些的執行。但是粒度也不能太小,太小了會很瑣碎不好維護。

name屬性

depends屬性

description屬性

前面的build.xml例項中,編譯打包拆成了兩個target,如果每次這兩個target都是一起被呼叫的,把他們放在一個target中也是可以的。

Task(任務)  任務是構建檔案中的最小構建單位。通過Target把一個總過程組織成了幾個大的Target目標(步驟),但是Target並不做任何具體的工作,Target下面有包含一些Task,所有的具體工作都是靠這些task來完成。Ant提供非常多的Task,如編譯,大包,檔案系統操作等等。Ant中每個任務對應於Ant物件模型中的一個Java物件,要自定義新的任務就是要編寫執行該任務類然後提供給Ant呼叫。很多系統命令也都是用Task包裝,而不是直接呼叫shell命令,在不同的作業系統上Task的使用方式是完全一致的。

構建檔案中任務標籤內部也可以有很多層次。但是Task內部的這些層次結構和Java類的層次結構沒有任何關係了。

Task標籤不再有統一的屬性和子元素,內部層次完全取決於具體的任務。

2.資料元素(data element)

構建檔案中除了與任務構建過程相關的元素外。還包括了儲存資料的變數和抽象資料型別等元素。資料元素有兩類:Property和DataType

Property

表示字串型的“鍵-值”對,只能用在可使用字串的位置。

Propery和Java中的Property物件是相容的,可以使用Property檔案或JVM命令列-Dproperty=value選項,在執行ant時動態定義。

可以使用${propName}的形式引用Property資料。

property資料定義和引用

載入config.properties檔案中定義的property資料

通過命令列在執行時動態定義propery資料

ant mytarget -Dname=value

DataType

Property資料值都是字串,ant並不知道這些字串代表了什麼物件。如果將包含很多個Jar檔案的長串路徑儲存在Property資料中,就很容易出錯,修改也不方便。

Ant還提供了很多種具體的資料型別(DataType),各種資料型別能夠更清晰地描述特定型別的資料,如Path(路徑), FileSet(檔案集合,可以使用萬用字元)等,修改起來更加方便。

使用Property表示路徑和使用Path/FileSet物件表示路徑的對比:

3.工程結構和構建檔案

要編寫工程的構建檔案,必須要了解專案的結構。專案型別不同,專案結構往往存在較大的差異(如Web專案和GUI專案),沒有最佳的工程組織模式。工程結構是比較複雜的,需要考慮跨平臺(使用相對路徑),依賴自包含無外部需求,功能模組和不同型別檔案分離等等。

以下面的專案結構為例:

projectName

build.xml      構建檔案

src/

api

module

doc/       專案相關文件(非JavaDoc文件,不能自動生成),如readme,license等

lib/        依賴的外部庫,統一依賴

bin/   可選目錄,包含安裝、執行等指令碼或者是難找的、定製的可執行工具(為跨平臺,最好不要使用可執行程式)

build/     構建產出目錄

classes/

doc/   javadoc產出

lib/    

bin/

dist/     最終用於釋出的目錄(內容一般都是從其他目錄複製而來)

lib/

bin/

doc/

config/

 編寫構建檔案


相關文章