Gradle多專案構建


Gradle可以輕鬆處理各種大小規模的專案。小專案由一個單一的構建檔案和一個原始碼樹構成。 大專案可以將其拆分成更小的,相互依賴的模組,以便更容易理解。Gradle完美支援這種多專案構建的場景。

多專案構建的結構

這種構建有各種形狀和大小,但它們都有一些共同的特點 -

  • 在專案的根目錄或主目錄中都有一個settings.gradle檔案。
  • 根目錄或主目錄都有一個build.gradle檔案。
  • 具有自己的*.gradle構建檔案的子目錄(某些多專案構建可能會省略子專案構建指令碼)。

要列出構建檔案中的所有專案,可以使用以下命令。

D:/water>gradle -q projects

如果命令執行成功,將獲得以下輸出。

D:/water>gradle -q projects

------------------------------------------------------------
Root project
------------------------------------------------------------

Root project 'water'
+--- Project ':bluewhale'
/--- Project ':krill'

To see a list of the tasks of a project, run gradle <project-path>:tasks
For example, try running gradle :bluewhale:tasks

報告將顯示每個專案的描述(如果指定)。可以使用以下命令指定描述。 將其貼上到build.gradle檔案中。

description = 'The shared API for the application'

指定常規構建組態

在根專案中的build.gradle檔案中,常規組態可以應用於所有專案或僅應用於子專案。

allprojects {
   group = 'com.example.gradle'
   version = '0.1.0'
}

subprojects {
   apply plugin: 'java'
   apply plugin: 'eclipse'
}

這指定了一個公共com.example.gradle組和一個0.1.0版本到所有專案。subprojects 閉合所有應用對子專案通用組態,但不對根專案應用,如:allprojects閉合。

專案指定組態和依賴關係

核心uiutil子專案也可以有自己的build.gradle檔案,如果它們有特定的需求,那麼一般不會應用根專案組態。

例如,ui專案通常具有對核心專案的依賴性。所以在ui專案中需要有組態自己的build.gradle檔案來指定這個依賴。

dependencies {
   compile project(':core')
   compile 'log4j:log4j:1.2.17'
}

專案依賴項可使用專案方法指定。

Gradle多專案構建的範例

定義公共行為

讓我們看看下面的一個例子的專案樹。這是一個多專案構建,其中包含一個名為water的根專案和一個名稱為bluewham的子專案。在這個範例中,我們把在建立一個目錄D:/water,作為根專案的目錄。
多專案樹 - waterbluewham專案的構建布局如下圖所示 -

water/
  build.gradle
  settings.gradle
  bluewhale/

首先,建立一個檔案 settings.gradle 並寫入以下程式碼內容 -

include 'bluewhale'

bluewhale專案的構建指令碼在哪裡? 在Gradle中構建指令碼是可選的。顯然,對於單個專案構建,如果沒有構建指令碼那麼專案是沒有意義的。但對於多專案構建情況不同。讓我們看看water專案的構建指令碼並執行它,建立一個檔案build.gradle 並寫入以下程式碼:

Closure cl = { task -> println "I'm $task.project.name" }
task hello << cl
project(':bluewhale') {
    task hello << cl
}

並執行 gradle -q hello 輸出結果如下 -

D:/water>gradle -q hello
I'm water
I'm bluewhale

Gradle允許從構建指令碼中存取多專案構建的任何專案。 Project API提供了一個名稱為project()的方法,它將一個路徑作為引數,並返回此路徑的Project物件。
為每個專案顯式新增任務是不方便的。我們可以稍微做一下調整,先將另一個名稱為krill的專案新增到多專案構建中。
現在目錄結構看起來如下所示 -

water/
  build.gradle
  settings.gradle
  bluewhale/
  krill/

再次編輯 settings.gradle 將以下程式碼加入到檔案中 -

include 'bluewhale', 'krill'

現在我們已經重寫 water 構建指令碼並將其放在一行中。
將檔案water專案中的 build.gradle 並寫入以下程式碼:

allprojects {
    task hello << { task -> println "I'm $task.project.name" }
}

並執行 gradle -q hello 輸出結果如下 -

D:/water>gradle -q hello
I'm water
I'm bluewhale
I'm krill

這是如何工作的? Project API提供了一個屬性allprojects,它返回當前專案及其下面所有子專案的列表。 如果使用閉包呼叫allprojects,則閉包的語句將委派給與所有專案相關聯的專案。當然也可以通過allprojects.each進行疊代,但這將更冗長。

其他構建系統使用繼承作為定義公共行為的主要方法。Gradle也為專案提供繼承,您將在後面看到。但Gradle使用組態注入作為定義公共行為的常用方式。這是一種非常強大和靈活的組態多專案構建的方式。共用組態的另一種可能性是使用公共外部指令碼。

子專案組態

Project API還提供了一個僅用於存取子專案的屬性。

定義公共行為

定義所有專案和子專案的公共行為,編輯 build.gradle 檔案使用以下程式碼 -

allprojects {
    task hello << {task -> println "I'm $task.project.name" }
}
subprojects {
    hello << {println "- I depend on water"}
}

並執行 gradle -q hello 輸出結果如下 -

D:/water>gradle -q hello
I'm water
I'm bluewhale
- I depend on water
I'm krill
- I depend on water

注意兩個程式碼片段參照「hello」任務。 第一個,它使用「task」關鍵字,構建任務並提供它的基本組態。第二部分不使用「task」關鍵字,因為它進一步組態現有的「hello」任務。只能在專案中構建一次任務,但可以新增任意數量的程式碼塊以提供其他組態。

新增指定行為

可以在常見行為之上新增指定的行為。要應用這個特定的行為,通常將專案特定的行為放在專案的構建指令碼中。我們可以為 bluewhale 專案新增專案特定的行為,如下所示:
編輯 build.gradle 檔案使用以下程式碼 -

allprojects {
    task hello << {task -> println "I'm $task.project.name" }
}
subprojects {
    hello << {println "- I depend on water"}
}
project(':bluewhale').hello << {
    println "- I'm the largest animal that has ever lived on this planet."
}

並執行 gradle -q hello 輸出結果如下 -

D:/water>gradle -q hello
I'm water
I'm bluewhale
- I depend on water
- I'm the largest animal that has ever lived on this planet.
I'm krill
- I depend on water

正如上面所說的,通常把專案特定的行為放入這個專案的構建指令碼中。現在重構程式碼並向krill專案新增一些專案特定的行為。

定義 krill 專案的具體行為

構建布局如下圖中所示 -

water/
  build.gradle
  settings.gradle
  bluewhale/
    build.gradle
  krill/
    build.gradle

settings.gradle 檔案的內容 -

include 'bluewhale', 'krill'

bluewhale/build.gradle 檔案的內容 -

hello.doLast {
  println "- I'm the largest animal that has ever lived on this planet."
}

krill/build.gradle 檔案的內容 -

hello.doLast {
  println "- The weight of my species in summer is twice as heavy as all human beings."
}

build.gradle 檔案的內容 -

allprojects {
    task hello << {task -> println "I'm $task.project.name" }
}
subprojects {
    hello << {println "- I depend on water"}
}

並執行 gradle -q hello 輸出結果如下 -

D:/water>gradle -q hello
I'm water
I'm bluewhale
- I depend on water
- I'm the largest animal that has ever lived on this planet.
I'm krill
- I depend on water
- The weight of my species in summer is twice as heavy as all human beings.

參考