天天看點

Gradle——建構腳本基礎

1、項目(project)和任務(task)

Gradle中的任何事都基于兩個基本概念:項目(project)和任務(task)

每一個建構(build)都是由一個或多個項目組成的。一個項目代表什麼取決于你使用Gradle做什麼。例如,一個項目也許代表一個庫或者一個web應用程式,它也許代表一個由其他項目産生的JAR檔案組成的ZIP。一個工程不一定代表一件要去建構的事,它也許代表一件要去做的事情,例如将你的應用程式部署到工作台或者生産環境。現在看來,這些概念似乎有一點模糊,不過别擔心,Gradle的基于約定的建構會對一個項目是什麼有更具體的定義。

每一個項目由一個或多個任務(task)組成,一個任務代表一些執行建構工作的最小工作單元。它也許編譯一些類,建立一個JAR,生成Javadoc文檔,或者向庫釋出一些文檔。

Gradle——建構腳本基礎

一個build包含多個project,一個project包含多個task

現在,我們将在一個項目中定義一些簡單的任務,後面的章節将會使用多個項目,并且還有更多關于使用項目和任務的知識。

2、Hello World

你可以使用gradle指令運作Gradle的建構。gradle指令在目前目錄下查找一個名為build.gradle的檔案,我們稱build.gradle檔案是一個“建構腳本”,嚴格的說它是一個建構配置腳本。建構腳本定義了一個項目及其任務。

試一試:建立如下建構腳本,并命名為“build.gradle”

task hello{
    doLast{
        println 'Hello World!'
    }
}
           

在控制台中移動到此檔案所在目錄,并輸入“gradle -q hello”執行該檔案,可看到控制台中輸出Hello World。

Gradle——建構腳本基礎

(關于 -q :使用者手冊中的大多數例子都使用了 -q 指令行選項,它會抑制Gradle的日志資訊,是以會隻顯示task的輸出。這會使手冊中例子的輸出更簡潔,你完全可以不使用它。)

對build.gradle的說明:建構腳本定義了一個名為“hello”的task,并為其添加了一個操作。當你運作“gradle hello”的時候,Gradle執行這個名為“hello”的task時,會去執行你提供的操作。這個操作是一個閉包,包含了Groovy代碼去執行。

3、使用更簡單/快捷的定義方式定義task

task hello << {
    println 'Hello World!'
}
           

如上,這使用了 [一個簡單的閉包(翻譯不恰當)] 定義了一個名為“hello”的task,我們将在使用者手冊中使用這種風格定義task

4、建構腳本代碼

Gradle的建構腳本給你Groovy的全部權利。

例1:在名為“build.gradle”的檔案中輸入如下代碼:

task upper <<{
    String str = 'aBcD'
    println "original:" + str
    println "Upper case:" + str.toUpperCase()

}
           

運作結果如下:

Gradle——建構腳本基礎

例2:在名為“build.gradle”的檔案中輸入如下代碼:

task count << {
     .times { print "$it " }
     println ''
}
           

結果如下:

Gradle——建構腳本基礎

5、task依賴

也許你已經猜到了,你可以聲明依賴于其他tasks的task

例:在名為“build.gradle”的檔案中輸入如下代碼:

task hello << {
    println "hello"
}

task world(dependsOn: hello) <<{
    println "world"
}
           

結果如下:

Gradle——建構腳本基礎

可見,若先執行名為hello的task,則會隻執行該task;若先執行名為world的task,則會先執行該task所依賴的其他task(hello),然後再執行自身那個task。即,被依賴的task會先執行。

懶依賴:被依賴的task不存在(被依賴的task後定義)

task world(dependsOn: "hello") <<{   
    println "world"
}
task hello << {
    println "hello"
}
           

注意:task world依賴的task的名字要加上引号

結果如下:

Gradle——建構腳本基礎

Task world對task hello的依賴關系聲明在task hello定義之前,這對于多項目建構非常重要。

請注意,當引用一個未被定義的task時,你不能使用 shortcut notation (即點運算符 . )

6、動态task

Groovy能不僅能用于指定一個task能做什麼,你也能用它去動态建立task。

.times{ counter -> 
    task "task$counter" <<{
        println "No. $counter task"
    }
}
           

結果如下:

Gradle——建構腳本基礎

7、操作現有的task

一旦task被建立,他們就能通過API被通路到。

例如,你可以在運作時動态地為task添加依賴關系。

.times{ counter -> 
    task "task$counter" <<{
        println "No. $counter task"
    }
}
task1.dependsOn task2, task3
           

為task1添加對task2,task3的依賴。

結果如下:

Gradle——建構腳本基礎

為現有的task添加行為:

task hello <<{
    println "hello"
}

hello.doFirst{
    println "doFirst"
}

hello.doLast{
    println "doLast"
}
hello << {
    println '88888'
}
           

結果如下:

Gradle——建構腳本基礎

可見,執行的順序為:doFirst - task本身 - doLast - <<(doLast)

doFirst和doLast可以被多次調用,doFirst在task的操作清單開頭,doLast在task的操作清單結尾,當task執行時,操作清單中的操作會按順序執行。

“<<”操作符隻不過是doLast的别名。

8、快捷通路符(. )

也許你已經注意到,可以使用快捷通路符通路現存的task,建構腳本中的每一個task的屬性都可以使用快捷通路符通路。

task hello <<{
    println "hello world"
}

hello.doLast{
    println "my name is $hello.name !"
}
           

結果如下:

Gradle——建構腳本基礎

這使得代碼很易讀,特别是當使用插件提供的task時,例如編譯task(compile task)

9、額外的task屬性

你可以為task添加你自己的屬性。

添加一個名為“myProperty”的屬性,并為其賦初值。從這時起,這個屬性就能像一個預定義的task屬性一樣讀、寫(設定)

task myTask {
    ext.myProperty = "Xiaming_Chen"
}

task printMyProperty <<{
    println myTask.myProperty
    myTask.myProperty = "Chen_Xiaming"
    println myTask.myProperty
}
           

結果如下:

Gradle——建構腳本基礎

可見,額外的task屬性不局限于task,myProperty屬性可以被其他的task讀,也能在其他task中為其指派。

10、使用Ant tasks

11、使用方法

在Gradle中,你可以怎樣組織你的建構邏輯是有等級限制的。上面的示例“提取一個方法”隻是第一級。

12、預設task

如果你沒有指定其他的task,Gradle允許你定義一個或多個預設task執行。

defaultTasks "default1","default2"

task default1<<{
    println "No.1 default task"
}

task default2<<{
    println "No.2 default task"
}

task myTask<<{
    println "my task"
}
           

結果如下:

Gradle——建構腳本基礎

指定預設task為default1和default2,當執行時若不指定要執行的task,則會執行所有預設的task。

這與運作“gradle default1 default2”等效。

在一個多項目建構中,每個子項目能擁有他們自己特定的預設task,如果一個子項目沒有指定預設task,則父項目的預設task會被使用(如果定義了的話)。

13、用DAG配置Gradle有配置階段和執行階段,在配置階段之後,Gradle知道所有需要被執行的task,Gradle為你提供了可以利用這些資訊的工具。一個用例将會檢查釋出的task是否在要被執行的所有task中,由此,你可以為不同的變量配置設定不同的值。

在下面的例子中,task的執行結果會因變量version的不同而不同。

task distribution <<{
    println "We build the zip with version = $version"
}

task release(dependsOn: distribution) <<{
    println "We release now"
}

gradle.taskGraph.whenReady { taskGraph ->

    if(taskGraph.hasTask(release)){
        version = "1.0"
    }else{
        version = "1.0-SNAPSHOT"
    }

}
           

執行gradle -q distribution:

Gradle——建構腳本基礎

執行gradle -q release:

Gradle——建構腳本基礎

“whenReady”會在release task執行之前影響release,即使release task不是首要的task這也會起作用。

繼續閱讀