在 Gradle中使用Ant

Gradle 出色的集成了 Ant. 你可以在 Gradle 构建时使用单独的 Ant 任务或完整的 Ant 构建. 事实上, 你会发现在 Gradle 构建脚本中使用Ant任务远比直接使用 Ant 的 XML 格式更加容易和强大. 你甚至可以将 Gradle 仅仅作为一个强大的 Ant 脚本工具.

Ant 可以分为两层. 第一层是 Ant 语言. 它给 build.xml 文件, 处理目标, 像 macrodefs 的特殊构造等提供语法支持. 换句话说, 除了 Ant 任务和类型, 其余一切都支持. Gradle 了解这种语言, 并允许用户直接导入 Ant 的 build.xml 到 Gradle 的项目下. 然后, 你可以 像 Gradle 任务一样直接使用这些 Ant 构建.

第二层是 Ant 丰富的任务和类型, 如 javac, copy 或 jar. Gradle 提供了基于 Groovy 的集成以及梦幻般的 AntBuilder.

最后,由于构建脚本是 Groovy 脚本, 你总是可以执行一个 Ant 构建作为一个外部进程. 构建脚本可能会含有类似的语句:“ant clean compile”.execute().[7]

你可以使用 Gradle 的 Ant 集成,作为迁移路径将构建 Ant 迁移到 Gradle. 例如, 你可以从通过导入现有的 Ant 构建开始, 然后将你的依赖声明从 Ant 脚本迁移到你的 build 文件. 最后, 你可以将任务迁移到你的构建文件, 或者用一些 Gradle 插件代替他们. 随着时间的推移, 这部分工作会一步一步地完成, 并且你可以在整个进程中有一个运行良好的 Gradle 构建.

16.1.使用 Ant 任务和 Ant 类型的构建

在构建脚本中, Ant 属性是由 Gradle提供的. 这是一个用于参考的 AntBuilder 实例. AntBuilder 用于从构建脚本访问 Ant 任务, 类型和属性. 下面的例子解释了从 Ant 的 build.xml 格式到 Grooy 的映射.

你可以通过调用 AntBuilder 实例的方法执行 Ant 任务. 你可以使用任务名称作为方法名, 比如, 可以通过调用 anto.echo() 任务执行 Ant echo 任务. Ant 任务属性通过 Map 参数传递给方法. 下面是一个 echo 任务的例子, 注意我们也可以混合使用 Groovy 代码和 Ant 任务标记, 这点个功能非常强大.

例 16.1.使用 Ant 任务

build.gradle

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

gradle hello 的输出

>\> gradle hello
>:hello
>[ant:echo] hello from Ant
>
>BUILD SUCCESSFUL
>
>Total time: 1 secs

你可以添加嵌套元素添加到一个封闭的 Ant 任务的内部. 定义嵌套元素跟定义任务的方式相同, 通过与调用我们要定义的元素名相同的方法.

例 16.3.添加嵌套元素到一个Ant任务

build.gradle

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

你可以像访问任务一样访问 Ant type,只需要将 type 名作为方法名即可. 该方法调用返回的 Ant 数据类型,可以直接在构建脚本中使用.下面的例子中,我们创建了一个ant path对象,然后遍历他的内容.

例 16.4.使用 Ant 类型

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 Wiki.

在构建中使用自定义Ant任务

为了让你的构建可以自定义任务, 你可以使用 taskdef(通常更容易) 或者 typedef Ant 任务, 就像你在一个build.xml文件中一样. 然后,你可以参考内置 Ant 任务去定制 Ant 任务.

例 16.5.使用自定义 Ant 任务

build.gradle

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

你可以使用 Gradle 的依赖管理去组装你自定义任务所需要的 classpath. 要做到这一点, 你需要定义一个自定义配置类路径, 然后添加一些依赖配置.在Section 51.4, “How to declare your dependencies”部分有更详细的说明.

例 16.6.声明类路径的自定义 Ant 任务

build.gradle

configurations {
    pmd
}

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

要使用 classpath 配置, 使用自定义配置的asPath属性。

例 16.7.一起使用自定义Ant任务和依赖管理

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')
    }
}

导入一个Ant构建

你可以在你的gradle项目中通过ant.importBuild()来导入一个ant构建,当你导入了一个ant构建,每一个ant target都会被视为一个Gradle任务.这意味着你可以像操作,执行gradle任务一样操作,执行ant target

例 16.8.导入ant构建

build.gradle

ant.importBuild 'build.xml'

build.xml

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

gradle hello的输出

>\> gradle hello
>:hello
>[ant:echo] Hello, from Ant
>
>BUILD SUCCESSFUL
>
>Total time: 1 secs

你可以添加一个依赖于ant target的任务: 例 16.9.依赖于ant target的任务

build.gradle

ant.importBuild 'build.xml'

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

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

BUILD SUCCESSFUL

Total time: 1 secs

或者,你可以为ant target添加动作

例 16.10.为Ant target添加动作

build.gradle

ant.importBuild 'build.xml'

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

gradle hello的输出

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

BUILD SUCCESSFUL

Total time: 1 secs

当然,一个ant target也可以依赖于gradle的任务

例 16.11.为Ant target添加动作

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的输出

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

BUILD SUCCESSFUL

Total time: 1 secs

有时候可能需要'重命名'ant target以避免与现有的gradle任务冲突.需要使用AntBuilder.importBuilder()方法.

例 16.12.重命名导入的ant target

build.gradle

ant.importBuild('build.xml') { antTargetName ->
    'a-' + antTargetName
}

build.xml

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

gradle a-hello的输出

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

BUILD SUCCESSFUL

Total time: 1 secs

注意,方法的二个参数应该是一个TransFormer,在Groovy编程的时候,由于Groovy的支持自动闭包单抽象方法的类型。我们可以简单地使用闭包取代匿名内部类,

Ant的属性与引用

有许多方法可以设定 Ant 属性,可以通过Ant任务使用属性.您可以直接在AntBuilder的实例设置属性。Ant的属性也可以作为一个可改变的Map.也可以使用Ant的任务属性,如下例所示:

例16.13.设置Ant属性

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>

许多任务会在执行时设置属性.下面有几种方法来获取属性值,可以直接从AntBuilder实例获得属性,如下所示,ant的属性仍然是作为一个map:

例16.14.获取Ant属性

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引用的方法:

例16.15.设置一个Ant引用

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引用的方法:

例16.16.获取一个Ant引用

build.xml

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

build.gradle

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

API

Ant 集成是由 AntBuilder 提供的.git