從零開始學習Gradle之三---多項目構建

           

             隨著信息化的快速發展,IT項目變得越來越復雜,通常都是由多個子系統共同協作完成。對于這種多系統、多項目的情況,很多構建工具都已經提供了不錯的支持,像maven、ant。Gradle除了借鑒了ant或者maven的繼承的方式定義子項目,也提供了一種更為方便的集中配置的方式,大大減少了構建帶來的復雜度。除此之外,Gradle還提供了清晰的Project樹模型來映射多項目的組織結構。下面,讓我們了解一下如何使用Gradle構建多項目。

           

          1. 多項目定義及結構

           在Gradle中,使用文件settings.gradle定義當前項目的子項目,格式如下所示: 

          include 'sub-project1', 'sub-project2', 'sub-project3',

          它表示在當前的項目下建立三個子項目,分別為'sub-project1', 'sub-project2', 'sub-project3'。默認情況下,每個子項目的名稱對應著當前操作系統目錄下的一個子目錄。

          當Gradle運行時,會根據settings.gradle的配置情況,構建一個單根節點的項目樹。其中的每個子節點代表一個項目(Project),每個項目都有一個唯一的路徑表示它在當前樹中的位置,路徑的定義方式類似:

          Root:<Level1-子節點>:<Level2-子節點>:<Level3-子節點>

          也可以簡寫成“:<Level1-子節點>:<Level2-子節點>:<Level3-子節點>”。借助這種路徑的定義方式,我們可以在build.gradle去訪問不同的子項目。另外,對于單項目,實際上是一種特殊的、只存在根節點,沒有子節點的項目樹。

          例如,我們有個產品A,包括以下幾個組件core,web,mobile。分別代表"核心邏輯"、"網站"、“手機客戶端”。 因為每個組件是獨立的部分,這個時候最好我們能定義多個子項目,讓每個子項目分別管理自己的構建。于是我們可以這樣定義A/settings.gradle

          include 'core', 'web', 'mobile'

          按照之前描述的,core組件對應A/core目錄,web組件對應A/web目錄,mobile組件對應A/mobile目錄。接下來,我們就可以在每個組件內部,定義build.gradle負責管理當前組件的構建。

          Gradle提供了一個內建的task 'gradle projects',可以 幫助我們查看當前項目所包含的子項目,下面讓我們看看gradle projects的輸出結果:

          $ gradle projects
          :projects
          ------------------------------------------------------------
          Root project
          ------------------------------------------------------------
          Root project 'A'
          +--- Project ':core'
          +--- Project ':mobile'
          \--- Project ':web

          結果一目了然,首先是Root級別的項目A,然后是A下面的子項目'core', 'mobile', 'mobile'

          最終的文件以及目錄結構如下所示:

          A
             --settings.gradle
             --build.gradle
             --core
               --build.gradle
             --web
                --build.gradle
             --mobile
                --build.gradle

          如果你不喜歡這種默認的結構,也可以按照如下方式定義子項目的名稱和物理目錄結構:

          include(':core)
          project(':core').projectDir = new File(settingsDir, 'core-xxx') 

          include(':web)
          project(':web').projectDir = new File(settingsDir, 'web-xxx') 

          include(':mobile)
          project(':mobile').projectDir = new File(settingsDir, 'mobile-xxx') 

          在這個例子中,子項目core實際上對應的物理目錄為A/core-xxx,web實際上對應的是A/web-xxx,mobile也類似。

          雖然我們更改了子項目的物理目錄結構,不過由于我們在build.gradle中使用的是類似 “ :<SubProject>”的方式訪問對應的子項目,所以目錄結構的改變,對我們Gradle的構建腳本并不會產生影響。

          接下來,考慮一個更復雜的情況,隨著產品的發展,mobile這個組件慢慢的劃分成了Android和IOS兩個部分,這時我們只需要在目錄A/mobile下定義新的settings.gradle,并加入如下部分:

          include 'android', 'ios'

          現在,mobile組件下將存在兩個新的子項目 "android"和"ios"

          于是,這時候'gradle projects'的目錄結構就變成

          A
             --settings.gradle
             --core
                --build.gradle
             --web
                --build.gradle
             --mobile
                --settings.gradle
                --ios
                  --build.gradle
                --android
                  --build.gradle

          2. 多項目的集中配置

          對于大多數構建工具,對于子項目的配置,都是基于繼承的方式。Gradle除了提供繼承的方式來設置子項目,還提供了另外一種集中的配置方式,方便我們統一管理子項目的信息。下面看一個例子,打開A/build.gradle,輸入如下部分:

          allprojects {
              task hello << {task -> println "I'm $task.project.name" }
          }
          subprojects {
              hello << {println "- I am the sub project of A"}
          }
          project(':core').hello << {
                println "- I'm the core component and provide service for other parts."
          }

          對于上面所示的代碼,已經很表意了:

          allprojects{xxx}  這段代碼表示,對于所有的project,Gradle都將定義一個名稱是hello的Task { println "I'm $task.

          subprojects{xxxx}的這段代碼表示,對于所有的子project,將在名稱為hello的Task上追加Action {println "- I am the sub project of A"}

          注意:關于Task和Action的關系,請看我之前寫的本系列的第一部分。

          project(':core')的這段代碼表示,對于名稱為core的project,將在名稱為hello的Task上追加Action { println "- I'm the core component and provide service for other parts." }


          3. 多項目的Task執行

          之前我們已經了解了多項目的結構以及如何通過路徑去訪問子項目。現在讓我們看看如何使用Gradle來執行多項目。

          在Gradle中,當在當前項目上執行gradle <Task>時,gradle會遍歷當前項目以及其所有的子項目,依次執行所有的同名Task,注意:子項目的遍歷順序并不是按照setting.gradle中的定義順序,而是按照子項目的首字母排列順序。

          基于剛才的例子,如果我們在根目錄下,執行gradle hello,那么所有子項目的“hello” Task都會被執行。如果我們在mobile目錄下執行gradle hello,那么mobile、android以及IOS的“hello” Task都會被執行。關于該例子的運行結果,這里就不貼出來了。大家如果有興趣的話可以試試。

          4. 總結
          這篇文章主要描述了使用Gradle管理多項目的知識。相比Ant或者Maven,Gradle提供了更靈活的配置方式。更重要的是,Gradle還提供了很多內建的Task幫助我們查看或者管理項目。這次就先聊到這里,下次我們來看看Gradle的生命周期。

          posted on 2012-07-12 21:33 想飛就飛 閱讀(29955) 評論(2)  編輯  收藏 所屬分類: Groovy/Grails

          評論

          # re: 從零開始學習Gradle之三---多項目構建 2014-05-30 17:45 啦啦

          后面什么情況,沒更新了啊?  回復  更多評論   

          # re: 從零開始學習Gradle之三---多項目構建 2014-05-30 18:32 繁星之海

          更新...  回復  更多評論   

          公告


          導航

          <2012年7月>
          24252627282930
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234

          統計

          常用鏈接

          留言簿(13)

          我參與的團隊

          隨筆分類(69)

          隨筆檔案(68)

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 莱芜市| 富裕县| 乌恰县| 永靖县| 漳浦县| 洛隆县| 和硕县| 冀州市| 永泰县| 郸城县| 德保县| 南通市| 灵璧县| 新河县| 公主岭市| 阿荣旗| 荔波县| 仙居县| 延吉市| 栾城县| 宁阳县| 芜湖县| 岗巴县| 鄂托克前旗| 莱西市| 敦煌市| 许昌县| 旬邑县| 安国市| 吴江市| 濮阳市| 宁乡县| 洛南县| 台中县| 自治县| 佛冈县| 濮阳县| 襄汾县| 大同县| 香河县| 麦盖提县|