第13章 Writing Build Scripts 編寫構(gòu)建腳本

2018-02-24 15:56 更新

本章著眼于一些編寫構(gòu)建腳本的詳細信息。

13.1. The Gradle build language 構(gòu)建語言

Gradle 提供一種 domain specific language (領(lǐng)域特定語言)或者說是 DSL,來描述構(gòu)建。這種構(gòu)建語言基于 Groovy 中,并進行了一些補充,使其易于描述構(gòu)建。

構(gòu)建腳本可以包含任何 Groovy 語言的元素(除了聲明標(biāo)簽任何語言元素)。Gradle 假定每個構(gòu)建腳本使用 UTF-8 編碼。

13.2. The Project API 項目 API

Chapter 07. Java Quickstart 快速開始 Java的教程中,我們使用了 apply() 方法。這方法從何而來?我們之前說在 Gradle 中構(gòu)建腳本定義了一個 project 。在構(gòu)建的每一個 project,Gradle 創(chuàng)建了一個?Project?類型的實例,并在構(gòu)建腳本中關(guān)聯(lián)此 Project 對象。當(dāng)構(gòu)建腳本執(zhí)行時,它會配置此Project 對象:

  • 在構(gòu)建腳本中,你所調(diào)用的任何一個方法,如果在構(gòu)建腳本中未定義,它將被委托給 Project 對象。
  • 在構(gòu)建腳本中,你所訪問的任何一個屬性,如果在構(gòu)建腳本里未定義,它也會被委托給 Project 對象。

下面我們來試試這個,試試訪問 Project 對象的 name 屬性。

Example 13.1. Accessing property of the Project object

build.gradle

println name
println project.name

執(zhí)行 gradle -q check

> gradle -q check
projectApi
projectApi

這兩個 println 語句打印出相同的屬性。在生成腳本中未定義的屬性,第一次使用時自動委托到P roject 對象。其他語句使用了在任何構(gòu)建腳本中可以訪問的 project 屬性,則返回關(guān)聯(lián)的 Project 對象。只有當(dāng)您定義的屬性或方法 Project 對象的一個成員相同名字時,你才需要使用project 屬性。

獲取有關(guān)編寫構(gòu)建腳本幫助

不要忘記您的構(gòu)建腳本是簡單的 Groovy 代碼,并驅(qū)動著 Gradle API。并且 Project 接口是您在 Gradle API 中訪問一切 的入點。所以,如果你想知道什么 '標(biāo)簽(tag)' 在構(gòu)建腳本中可用,您可以去看項目接口的文檔。

13.2.1. Standard project properties 標(biāo)準(zhǔn) project 屬性

Project 對象提供了一些在構(gòu)建腳本中可用的標(biāo)準(zhǔn)的屬性。下表列出了常用的幾個屬性。

名稱 類型 默認值
project Project The?Project實例
name String 項目目錄的名稱
path String 項目的絕對路徑
description String 項目的描述
projectDir File 包含生成腳本的目錄
buildDir File *projectDir*/build
group Object 未指定
version Object 未指定
ant AntBuilder An?AntBuilder實例

13.3. The Script API 腳本 API

當(dāng) Gradle 執(zhí)行一個腳本時,它將腳本編譯為一個實現(xiàn)了 Script 接口的類。這意味著所有由該 Script 接口聲明的屬性和方法在您的腳本中是可用的。

13.4. Declaring variables 聲明變量

有兩類可以在生成腳本中聲明的變量: 局部變量和額外屬性。

13.4.1. Local variables 局部變量

局部變量是用 def 關(guān)鍵字聲明的。它們只在定義它們的范圍內(nèi)可以被訪問。局部變量是 Groovy 語言底層的一個特征。

Example 13.2. Using local variables

build.gradle

def dest = "dest"

task copy(type: Copy) {
    from "source"
    into dest
}

13.4.2. Extra properties 額外屬性

Gradle 的域模型中,所有增強的對象都可以容納用戶定義的額外的屬性。這包括但并不限于 project、task 和源碼集。額外的屬性可以通過所屬對象的 ext 屬性進行添加,讀取和設(shè)置?;蛘撸梢允褂?ext塊同時添加多個屬性。

Example 13.3. Using extra properties

build.gradle

apply plugin: "java"

ext {
    springVersion = "3.1.0.RELEASE"
    emailNotification = "build@master.org"
}

sourceSets.all { ext.purpose = null }

sourceSets {
    main {
        purpose = "production"
    }
    test {
        purpose = "test"
    }
    plugin {
        purpose = "production"
    }
}

task printProperties << {
    println springVersion
    println emailNotification
    sourceSets.matching { it.purpose == "production" }.each { println it.name }
}

執(zhí)行 gradle -q printProperties

> gradle -q printProperties
3.1.0.RELEASE
build@master.org
main
plugin

在此示例中, 一個 ext 代碼塊將兩個額外屬性添加到 project 對象中。此外,通過將 ext.purpose設(shè)置為 null(null是一個允許的值),一個名為 purpose 的屬性被添加到每個源碼集。一旦屬性被添加,他們就可以像預(yù)定的屬性一樣被讀取和設(shè)置。

通過添加屬性所要求特殊的語法,Gradle 可以在你試圖設(shè)置 (預(yù)定義的或額外的) 的屬性,但該屬性拼寫錯誤或不存在時馬上失敗。額外屬性在任何能夠訪問它們所屬的對象的地方都可以被訪問,這使它們有著比局部變量更廣泛的作用域。父項目上的額外屬性,在子項目中也可以訪問。

有關(guān)額外屬性和它們的 API 的詳細信息,請參閱ExtraPropertiesExtension?類的 API。

13.5. Some Groovy basics 一些 Groovy 的基礎(chǔ)

Groovy 提供了用于創(chuàng)建 DSL 的大量特點,并且 Gradle 構(gòu)建語言利用了這些特點。了解構(gòu)建語言是如何工作的,將有助于你編寫構(gòu)建腳本,特別是當(dāng)你開始寫自定義插件和 task 的時候。

13.5.1. Groovy JDK

Groovy 對 Java 的標(biāo)準(zhǔn)類增加了很多有用的方法。例如, Iterable 新增的each方法,會對Iterable 的元素進行遍歷:

Example 13.4. Groovy JDK methods

build.gradle

// Iterable gets an each() method
configurations.runtime.each { File f -> println f }

在?http://groovy.codehaus.org/groovy-jdk/?查看詳情

13.5.2. Property accessors屬性訪問器

Groovy 會自動地把一個屬性的引用轉(zhuǎn)換為對適當(dāng)?shù)?getter 或 setter 方法的調(diào)用。

Example 13.5. Property accessors

build.gradle

// Using a getter method
println project.buildDir
println getProject().getBuildDir()

// Using a setter method
project.buildDir = 'target'
getProject().setBuildDir('target')

13.5.3. Optional parentheses on method calls 括號可選的方法調(diào)用

調(diào)用方法時括號是可選的。

Example 13.6. Method call without parentheses

build.gradle

test.systemProperty 'some.prop', 'value'
test.systemProperty('some.prop', 'value')

13.5.4. List and map literals

Groovy 提供了一些定義 List 和 Map 實例的快捷寫法。兩種類型都是簡單的 literal,但 map literal 有一些有趣的曲折。

例如,“apply” 方法(如你通常應(yīng)用插件)需要 map 參數(shù)。然而,當(dāng)你有一個像 “apply plugin:'java'”,你實際上并沒有使用 map literal ,你實際上使用“命名的參數(shù)”,這幾乎是和 map literal 相同的語法(不包包裝器)。命名參數(shù)列表將被轉(zhuǎn)換成一個 map 當(dāng)方法被調(diào)用時,但它沒有在開始作為一個 map。

Example 13.7. List and map literals

build.gradle

// List literal
test.includes = ['org/gradle/api/**', 'org/gradle/internal/**']

List<String> list = new ArrayList<String>()
list.add('org/gradle/api/**')
list.add('org/gradle/internal/**')
test.includes = list

// Map literal.
Map<String, String> map = [key1:'value1', key2: 'value2']

// Groovy will coerce named arguments
// into a single map argument
apply plugin: 'java'

13.5.5. Closures as the last parameter in a method 作為方法最后一個參數(shù)的閉包

Gradle DSL 在很多地方使用閉包。你可以在這里查看更多有關(guān)閉包的資料。當(dāng)方法的最后一個參數(shù)是一個閉包時,你可以把閉包放在方法調(diào)用之后:

Example 13.8. Closure as method parameter

build.gradle

repositories {
    println "in a closure"
}
repositories() { println "in a closure" }
repositories({ println "in a closure" })

13.5.6. Closure delegate 閉包委托

每個閉包都有一個委托對象,Groovy 使用它來查找變量和方法的引用,而不是作為閉包的局部變量或參數(shù)。Gradle 在配置閉包中使用到它,把委托對象設(shè)置為被配置的對象。

Example 13.9. Closure delegates

build.gradle

dependencies {
    assert delegate == project.dependencies
    testCompile('junit:junit:4.11')
    delegate.testCompile('junit:junit:4.11')
}
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號