理想情况下,Groovy构建脚本看起来大体上类似于配置:设置项目的某些属性,配置依赖项,声明任务等. 该配置基于Groovy语言构造. 本入门手册旨在说明这些构造是什么,以及最重要的是,它们与Gradle的API文档之间的关系.

The Project object

As Groovy is an object-oriented language based on Java, its properties and methods apply to objects. In some cases, the object is implicit — particularly at the top level of a build script, i.e. not nested inside a {} block.

考虑以下构建脚本片段,其中包含一个不合格的属性和块:

version = '1.0.0.GA'

configurations {
    ...
}

versionconfigurations {}都是org.gradle.api.Project的一部分.

此示例反映了每个Groovy构建脚本如何由Project的隐式实例支持. 如果看到不合格的元素并且不知道其定义位置,请始终查看Project API文档以查看其来源.

Properties

<obj>.<name>                // Get a property value
<obj>.<name> = <value>      // Set a property to a new value
"$<name>"                   // Embed a property value in a string
"${<obj>.<name>}"           // Same as previous (embedded value)
Examples
version = '1.0.1'
myCopyTask.description = 'Copies some files'

file("$buildDir/classes")
println "Destination: ${myCopyTask.destinationDir}"

属性表示对象的某种状态. =符号的存在清楚地表明您正在查看属性. 否则,为合格名称-以<obj>.开头<obj>. -没有任何其他装饰也是财产.

如果名称不合格,则可能是以下之一:

请注意,插件可以将自己的属性添加到Project对象. API文档列出了核心插件添加的所有属性. 如果您很难找到属性的来源,请查看文档以了解构建所使用的插件.

💡
当在由非核心插件添加的构建脚本中引用项目属性时,请考虑在其前面加上project. —显然,该属性属于项目对象.

Properties in the API documentation

Groovy DSL参考显示了在构建脚本中使用的属性,但是Javadocs仅显示方法. 这是因为属性是作为幕后方法实现的:

  • 如果存在一个名为get<PropertyName>的方法,该方法的参数为零,并且返回的类型与属性相同,则可以读取属性.

  • 如果存在一个名为set<PropertyName>的方法,且该方法的一个参数与该属性具有相同的类型,并且返回类型为void则可以修改该属性.

请注意,属性名称通常以小写字母开头,但是该字母在方法名称中为大写字母. 因此,getter方法getProjectVersion()对应于属性projectVersion . 当名称至少以两个大写字母开头时,该约定不适用,在这种情况下,大小写不变. 例如, getRAM()对应于属性RAM .

Examples
project.getVersion()
project.version

project.setVersion('1.0.1')
project.version = '1.0.1'

Methods

<obj>.<name>()              // Method call with no arguments
<obj>.<name>(<arg>, <arg>)  // Method call with multiple arguments
<obj>.<name> <arg>, <arg>   // Method call with multiple args (no parentheses)
Examples
myCopyTask.include '**/*.xml', '**/*.properties'

ext.resourceSpec = copySpec()   // `copySpec()` comes from `Project`

file('src/main/java')
println 'Hello, World!'

尽管Gradle经常使用方法来配置对象的状态,但是方法表示对象的某些行为. 方法可以通过其参数或空括号来识别. 请注意,有时需要使用括号,例如当一个方法的参数为零时,因此始终使用括号最简单.

Gradle有一个约定,如果一个方法与基于集合的属性具有相同的名称,则该方法会将其值附加到该集合.

Blocks

块也是方法 ,只是最后一个参数具有特定类型.

<obj>.<name> {
     ...
}

<obj>.<name>(<arg>, <arg>) {
     ...
}
Examples
configurations {
    assets
}

sourceSets {
    main {
        java {
            srcDirs = ['src']
        }
    }
}

project(':util') {
    apply plugin: 'java-library'
}

块是一种用于一次性构造构建元素的多个方面的机制. 它们还提供了嵌套配置的方法,从而导致结构化数据的形式.

您应该了解块的两个重要方面:

  1. 它们被实现为具有特定签名的方法.

  2. 他们可以更改不合格方法和属性的目标("委托").

两者均基于Groovy语言功能,我们将在以下各节中进行解释.

Block method signatures

您可以通过其签名(或更具体地说,其参数类型)轻松地将方法标识为块后面的实现. 如果方法对应于一个块:

例如, Project.copy(Action)满足以下要求,因此可以使用以下语法:

copy {
    into "$buildDir/tmp"
    from 'custom-resources'
}

这就引出了to into()from()工作的问题. 它们显然是方法,但是您会在API文档中找到它们吗? 答案来自对对象委托的理解.

Delegation

属性部分列出了可能会发现不合格属性的地方. 一个常见的地方是在Project对象上. 但是,对于块内的那些不合格的属性和方法,还有另一种来源:块的委托对象 .

为了帮助解释这个概念,请考虑上一节中的最后一个示例:

copy {
    into "$buildDir/tmp"
    from 'custom-resources'
}

此示例中的所有方法和属性均不合格. 您可以在Project API文档中轻松找到copy()buildDir ,但是into()from()呢? 这些将根据copy {}块的委托进行解析. 该代表的类型是什么? 您需要查看API文档 .

有两种方法可以确定委托类型,具体取决于block方法的签名:

  • 对于Action参数,请查看类型的参数.

    在上面的示例中,方法签名为copy(Action<? super CopySpec>) ,正是尖括号内的那个位告诉您委托类型-在这种情况下为CopySpec .

  • 对于Closure参数,文档将在描述中明确说明正在配置的类型或委托的类型(同一事物的不同术语).

因此,您可以在CopySpecCopySpec ()from() . 您甚至可能会注意到,这两种方法都具有将Action作为最后一个参数的变体,这意味着您可以对它们使用块语法.

所有新的Gradle API都声明一个Action参数类型,而不是Closure ,这使得选择委托类型非常容易. 除了旧的Closure API,甚至更旧的API也具有Action变体.

Local variables

def <name> = <value>        // Untyped variable
<type> <name> = <value>     // Typed variable
Examples
def i = 1
String errorMsg = 'Failed, because reasons'

局部变量是Groovy构造(与其他属性不同),可用于在构建脚本中共享值.

避免在项目的根目录中使用局部变量,即作为伪项目属性. 无法在构建脚本之外读取它们,并且Gradle不了解它们.

在狭窄的环境中(例如配置任务),局部变量有时会有所帮助.