第十四章. 教程 - 杂七杂八

Chapter 14. Tutorial - 'This and That'

14.1. 创建目录

14.1. Directory creation

有一个常见的情况是,多个任务都依赖于某个目录的存在。当然,你可以在这些任务的开始加入 mkdir 来解决这个问题。但这是种臃肿的解决方法。这里有一个更好的解决方案 (仅适用于这些需要这个目录的任务有着 dependsOn 的关系的情况):
There is a common situation, that multiple tasks depend on the existence of a directory. Of course you can deal with this by adding a mkdir to the beginning of those tasks. But this is kind of bloated. There is a better solution (works only if the tasks that need the directory have a dependsOn relationship):

示例 14.1. 使用 mkdir 创建目录
Example 14.1. Directory creation with mkdir

build.gradle

classesDir = new File('build/classes')
task resources << {
    classesDir.mkdirs()
    // do something
}
task compile(dependsOn: 'resources') << {
    if (classesDir.isDirectory()) {
        println 'The class directory exists. I can operate'
    }
    // do something
}

gradle -q compile 的输出结果
Output of gradle -q compile

> gradle -q compile
The class directory exists. I can operate

14.2. Gradle 属性和系统属性

14.2. Gradle properties and system properties

Gradle 提供了许多方式将属性添加到您的构建中。 从Gradle 启动的 JVM,你可以使用 -D 命令行选项向它传入一个系统属性。 Gradle 命令的 -D 选项和 java 命令的 -D 选项有着同样的效果。
Gradle offers a variety of ways to add properties to your build. With the -D command line option you can pass a system property to the JVM which runs Gradle. The -D option of the gradle command has the same effect as the -D option of the java command.

此外,您也可以通过属性文件直接向您的project对象添加属性。您可以把一个 gradle.properties 文件放在 Gradle 的用户主目录 (默认为 USER_HOME /.gradle ) ,或您的项目目录中。对于多项目构建,您可以将 gradle.properties 文件放在任何子项目的目录中。通过project对象,可以访问到 gradle.properties 里的属性。用户的主目录中的属性文件比项目目录中的属性文件更先被访问到。
You can also directly add properties to your project objects using properties files. You can place a gradle.properties file in the Gradle user home directory (defaults to USER_HOME /.gradle ) or in your project directory. For multi-project builds you can place gradle.properties files in any subproject directory. The properties of the gradle.properties can be accessed via the project object. The properties file in the user's home directory has precedence over property files in the project directories.

你还可以通过使用 -P 命令行选项来直接向您的项目对象添加属性。在更多的用法中,您甚至可以通过系统和环境属性把属性 直接 传给项目对象。例如,如果你在一个持续集成服务器上运行构建,但你没有这台 机器 的管理员权限,而你的构建脚本需要一些不能让其他人知道的属性值,那么,您就不能使用 -P 选项。在这种情况下,您可以在项目管理部分 (对普通用户不可见) 添加一个环境属性。 [ 6 ] 如果环境属性遵循 ORG_GRADLE_PROJECT_ propertyName = somevalue 的模式,这里的 propertyName 会被添加到您的项目对象中。对系统属性我们也支持相同的机制。唯一的区别是,它是 org.gradle.project propertyName 的模式。
You can also add properties directly to your project object via the -P command line option. For more exotic use cases you can even pass properties directly to the project object via system and environment properties. For example if you run a build on a continuous integration server where you have no admin rights for the machine . Your build script needs properties which values should not be seen by others. Therefore you can't use the -P option. In this case you can add an environment property in the project administration section (invisible to normal users). [ 6 ] If the environment property follows the pattern ORG_GRADLE_PROJECT_propertyName =somevalue , propertyName is added to your project object. We also support the same mechanism for system properties. The only difference is the pattern, which is org.gradle.project.propertyName .

通过 gradle.properties 文件,你还可以设置系统属性。如果此类文件中的属性有一个 systemProp. 的前缀,该属性和它的值会被添加到系统属性,且不带此前缀。在多项目构建中,除了在根项目之外的任何项目里的 systemProp. 属性集都将被忽略。也就是,只有根项目 gradle.properties 文件里的 systemProp. 属性会被作为系统属性。
With the gradle.properties files you can also set system properties. If a property in such a file has the prefix systemProp. the property and its value are added to the system properties, without the prefix. In a multi project build, systemProp. properties set in any project except the root will be ignored. That is, only systemProp. in the root project's gradle.properties file will be set as system properties.

未例 14.2. 使用 gradle.properties 文件设置属性
Example 14.2. Setting properties with a gradle.properties file

gradle.properties

gradlePropertiesProp=gradlePropertiesValue
systemProjectProp=shouldBeOverWrittenBySystemProp
envProjectProp=shouldBeOverWrittenByEnvProp
systemProp.system=systemValue

build.gradle

task printProps << {
    println commandLineProjectProp
    println gradlePropertiesProp
    println systemProjectProp
    println envProjectProp
    println System.properties['system']
}

gradle -q -PcommandLineProjectProp=commandLineProjectPropValue -Dorg.gradle.project.systemProjectProp=systemPropertyValue printProps 的输出结果
Output of gradle -q -PcommandLineProjectProp=commandLineProjectPropValue -Dorg.gradle.project.systemProjectProp=systemPropertyValue printProps

> gradle -q -PcommandLineProjectProp=commandLineProjectPropValue -Dorg.gradle.project.systemProjectProp=systemPropertyValue printProps
commandLineProjectPropValue
gradlePropertiesValue
systemPropertyValue
envPropertyValue
systemValue

14.2.1.检查项目的属性

14.2.1. Checking for project properties

当你要使用一个变量时,你可以仅通过其名称在构建脚本中访问一个项目的属性。如果此属性不存在,则会引发异常,并且构建失败。如果您的构建脚本依赖于一些可选属性,而这些属性用户可能在比如 gradle.properties 文件中设置,您就需要在访问它们之前先检查它们是否存在。你可以通过使用方法 hasProperty('propertyName') 来进行检查,它返回 truefalse
You can access a project property in your build script simply by using its name as you would use a variable. In case this property does not exists, an exception is thrown and the build fails. If your build script relies on optional properties the user might set for example in a gradle.properties file, you need to check for existence before you can access them. You can do this by using the method hasProperty('propertyName') which returns true or false .

14.3. 使用外部构建脚本配置项目

14.3. Configuring the project using an external build script

构建语言的所有内容在外部脚本中也可以使用。您甚至可以在外部脚本中应用其他脚本。
You can configure the current project using an external build script. All of the Gradle build language is available in the external script. You can even apply other scripts from the external script.

示例14.3. 使用外部构建脚本配置项目
Example 14.3. Configuring the project using an external build script

build.gradle

apply from: 'other.gradle'

other.gradle

println "configuring $project"
task hello << {
    println 'hello from other script'
}

gradle -q hello 的输出结果
Output of gradle -q hello

> gradle -q hello
configuring root project 'configureProjectUsingScript'
hello from other script

14.4. 配置任意对象

14.4. Configuring arbitrary objects

您可以用以下非常易理解的方式配置任意对象。
You can configure arbitrary objects in the following very readable way.

示例 14.4. 配置任意对象
Example 14.4. Configuring arbitrary objects

build.gradle

task configure << {
    pos = configure(new java.text.FieldPosition(10)) {
        beginIndex = 1
        endIndex = 5
    }
    println pos.beginIndex
    println pos.endIndex
}

gradle -q configure 的输出结果
Output of gradle -q configure

> gradle -q configure
1
5

14.5. 使用外部脚本配置任意对象

14.5. Configuring arbitrary objects using an external script

你还可以使用外部脚本配置任意对象。
You can also configure arbitrary objects using an external script.

示例14.5. 使用脚本配置任意对象
Example 14.5. Configuring arbitrary objects using a script

build.gradle

task configure << {
    pos = new java.text.FieldPosition(10)
    // Apply the script
    apply from: 'other.gradle', to: pos
    println pos.beginIndex
    println pos.endIndex
}

other.gradle

beginIndex = 1;
endIndex = 5;

gradle -q configure 的输出结果
Output of gradle -q configure

> gradle -q configure
1
5

14.6. 缓存

14.6. Caching

为了提高响应速度,默认情况下 Gradle 会缓存所有已编译的脚本。这包括所有构建脚本,初始化脚本和其他脚本。你第一次运行一个项目构建时, Gradle 会创建 .gradle目录,用于存放已编译的脚本。下次你运行此构建时, 如果该脚本自它编译后没有被修改,Gradle 会使用这个已编译的脚本。否则该脚本会重新编译,并把最新版本存在缓存中。如果您通过 --recompile-scripts选项运行 Gradle ,会丢弃缓存的脚本,然后重新编译此脚本并将其存在缓存中。通过这种方式,您可以强制 Gradle 重新生成缓存。
To improve responsiveness Gradle caches all compiled scripts by default. This includes all build scripts, initialization scripts, and other scripts. The first time you run a build for a project, Gradle creates a .gradle directory in which it puts the compiled script. The next time you run this build, Gradle uses the compiled script, if the script has not changed since it was compiled. Otherwise the script gets compiled and the new version is stored in the cache. If you run Gradle with the --recompile-scripts option, the cached script is discarded and the script is compiled and stored in the cache. This way you can force Gradle to rebuild the cache.



[ 6] Teamcity Bamboo 就是提供这个功能的 CI 服务器的例子。
[ 6 ] Teamcity or Bamboo are for example CI servers which offer this functionality.