1. 程式人生 > >Gradle之重新認識Gradle(專案結構、命令列、task、構建Java專案、包裝器)

Gradle之重新認識Gradle(專案結構、命令列、task、構建Java專案、包裝器)

前言:之前一直接觸使用Gradle完成Android專案的自動化構建,所謂重新認識Gradle是因為最近看了《Gradle IN Action》一書,對gradle進行了一次全面的重新的認識。所以決定以系列部落格,來完成自己對Gradle學習之路的一個總結。關於書中的一些原始碼我備份了一份在github上:https://github.com/ChenSWD/CopyGradleInAction,有該書的pdf版本,所有目錄名以”-註釋“結尾的是在部落格中引用過的指令碼,都是添加了程式碼註釋的。

一、重新梳理認識一些概念

1、專案自動化:有效的專案自動化是促使軟體成功交付的關鍵因素,是以一種可重複、可持續的方式構建和交付軟體。它的好處有:①防止手動介入專案的交付帶來的耗時和錯誤,畢竟人為的編譯拷貝等操作總會避免不了犯錯;②可以建立重複的構建,即:將重複有序的軟體構建過程組裝起來;③不依賴於特定型別的作業系統,具有可移植性。

2、構建工具:構建工具是一種可程式設計工具,能夠讓你以可執行和有序的任務來表達自動化的需求。如圖,每個任務代表一個工作單元,這些任務的執行順序非常重要,編譯任務就必須要在拷貝之前完成。Java的構建工具一般有Ant、Maven、當然還有Gradle。 這裡寫圖片描述

3、Gradle:Gradle是基於JVM構建工具的新一代版本,它使用一種強大且具有表達性的基於Groovy的領域特定語言(DSL),而不是XML(Ant、Maven基於xml),允許使用Java或者Groovy語言編寫定製邏輯,其實Gradle就是Groovy,它提供了基於Java的語法糖,你編寫的所有指令碼都是Groovy,能夠以程式語言來表達你需要的構建是Gradle的一大亮點。Gradle的座右銘:“讓不可能成為可能,讓可能變得簡單,讓簡單變得優雅”

這裡寫圖片描述 Gradle的特性簡單介紹: ①可表達性的構建語言和底層API:在Gradle指令碼中每一個元素都有一個與Java類一對一的對映,如每一個構建指令碼對映成Gradle API中的Project型別的一個例項,dependencies配置塊觸發project例項的dependencies()方法。 ②靈活的約定:Gradle最主要的思想之一就是針對你的專案給予引導和有意義的預設值,Gradle具有統一的專案結構佈局(如圖),Gradle中的每個Java專案都確切的知道原始碼和測試類檔案的位置,知道如何編譯原始碼,執行單元測試,釋出程式碼,這些任務都被完全整合到了構建的生命週期中。 這裡寫圖片描述
③魯棒和強大的依賴管理:Gradle提供了一個基礎設施去管理解析、獲取和儲存依賴的複雜性,一旦相關的依賴被下載到本地快取中,那麼在你的專案中就可以使用了。

二、Gradle的基本使用 1、每一個Gradle構建都是從一個指令碼開始的。Gradle預設的構建指令碼的名字是build.gradle,在執行gradle命令時,就會去尋找build.gralde檔案。使用gradle命令列要配置gradle環境變數。 ①簡單使用,從HelloWorld開始:建立一個build.gradle檔案,定義一個helloWorld的任務(task),將列印語句新增到action中(doLast)。

task helloWorld{
    doLast{
        println('Hello World!')
    }
}
執行該task:
gradle -q helloWorld
Hello World!

②簡單的任務依賴:

task startSession {
    doLast {
        chant()
    }
}

def chant() {
    /**每個指令碼都帶有一個ant屬性,它賦予了直接訪問ant任務的能力*/
    ant.echo 'Repeat after me...'
}
/**這是一個動態的task,可以在執行的時候指定它的名字。
 * 該方法是Groovy在java.lang.Number中擴充套件的times方法,
 * 建立3個新的task,隱含變數it(counter)指定迴圈的次數,這裡使用計數器來建立task的名字.*/
3.times { counter ->
    task "yayGradle$counter" {
        doLast {
            println 'Gradle rocks'
        }
    }
}
/**dependsOn說明了task之間的依賴,gradle確保被依賴的task總是在其之前執行。*/
yayGradle0.dependsOn startSession
yayGradle2.dependsOn yayGradle1, yayGradle0
task groupTherapy(dependsOn: yayGradle2)

執行輸出:
gradle groupTherapy
> Task :startSession 
[ant:echo] Repeat after me...
> Task :yayGradle0 
Gradle rocks
> Task :yayGradle1 
Gradle rocks
> Task :yayGradle2 
Gradle rocks

這裡寫圖片描述

2、Gradle命令列:我們是通過命令列來執行gradle指令碼的,如之前gradle helloWorld就直接可以執行helloWorld task。 ①tasks 命令:gradle -q tasks命令可以顯示該指令碼所有可用的task,gradle -q tasks –all 可以獲得關於task的更多資訊。 ②gradle命令可以一次執行多個任務,gradle yayGradle0 groupTherapy命令會先執行yayGradle0 任務在執行groupTherapy任務,但是任務只會執行一次,yayGradle0 作為groupTherapy的依賴也只會執行一次。 ③gradle可以以守護程序開啟,gradle helloWorld –daemon,啟動後,gradle會在後續的構建中重用之前建立的守護程序,避免啟動時造成開銷。

3、構建Java專案。Gradle外掛可以自動化執行相關構建的任務,Java外掛是Gradle自身裝載的一個外掛,它為專案建立一個標準的專案佈局,並確保有意義、有順序地執行任務。 ①使用Java外掛:在build.gradle 檔案中加入:

apply plugin:'java'

該行程式碼代表專案使用Java外掛構建你寫的Java程式碼,該外掛會構建出一個JAR包。Gradle是怎麼找到原始碼的位置呢?Java外掛引入的約定之一就是原始碼的位置,在預設情況下,外掛會到src/main/java目錄下查詢。所以,需要將要參與編譯構建的程式碼放到該目錄下面,IDE一般在建立相關專案時就已經建立了相關的專案結構。 ②開始構建。Java外掛提供一個任務叫做build,該任務可以以正確的順序編譯原始碼,組裝成JAR檔案。 build.gradle指令碼檔案如下,指令碼可以動態的設定原始碼的目錄和生成檔案的目錄,這裡修改為out目錄下。我們知道JAR檔案有可執行和不可執行兩種,可執行的JAR檔案(可以通過java -jar 命令執行的JAR檔案)需要有下面的Main-Class相關設定(要設定主類),否則只能當做普通工具包使用。

apply plugin: 'java'
/**定義專案的版本*/
version = 0.1
/**jdk版本*/
sourceCompatibility = JavaVersion.VERSION_1_7

sourceSets {
    main {
        java {
            /**設定專案的原始碼目錄是src*/
            srcDirs = ['src']
        }
    }
    test {
        java {
            /**設定專案的測試程式碼目錄是test*/
            srcDirs = ['test']
        }
    }
}
/**修改build生成目錄,預設是build目錄*/
buildDir = 'out'
/**設定主類,設定了該屬性生成的JAR檔案才能被執行*/
jar {
    manifest {
        attributes 'Main-Class': 'com.manning.gia.todo.ToDoApp'
    }
}

執行gradle build命令,UP-TO-DATE意味著任務被跳過,Gradle增量式構建支援自動鑑別不需要被執行的任務。NO-SOURCE因為我沒有建相關目錄。

>gradle build
> Task :compileJava UP-TO-DATE   //編譯Java產品程式碼
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :jar UP-TO-DATE           //組裝JAR檔案
> Task :assemble UP-TO-DATE
> Task :compileTestJava NO-SOURCE  //編譯測試程式碼,我沒有編寫相關測試程式碼
> Task :testClasses UP-TO-DATE     
> Task :test NO-SOURCE           //執行測試
> Task :check UP-TO-DATE
> Task :build UP-TO-DATE

③配置專案依賴,在Java世界裡,依賴都是以JAR檔案的形式釋出的,許多類庫可以在倉庫中找到,倉庫是一個檔案系統或者是一箇中心伺服器,Gradle要求至少使用一個倉庫來使用依賴。倉庫就是儲存你要依賴的專案的一個伺服器,可以從裡面下載你依賴的相關的JAR檔案。使用依賴需要配置元素:repositories 和 dependencies。 build.gradle指令碼,如何查詢依賴:可以在Maven Central中查詢依賴的詳細資訊。http://search.maven.org/ 上面,倉庫提供了一個簡單的搜尋入口。

apply plugin: 'java'
/**配置對maven倉庫的依賴,下載依賴原始碼的中心倉庫  */
repositories {
    mavenCentral()
}
/**新增要依賴的庫,現在一般使用implementation(compile被廢棄)*/
dependencies {
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.1'
}

執行指令碼:compileJava任務會去下載相關的依賴

>gradle build
<-----<-----<-----Download https://repo.maven.apache.org/maven2/org/apache/commons/commons-lang3/3.1/commons-lang3-3.1.pom
Download https://repo.maven.apache.org/maven2/org/apache/commons/commons-lang3/3.1/commons-lang3-3.1.jar

4、Gradle包裝器:能夠讓沒有安裝Gradle執行環境的機器執行Gradle構建。開發過程中,不同開發人員很可能因為選錯構建工具版本或者執行時環境產生對構建結果不好的影響,比如在自己的機器上構建成功,在別的機器上卻構建失敗。 包裝器可以讓構建指令碼執行在指定版本的Gradle上,它是通過自動從中心倉庫下載Gradle,最終建立一個獨立於系統和Gradle版本的可靠的和可重複的構建。 ①配置build.gradle指令碼:

/**建立一個包裝器任務,通過改變gradleVersion的值和重新執行該任務可以升級包裝器的版本*/
task wrapper(type: Wrapper) {
    gradleVersion = '4.4'
}

執行指令碼:
>gradle wrapper

執行後,會生成構建器檔案(下圖),以後就可以用包裝器的指令碼執行構建了。 這裡寫圖片描述

②使用包裝器:linux執行gradlew的shell指令碼,windows作業系統直接執行gradlew.bat,使用它們執行構建和使用已安裝的Gradle執行構建是一樣的。在包裝器執行時,Gradle執行時會被下載、解包並使用,因為有下載Gradle過程,也許構建過程會比較慢。

③包裝器下載的Gradle預設從Gradle網站(distributionUrl=https://services.gradle.org/distributions/gradle-4.4-bin.zip),但是如果不能訪問外網的情況下(也許有些企業不允許訪問外網),可以改變預設配置,將它指向存有執行時釋出檔案的企業內部伺服器。 這裡寫圖片描述