Gradle核心思想(二)Gradle入門前奏

劉望舒發表於2018-09-27

本文首發於微信公眾號「劉望舒」
原文連結:Gradle入門前奏

前言

在上一篇文章Android Gradle(一)為什麼現在要用Gradle?中,我們學習了常見的構建工具,以及Gradle與這些構建工具相比有那些不同的特性。這一篇文章我們接著來學習Gradle入門需要掌握的知識,包括配置環境、實現Hello World、Gradle的任務、Gradle日誌和Gradle命令列,掌握這些能夠更好的理解Gradle。

1.配置Gradle環境

安裝Gradle前要確保系統已經配置好JDK的環境,要求JDK的版本在1.7或更高。 Gradle的安裝有兩種形式:

  1. 通過包管理安裝,比如Window平臺的ChocolateyScoop,Mac平臺的MacPortsl、Homebrew等等。
  2. 手動安裝。

關於包管理器安裝可以檢視官方文件 ,這裡主要介紹手動安裝,在https://gradle.org/releases/中下載你想要Gradle版本的binary-only。

1.1 Windows平臺安裝

和配置Java環境類似,在系統變數中新增GRADLE_HOME:

Gradle核心思想(二)Gradle入門前奏
然後再將%GRADLE_HOME%\bin新增到path系統變數中就可以了,執行gradle -v命令來進行驗證。

1.2 Mac平臺安裝

步驟如下:

  1. 開啟終端執行open -e .bash_profile,開啟.bash_profile檔案來配置環境變數。
  2. 在.bash_profile檔案中將gradle路徑新增到path環境變數中,比如我的就是:
 export PATH=$PATH:~/develop/gradle-4.10.1/bin
複製程式碼
  1. 儲存.bash_profile檔案,在終端中執行source ~/.bash_profile,更新.bash_profile檔案。
  2. 在終端上執行gradle -v命令,檢視是否配置成功。

Gradle核心思想(二)Gradle入門前奏

2.實現Hello World

配置完Gradle環境後,按照慣例要實現Gradle的Hello World,這裡以Windows平臺為例。 build.gradle為Gradle預設的構建指令碼檔案,執行Gradle 命令時,會從當前目錄下尋找 build.gradle 檔案來執行構建。 我們先新建一個目錄,比如D:\Android\gradle_demo,在這個目錄中新建一個 build.gradle 檔案,輸入以下內容:

task hello {
    doLast {
        println 'Hello world!'
    }
}
複製程式碼

然後在該檔案所在目錄下執行gradle -q hello構建指令碼, 就會列印出“Hello world!”。

專案構建比較複雜,為了使用各種開發語言的開發者都能夠快速的構建專案,專家們開發出了Gradle這個基於Groovy的DSL,DSL(Domain Specifc Language)意為領域特定語言,只用於某個特定的領域。我們只要按照Groovy的DSL語法來寫,就可以輕鬆構建專案。 task(任務)和action(動作)是Gradle的重要元素。上面的程式碼中,task代表一個獨立的原子性操作,比如複製一個檔案,編譯一次Java程式碼,這裡我們簡單的定義一個名為hello的任務。doLast 代表task執行的最後一個action,通俗來講就是task執行完畢後會回撥doLast中的程式碼,在上面這個例子中就會列印 'Hello world!'

上面的例子還可以寫的更簡潔一些,操作符<< 是doLast方法的快捷版本,它們做了相同的事情,如下所示。

task hello << {
    println 'Hello world!'
}
複製程式碼

3.Gradle的任務

為了更好的講解後面的Gradle 命令列,這裡簡單的介紹下Gradle的任務,包括建立任務、任務依賴、 動態定義任務和任務的分組和描述。

3.1 建立任務

除了第2節實現Hello World的例子採用的建立任務方式,還有其他的3種建立任務方式。 1.直接用任務名稱建立。

def Task hello=task(hello)
hello.doLast{
	 println "hello world"
}
複製程式碼

2.任務名稱+任務配置建立。

def Task hello=task(hello,group:BasePlugin.BUILD_GROUP)
hello.doLast{
	 println "hello world"
}
複製程式碼

其中group為任務配置項,它代表了分組,關於分組具體見3.4小節。

3.TaskContainer的create方法建立。

tasks.create(name: 'hello') << {
    println "hello world"
}
複製程式碼

此前建立任務的方式最終都會呼叫tasks的create方法,其中tasks型別為TaskContainer。

3.2 任務依賴

任務依賴會決定任務執行的先後順序,被依賴的任務會在定義依賴的任務之前執行。建立任務間的依賴關係如下所示。

task hello << {
    println 'Hello world!'
}
task go(dependsOn: hello) << {
    println "go for it"
}
複製程式碼

在hello任務的基礎上增加了一個名為go的任務,通過dependsOn來指定依賴的任務為hello,因此go任務執行在hello之後。 執行gradle -q go構建指令碼,列印結果如下: Hello world! go for it

3.3 動態定義任務

動態定義任務指的是在執行時來定義任務的名稱,如下所示。

3.times {number ->
    task "task$number" << {
        println "task $number"
    }
}
複製程式碼

這裡用到了Groovy語法,關於Groovy語法會在本系列後續的文章進行介紹。times是Groovy在java.lang.Number中擴充的方法,是一個定時器。3.times中迴圈建立了三個新任務,隱式變數number的值為0,1,2,任務的名稱由task加上number的值組成,達到了動態定義任務的目的。 執行gradle -q task0構建指令碼,列印結果如下: task 0

3.4 任務的分組和描述

Gradle有任務組的概念,可以為任務配置分組和描述,以便於更好的管理任務,擁有良好的可讀性。改造3.2小節的例子,為hello任務新增分組和描述。

task hello {
	group = 'build'
	description = 'hello world'
    doLast {
    	println "任務分組: ${group}"
        println "任務描述: ${description}"
    }
}
task go(dependsOn: hello) << {
    println "go for it"
}
複製程式碼

也可以採用3.1小節中其他的建立任務方式來為任務新增分組和描述,如下所示。

def Task hello=task(hello)
hello.description ='hello world'
hello.group=BasePlugin.BUILD_GROUP
hello.doLast{
	println "任務分組: ${group}"
    println "任務描述: ${description}"
}
task go(dependsOn: hello) << {
    println "go for it"
}
複製程式碼

4.Gradle日誌級別

和Android一樣,Gradle也定義了日誌級別。

Gradle核心思想(二)Gradle入門前奏

前面我們通過gradle -q +任務名稱來執行一個指定的task,這個q是命令列開關選項,通過開關選項可以控制輸出的日誌級別。

Gradle核心思想(二)Gradle入門前奏

5.Gradle 命令列

從命令列的角度,Gradle和Git類似,命令都可以用一些IDE、圖形工具來代替,但是如果你對Gradle 命令列熟悉,會幫助你更好的理解Gradle,高效的運用Gradle。

5.1 獲取所有任務資訊

這一節的命令列以3.4小節的程式碼為例,此前我們通過gradle -q +任務名稱來執行一個指定的任務,如果不知道任務的名稱,可以 通過執行gradle -q tasks命令來獲取所有的任務資訊,這樣就不需要開啟原始碼了。

Build tasks
-----------
hello - hello world

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root projec
t 'gradle_demo'.
components - Displays the components produced by root project 'gradle_demo'. [in
cubating]
dependencies - Displays all dependencies declared in root project 'gradle_demo'.

dependencyInsight - Displays the insight into a specific dependency in root proj
ect 'gradle_demo'.
dependentComponents - Displays the dependent components of components in root pr
oject 'gradle_demo'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'gradle_demo'. [incubat
ing]
projects - Displays the sub-projects of root project 'gradle_demo'.
properties - Displays the properties of root project 'gradle_demo'.
tasks - Displays the tasks runnable from root project 'gradle_demo'.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>
複製程式碼

預設情況下,只會顯示那些被分組的任務的名稱和描述。比如Build tasks(Build 任務組)中有我們定義的hello任務,Build Setup tasks中有init和wrapper,Help tasks有buildEnvironment 和components等等。

5.2 排除任務

如果我們不想執行go任務,可以執行gradle hello -x go命令:

> Task :hello
任務分組: build
任務描述: hello world

Deprecated Gradle features were used in this build, making it incompatible with
Gradle 5.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/4.10.1/userguide/command_line_interface.html#sec:com
mand_line_warnings

BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed
複製程式碼

可以看出,並沒有執行go任務。

5.3 獲取任務幫助資訊

通過執行gradle -q help --task hello命令來顯示hello任務的幫助資訊。

Detailed task information for hello

Path
     :hello

Type
     Task (org.gradle.api.Task)

Description
     hello world

Group
     build
複製程式碼

可以看到hello任務的路徑、型別、描述和分組。

5.4 多工呼叫

task helloWorld << {
    println 'Hello world!'
}
task goForit<< {
    println "go for it"
}
複製程式碼

通過命令列一次執行多個任務,每個任務通常只會執行一次,無論是在命令列中指定任務還是任務依賴,上面的例子我們執行gradle helloWorld goForit,會先執行helloWorld任務後執行goForit任務。

5.5 任務名稱縮寫

可以對使用駝峰命名的任務進行縮寫,對於名稱特別長的任務這個特性非常有用,比如5.4小節中的例子只需要執行gradle hW gF 就可以了,不過需要注意一點,那就是任務名稱的縮寫必須是唯一的,如果5.4小節中第二個任務的名稱為helloWangshu,那麼就會報錯。


分享Android、Java和大前端相關技術

Gradle核心思想(二)Gradle入門前奏

相關文章