基於PDE的RCP項目自動構建

持續集成包括軟件項目的持續構建與發佈,經過持續性地編譯與構建,完成項目的不斷集成。持續集成一般應用與WEB開發領域,對於RCP項目的持續集成目前業界較少。對於RCP項目的持續集成,就是經過按期執行項目自動構建程序來完成項目版本的集成與發佈,重點在於項目的自動化構建。通過筆者的研究與學習,經過本文向你們介紹一種基於PDERCP項目自動化構建方式,但願你們多多交流。php

1、簡介java

PDE (Plug-in Development Environment) headless-build是一種基於 Ant 腳本的構建方式,它主要適用於Eclipse plug-in與 Eclipse RCP項目的導出。因爲headless-build是特定於 Eclipse 插件的構建平臺,而 Eclipse 插件的編譯構建都離不開Eclipse自己的類庫與資源,於是運行headless-build以前,必須已經安裝好帶有PDE環境的Eclipse SDK以及相應的插件PDE做爲Eclipse的一個插件項目存在於Eclipse中,且不一樣EclipsePDE實現的方式略有不一樣,本文以Eclipse3.5.1爲例,介紹PDE headless-build實現自動化構建的原理及示例。app

2、原理less

(一)headless-build核心庫文件eclipse

headless-build核心腳本文件都存儲於 Eclipse 的 PDE 插件中。以Eclipse3.5.1爲例,PDE build 插件位於 plugins 目錄下的 org.eclipse.pde.build 插件目錄中。在此目錄的 lib 文件夾中包含有 pde build 庫的核心類文件,其中包括了絕大多數和 PDE build 相關的 Ant task 的實現,有興趣的讀者能夠在 org.eclipse.pde.source 源代碼插件中看到相應的代碼ide

對於咱們的 build 任務,PDE headless-build 的核心腳本文件位於 scripts 和 templates 兩個目錄下。工具

scripts 文件夾中提供了 headless-build 的基礎控制腳本。事實上不管是使用 headless-build 仍是IDE 導出,咱們都間接地經過執行這些腳本完成了一系列的過程。其中的 build.xml 文件是 build 過程的主腳本文件,在以前的啓動命令中的 –buildfile 後的值就是此 build.xml 文件的路徑。而 genericTargets.xml 則定義了在 build 過程的各個子過程的行爲。學習

templates 文件夾中則提供了一系列的模板庫。您可在 templates 下的 headless-build 目錄中找到前面所說的 allElements.xmlbuild.propertiescustomTargets.xml 文件的模板。您能夠方便地將其拷貝和修改,用做您本身的構建配置文件。fetch

(二)headless-build 的工做流程和通知機制ui

customTargets.xml 提供了對 headless-build 流程的多個節點的控制。而事實上 PDE 將 headless-build 分爲多個子過程。customTargets.xml 正是針對了此些子過程提供了回調接口,以通知和觸發用戶定製的腳本被執行。如下是 headless-build 總體流程的簡圖。

在其中,您須要提供的是最初的引入腳本(Ant 文件,批處理文件或命令行指令),以後 Eclipse 宿主會被啓動並調用您指定的一般位於 PDE 插件 scripts 目錄下的 build.xml,而此文件則會相應找到您在配置目錄中定義的 customTargets.xml 文件,執行用戶設定的回調腳本,並經過 customTargets.xml 調用 PDE 插件 scripts 下的 genericTargets.xml 啓動 PDE 內部的各項子過程的執行代碼。而在 genericTargets 中則定義了 headless-build 4個子過程fetchgenerateprocess 和 assemble,下面咱們對他們作簡單的介紹。

1Fetch

Fetch負責從源控制中下載所需構建的插件項目的源文件。其過程以下:

正如前文所述,customTargets.xml中包含了headless build執行全部過程的預置以及回調接口,開發者能夠在其中本身編寫所需的自定義腳本。Fetch操做主要在於fetchElement操做,它會根據PreBuild中用戶定義的源文件庫的文件及地址映射的MAP來以次獲取須要構建的項目源碼。同時,fetch taeget中有一個unless=skipFetch的屬性,該屬性代表當shipFetch存在時,fetch過程能夠被跳過。

(2)Generate

Generate爲每一個插件分別生成自身的構建腳本。其過程以下:

一樣能夠自定義預置及回調操做,generate的主要過程在於generateScript操做。該操做使用eclipse.buildScript方法爲每一個插件分別生成自身的構建腳本

(3)Process 

process經過運行 generate 中生成的腳本,完成對每一個插件的構建。其過程以下:

Process過程主要調用prcessElement操做,該操做經過processViaFeatureprocessFlat兩個過程完成對各個插件以及依賴插件的構建。

(4)Assemble

assemble將 process 過程當中生成的插件打包。其過程以下:

調用了assembleElement過程,根據Manifest清單中的依賴,把相關的插件集成到一塊兒,打包發佈爲一個ZIP文件,該文件解壓後點擊.exe文件可運行。(打包後的的插件會被自動集成到宿主平臺中)

3、示例

瞭解了PDE headless build的實現原理,咱們能夠爲其量身打造本身的構建腳本。爲了直接突出核心,咱們對於獲取代碼管理工具上源碼的部分就取消了,在配置文件中將SkitFetchskipMap設置爲true便可,接下來將把本地的RCP項目完成自動化構建。

(1)新建一個Plug-in Project,項目名稱爲com.rcpquickstart.helloworld,模板選擇「RCP Helloworld,新建的步驟不作詳細講解,順着嚮導操做便可。

(2)新建一個Feature Project,名稱爲com.rcpquickstart.helloworld.feature,其插件選擇com.rcpquickstart.helloworld,新建的步驟不作詳細講解,順着嚮導操做便可,完成的Feature結構以下:

(3)com.rcpquickstart.helloworld項目中新建一個Product Configratiuon,名稱爲helloworld.product,新建完之後打開文件進行以下配置。

接着爲product添加功能部件(Feature),點擊選項卡「Dependencies」,添加「com.rcpquickstart.helloworld.feature」和「org.eclipse.rcp」兩個功能部件便可。到目前爲止,咱們的RCP產品項目配置完畢。

(4)新建一個Java Project,名稱爲com.rcpquickstart.helloworld.build,接着再新建兩個文件「build.xml」和「build.properties」。該項目爲自動構建插件項目,使用ant腳本。

(5)編輯build.xml內容以下:

<projectname="com.rcpquickstart.helloworld.build"default="build">

<propertyfile="build.properties"/>

<targetname="init">

<mkdirdir="${buildDirectory}"/>

<mkdirdir="${buildDirectory}/plugins"/>

<mkdirdir="${buildDirectory}/features"/>

<copytodir="${buildDirectory}/plugins">

<filesetdir="../">

<includename="com.rcpquickstart.helloworld/**"/>

</fileset>

</copy>

<copytodir="${buildDirectory}/features">

<filesetdir="../">

<includename="com.rcpquickstart.helloworld.feature/**"/>

</fileset>

</copy>

</target>

<targetname="pde-build">

<javaclassname="org.eclipse.equinox.launcher.Main"fork="true"failonerror="true">

<argvalue="-application"/>

<argvalue="org.eclipse.ant.core.antRunner"/>

<argvalue="-buildfile"/>

<argvalue="${eclipseLocation}/plugins/org.eclipse.pde.build_${pdeBuildPluginVersion}/scripts/productBuild/productBuild.xml"/>

<argvalue="-Dtimestamp=${timestamp}"/>

<classpath>

<pathelementlocation="${eclipseLocation}/plugins/org.eclipse.equinox.launcher_${equinoxLauncherPluginVersion}.jar"/>

</classpath>

</java>

</target>

<targetname="clean">

<deletedir="${buildDirectory}"/>

</target>

<targetname="build"depends="clean, init, pde-build"/>

</project>

從腳本能夠看出,執行過程分爲Cleaninitpde-build三部,Clean爲清理構建的目標目錄,即產品構建目錄,init爲新建構建目錄結構,同時,將所需構建的插件項目以及其feature拷貝到相應的目錄下(若是是依賴多個插件的話都須要執行拷貝)。Pde-build則是啓動一個Eclipse進程調用pde構建。

(6)build.properties內容以下:

# Version of org.ecilpse.pdebuild

pdeBuildPluginVersion=3.5.1.R35x_20090820

# Version of org.eclipse.equinox.launcher

equinoxLauncherPluginVersion=1.0.201.R35x_v20090715

base=c:/helloworld-build-target

eclipseLocation=F:/Install/PDE/eclipse-SDK-3.5.1-win32/eclipse

############# PRODUCT/PACKAGING CONTROL #############

product=/com.rcpquickstart.helloworld/helloworld.product

runPackager=true

#Set the name of the archive that will result from the product build.

#archiveNamePrefix=

archivePrefix=helloworld

# The location underwhich all of the build output will be collected.

collectingFolder=${archivePrefix}

configs=win32, win32, x86

allowBinaryCycles = true

#Sort bundles depenedencies across all features instead of just within a given feature.

flattenDependencies = true

#Arguments to send to the zip executable

zipargs=

#Arguments to send to the tar executable

tarargs=

############## BUILD NAMING CONTROL ################

# The directory into which the build elements are fetched and where

# the build takes place.

buildDirectory=c:/helloworld-build

# Type of build.  Used in naming the build output.  Typically this value is

# one of I, N, M, S, ...

buildType=I

# ID of the build.  Used in naming the build output.

buildId=HelloWorld

# Label for the build.  Used in naming the build output

buildLabel=${buildType}.${buildId}

Timestamp for the build.  Used in naming the build output

timestamp=007

baseLocation=${base}/eclipse

filteredDependencyCheck=false

skipBase=true

eclipseURL=<url for eclipse download site>

eclipseBuildId=<Id of Eclipse build to get>

eclipseBaseURL=${eclipseURL}/eclipse-platform-${eclipseBuildId}-win32.zip

skipMaps=true

mapsRepo=:pserver:anonymous@example.com/path/to/repo

mapsRoot=path/to/maps

mapsCheckoutTag=HEAD

#tagMaps=true

mapsTagTag=v${buildId}

skipFetch=true

############# JAVA COMPILER OPTIONS ##############

# Specify the output format of the compiler log when eclipse jdt is used

logExtension=.log

# Whether or not to include debug info in the output jars

javacDebugInfo=false 

# Whether or not to fail the build if there are compiler errors

javacFailOnError=true

# Enable or disable verbose mode of the compiler

javacVerbose=true

須要注意幾個關鍵配置:

pdeBuildPluginVersion

PDE BUILD的版本號,能夠在Eclipse目錄下的Plugin文件夾裏找到org.eclipse.pde.build_3.5.1.R35x_20090820文件夾,文件夾名後面的字符爲PDE版本;

equinoxLauncherPluginVersionequinoxLauncher版本號,用於Eclipse項目構建的進程,其在Eclipse目錄下的Plugin文件夾裏找到

org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar ,後面字符爲其版本號;

BaseRCP runtime BinaryDelta Pack存放的目錄路徑,其兩者包括了RCP運行時環境所需插件以及大量跨平臺插件。

eclipseLocation:執行構建的Eclpise路徑

Product:須要發佈的Product文件

buildDirectory:執行構建的目標目錄,包括了構建時產生的文件

skipMapstrue,跳過源文件的MAP獲取。

skipFetchtrue,跳過從源代碼管理工具獲取源文件。

(7)準備構建環境。根據配置文件中配置路徑,分別在C盤創建「helloworld-build」和「helloworld-build-target」兩個文件夾,同時,從eclipse官網上下載「eclipse-RCP-3.5.1-win32.zip」和「eclipse-3.5.1-delta-pack.zip」壓縮文件,將其解壓到剛纔的helloworld-build-target目錄下(相同的文件能夠覆蓋),下載地址:

http://archive.eclipse.org/eclipse/downloads/drops/R-3.5.1-200909170800/index.php

(8)執行build.xml,待構建完成後,在「/helloworld-build/I.HelloWorld」目錄下找到HelloWorld-win32.win32.x86.zip,其爲構建好的RCP項目,解壓後目錄結構以下:

雙擊helloworld.exe可運行程序。

相關文章
相關標籤/搜索