第十七章. 从 Gradle 中调用 Ant

Chapter 17. Using Ant from Gradle

Gradle 提供了对 Ant 的优秀集成您可以在你的 Gradle 构建中,使用单独的 Ant 任务或整个 Ant 构建。事实上,你会发现在 Gradle 中使用 Ant 任务比使用 Ant 的XML 格式更容易也更强大。你甚至可以只把 Gradle 当作一个强大的 Ant 任务脚本的工具。
Gradle provides excellent integration with Ant. You can use individual Ant tasks or entire Ant builds in your Gradle builds. In fact, you will find that it's far easier and more powerful using Ant tasks in a Gradle build script, than it is to use Ant's XML format. You could even use Gradle simply as a powerful Ant task scripting tool.

Ant 可以分为两层。第一层是 Ant 的语言。它提供了用于 build.xml,处理的目标,特殊的构造方法比如宏,还有其他等等的语法。换句话说,除了 Ant 任务和类型之外全部都有。Gradle 理解这种语言,并允许您直接导入你的Ant build.xml 到 Gradle 项目中。然后你可以使用你的 Ant 构建中的target,就好像它们是 Gradle 任务一样。
Ant can be divided into two layers. The first layer is the Ant language. It provides the syntax for the build.xml , the handling of the targets, special constructs like macrodefs, and so on. In other words, everything except the Ant tasks and types. Gradle understands this language, and allows you to import your Ant build.xml directly into a Gradle project. You can then use the targets of your Ant build as if they were Gradle tasks.

Ant 的第二层是其丰富的 Ant 任务和类型,如 javaccopyjar。这一层 Gradle 单靠 Groovy 和不可思议的 AntBuilder,对其提供了集成。
The second layer of Ant is its wealth of Ant tasks and types, like javac , copy or jar . For this layer Gradle provides integration simply by relying on Groovy, and the fantastic AntBuilder .

最后,由于构建脚本是 Groovy 脚本,所以您始终可以作为一个外部进程来执行 Ant 构建。你的构建脚本可能包含有类似这样的语句: "ant clean compile".execute()[ 8]
Finally, since build scripts are Groovy scripts, you can always execute an Ant build as an external process. Your build script may contain statements like: "ant clean compile".execute() . [ 8 ]

你可以把 Gradle 的 Ant 集成当成一个路径,将你的构建从 Ant 迁移至 Gradle 。例如,你可以通过导入您现有的 Ant 构建来开始。然后,可以将您的依赖声明从 Ant 脚本移到您的构建文件。最后,您可以将整个任务移动到您的构建文件,或者把它们替换为一些 Gradle 插件。这个过程可以随着时间一点点完成,并且在这整个过程当中你的 Gradle 构建都可以使用用。
You can use Gradle's Ant integration as a path for migrating your build from Ant to Gradle. For example, you could start by importing your existing Ant build. Then you could move your dependency declarations from the Ant script to your build file. Finally, you could move your tasks across to your build file, or replace them with some of Gradle's plugins. This process can be done in parts over time, and you can have a working Gradle build during the entire process.

17.1. 在构建中使用 Ant 任务和类型

17.1. Using Ant tasks and types in your build

在构建脚本中,Gradle 提供了一个名为 ant 的属性。它指向一个 AntBuilder 实例。 AntBuilder 用于从你的构建脚本中访问 Ant 任务、 类型和属性。从 Ant 的 build.xml格式到 Groovy 之间有一个非常简单的映射,下面解释。
In your build script, a property called ant is provided by Gradle. This is a reference to an AntBuilder instance. This AntBuilder is used to access Ant tasks, types and properties from your build script. There is a very simple mapping from Ant's build.xml format to Groovy, which is explained below.

通过调用 AntBuilder实例上的一个方法,可以执行一个 Ant 任务。你可以把任务名称当作方法名称使用。例如,你可以通过调用 ant.echo()方法执行 Ant 的 echo 任务。Ant 任务的属性会作为 Map 参数传给该方法。下面是执行 echo 任务的例子。请注意我们还可以混合使用 Groovy 代码和 Ant 任务标记。这将会非常强大。
You execute an Ant task by calling a method on the AntBuilder instance. You use the task name as the method name. For example, you execute the Ant echo task by calling the ant.echo() method. The attributes of the Ant task are passed as Map parameters to the method. Below is an example which executes the echo task. Notice that we can also mix Groovy code and the Ant task markup. This can be extremely powerful.

示例 17.1. 使用 Ant 任务
Example 17.1. Using an Ant task

build.gradle

task hello << {
    String greeting = 'hello from Ant'
    ant.echo(message: greeting)
}

gradle hello 的输出结果
Output of gradle hello

> gradle hello
:hello
[ant:echo] hello from Ant

BUILD SUCCESSFUL

Total time: 1 secs

You pass nested text to an Ant task by passing it as a parameter of the task method call. In this example, we pass the message for the echo task as nested text:

示例 17.2. 向 Ant 任务传入嵌套文本
Example 17.2. Passing nested text to an Ant task

build.gradle

task hello << {
    ant.echo('hello from Ant')
}

gradle hello 的输出结果
Output of gradle hello

> gradle hello
:hello
[ant:echo] hello from Ant

BUILD SUCCESSFUL

Total time: 1 secs

你可以在一个闭包里把嵌套的元素传给一个 Ant 任务。嵌套元素的定义方式与任务相同,通过调用与我们要定义的元素一样的名字的方法。
You pass nested elements to an Ant task inside a closure. Nested elements are defined in the same way as tasks, by calling a method with the same name as the element we want to define.

示例 17.3. 向 Ant 任务传入嵌套元素
Example 17.3. Passing nested elements to an Ant task

build.gradle

task zip << {
    ant.zip(destfile: 'archive.zip') {
        fileset(dir: 'src') {
            include(name: '**.xml')
            exclude(name: '**.java')
        }
    }
}

您可以用访问任务同样的方法,把类型名字作为方法名称,访问 Ant 类型。方法调用返回 Ant 数据类型,然后可以在构建脚本中直接使用。在以下示例中,我们创建一个 Ant 的 path对象,然后循环访问它的内容。
You can access Ant types in the same way that you access tasks, using the name of the type as the method name. The method call returns the Ant data type, which you can then use directly in your build script. In the following example, we create an Ant path object, then iterate over the contents of it.

示例 17.4. 使用 Ant 类型
Example 17.4. Using an Ant type

build.gradle

task list << {
    def path = ant.path {
        fileset(dir: 'libs', includes: '*.jar')
    }
    path.list().each {
        println it
    }
}

有关 AntBuilder的详细信息可以参阅 《Groovy in Action》的8.4章节, 或 Groovy 维基
More information about AntBuilder can be found in 'Groovy in Action' 8.4 or at the Groovy Wiki

17.1.1. 在您的构建中使用自定义 Ant 任务

17.1.1. Using custom Ant tasks in your build

要使自定义任务在您的构建中可用,你可以使用Ant 任务 taskdef(通常更容易) 或 typedef,就像在 build.xml文件中一样。然后,您可以像引用内置的 Ant 任务一样引用自定义 Ant 任务。
To make custom tasks available in your build, you can use the taskdef (usually easier) or typedef Ant task, just as you would in a build.xml file. You can then refer to the custom Ant task as you would a built-in Ant task.

示例 17.5. 使用自定义 Ant 任务
Example 17.5. Using a custom Ant task

build.gradle

task check << {
    ant.taskdef(resource: 'checkstyletask.properties') {
        classpath {
            fileset(dir: 'libs', includes: '*.jar')
        }
    }
    ant.checkstyle(config: 'checkstyle.xml') {
        fileset(dir: 'src')
    }
}

你可以使用 Gradle 的依赖管理组合类路径,以用于自定义任务。要做到这一点,你需要定义一个自定义配置的类路径中,然后将一些依赖项添加到配置中。这在 50.4章节,“如何声明你的依赖关系”有更详细的描述。
You can use Gradle's dependency management to assemble the classpath to use for the custom tasks. To do this, you need to define a custom configuration for the classpath, then add some dependencies to the configuration. This is described in more detail in Section 50.4, “How to declare your dependencies” .

示例 17.6. 声明用于自定义 Ant 任务的类路径
Example 17.6. Declaring the classpath for a custom Ant task

build.gradle

configurations {
    pmd
}

dependencies {
    pmd group: 'pmd', name: 'pmd', version: '4.2.5'
}

若要使用类路径配置,请使用自定义配置里的 asPath属性。
To use the classpath configuration, use the asPath property of the custom configuration.

示例 17.7. 同时使用自定义 Ant 任务和依赖管理
Example 17.7. Using a custom Ant task and dependency management together

build.gradle

task check << {
    ant.taskdef(name: 'pmd', classname: 'net.sourceforge.pmd.ant.PMDTask', classpath: configurations.pmd.asPath)
    ant.pmd(shortFilenames: 'true', failonruleviolation: 'true', rulesetfiles: file('pmd-rules.xml').toURI().toString()) {
        formatter(type: 'text', toConsole: 'true')
        fileset(dir: 'src')
    }
}

17.2. 导入 Ant 构建

17.2. Importing an Ant build

你可以使用 ant.importBuild()方法来向 Gradle 项目导入一个 Ant 构建。当您导入一个 Ant 构建时,每个 Ant 目标被视为一个 Gradle 任务。这意味着你可以用与 Gradle 任务完全相机的方式操纵和执行 Ant 目标。
You can use the ant.importBuild() method to import an Ant build into your Gradle project. When you import an Ant build, each Ant target is treated as a Gradle task. This means you can manipulate and execute the Ant targets in exactly the same way as Gradle tasks.

示例 17.8. 导入 Ant 构建
Example 17.8. Importing an Ant build

build.gradle

ant.importBuild 'build.xml'

build.xml

<project>
    <target name="hello">
        <echo>Hello, from Ant</echo>
    </target>
</project>

gradle hello 的输出结果
Output of gradle hello

> gradle hello
:hello
[ant:echo] Hello, from Ant

BUILD SUCCESSFUL

Total time: 1 secs

您可以添加一个依赖于 Ant 目标的任务:
You can add a task which depends on an Ant target:

示例 17.9. 依赖于 Ant 目标的任务
Example 17.9. Task that depends on Ant target

build.gradle

ant.importBuild 'build.xml'

task intro(dependsOn: hello) << {
    println 'Hello, from Gradle'
}

gradle intro 的输出结果
Output of gradle intro

> gradle intro
:hello
[ant:echo] Hello, from Ant
:intro
Hello, from Gradle

BUILD SUCCESSFUL

Total time: 1 secs

或者,您可以将行为添加到 Ant 目标中:
Or, you can add behaviour to an Ant target:

示例 17.10. 将行为添加到 Ant 目标
Example 17.10. Adding behaviour to an Ant target

build.gradle

ant.importBuild 'build.xml'

hello << {
    println 'Hello, from Gradle'
}

gradle hello 的输出结果
Output of gradle hello

> gradle hello
:hello
[ant:echo] Hello, from Ant
Hello, from Gradle

BUILD SUCCESSFUL

Total time: 1 secs

它也可以用于一个依赖于 Gradle 任务的 Ant 目标:
It is also possible for an Ant target to depend on a Gradle task:

示例 17.11. 依赖于 Gradle 任务的 Ant 目标
Example 17.11. Ant target that depends on Gradle task

build.gradle

ant.importBuild 'build.xml'

task intro << {
    println 'Hello, from Gradle'
}

build.xml

<project>
    <target name="hello" depends="intro">
        <echo>Hello, from Ant</echo>
    </target>
</project>

gradle hello 的输出结果
Output of gradle hello

> gradle hello
:intro
Hello, from Gradle
:hello
[ant:echo] Hello, from Ant

BUILD SUCCESSFUL

Total time: 1 secs

17.3. Ant 属性和引用

17.3. Ant properties and references

有几种方法来设置 Ant 属性,以便使该属性被 Ant 任务使用。你可以直接在 AntBuilder实例上设置属性。Ant 属性也可以从一个你可以修改的Map中获得。您还可以使用 Ant property 任务。下面是一些如何做到这一点的例子。
There are several ways to set an Ant property, so that the property can be used by Ant tasks. You can set the property directly on the AntBuilder instance. The Ant properties are also available as a Map which you can change. You can also use the Ant property task. Below are some examples of how to do this.

示例 17.12. Ant 属性设置
Example 17.12. Setting an Ant property

build.gradle

ant.buildDir = buildDir
ant.properties.buildDir = buildDir
ant.properties['buildDir'] = buildDir
ant.property(name: 'buildDir', location: buildDir)

build.xml

<echo>buildDir = ${buildDir}</echo>

许多 Ant 任务在执行时会设置一些属性。有几种方法来获取这些属性值。你可以直接从 AntBuilder实例获得属性。Ant 属性也可作为一个 Map。下面是一些例子。
Many Ant tasks set properties when they execute. There are several ways to get the value of these properties. You can get the property directly from the AntBuilder instance. The Ant properties are also available as a Map. Below are some examples.

示例 17.13. 获取 Ant 属性
Example 17.13. Getting an Ant property

build.xml

<property name="antProp" value="a property defined in an Ant build"/>

build.gradle

println ant.antProp
println ant.properties.antProp
println ant.properties['antProp']

有几种方法可以设置 Ant 引用:
There are several ways to set an Ant reference:

示例 17.14. Ant 引用设置
Example 17.14. Setting an Ant reference

build.gradle

ant.path(id: 'classpath', location: 'libs')
ant.references.classpath = ant.path(location: 'libs')
ant.references['classpath'] = ant.path(location: 'libs')

build.xml

<path refid="classpath"/>

有几种方法可以获取 Ant 引用:
There are several ways to get an Ant reference:

示例 17.15. 获取 Ant 引用
Example 17.15. Getting an Ant reference

build.xml

<path id="antPath" location="libs"/>

build.gradle

println ant.references.antPath
println ant.references['antPath']

17.4. API

17.4. API

Ant 集成由 AntBuilder 提供。
The Ant integration is provided by AntBuilder .



[ 8] In Groovy you can execute 字符串表示的命令。要了解更多关于使用 Groovy 执行外部进程的内容,可以看一下《Groovy in Action》的9.3.2章节,或者是 Groovy wiki
[ 8 ] In Groovy you can execute Strings. To learn more about executing external processes with Groovy have a look in 'Groovy in Action' 9.3.2 or at the Groovy wiki