Gradle提供了与Ant的出色集成. 您可以在Gradle构建中使用单个Ant任务或整个Ant构建. 实际上,您会发现,在Gradle构建脚本中使用Ant任务比使用Ant的XML格式要容易得多,功能更强大. 您甚至可以简单地将Gradle用作强大的Ant任务脚本工具.

蚂蚁可以分为两层. 第一层是Ant语言. 它提供了build.xml文件的语法,目标的处理,特殊构造(例如macrodefs)等等. 换句话说,除Ant任务和类型以外的所有内容. Gradle理解这种语言,并允许您将Ant build.xml直接导入Gradle项目. 然后,您可以像使用Gradle任务一样使用Ant构建的目标.

Ant的第二层是其丰​​富的Ant任务和类型,例如javaccopyjar . 对于这一层,Gradle仅依靠Groovy和出色的AntBuilder即可提供集成.

最后,由于构建脚本是Groovy脚本,因此您始终可以将Ant构建作为外部进程执行. 您的构建脚本可能包含如下语句: "ant clean compile".execute() . [ 1 ]

您可以使用Gradle的Ant集成作为将构建从Ant迁移到Gradle的路径. 例如,您可以从导入现有的Ant构建开始. 然后,您可以将依赖项声明从Ant脚本移至构建文件. 最后,您可以将任务移到构建文件中,或用Gradle的某些插件替换它们. 随着时间的流逝,该过程可以分几步完成,您可以在整个过程中构建一个有效的Gradle构建.

Using Ant tasks and types in your build

在您的构建脚本中,Gradle提供了一个名为ant的属性. 这是对AntBuilder实例的引用. 该AntBuilder用于从构建脚本访问Ant任务,类型和属性. 从Ant的build.xml格式到Groovy有一个非常简单的映射,下面将进行解释.

您可以通过在AntBuilder实例上调用方法来执行Ant任务. 您使用任务名称作为方法名称. 例如,您可以通过调用ant.echo()方法来执行Ant echo任务. Ant任务的属性作为Map参数传递给方法. 下面是echo任务的示例. 注意,我们还可以混合使用Groovy代码和Ant任务标记. 这可能非常强大.

示例1.使用Ant任务
build.gradle
task hello {
    doLast {
        String greeting = 'hello from Ant'
        ant.echo(message: greeting)
    }
}
build.gradle.kts
tasks.register("hello") {
    doLast {
        val greeting = "hello from Ant"
        ant.withGroovyBuilder {
            "echo"("message" to greeting)
        }
    }
}
gradle hello输出
> gradle hello

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

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

您可以通过将嵌套的文本作为任务方法调用的参数传递给Ant任务. 在此示例中,我们将echo任务的消息作为嵌套文本传递:

示例2.将嵌套文本传递给Ant任务
build.gradle
task hello {
    doLast {
        ant.echo('hello from Ant')
    }
}
build.gradle.kts
tasks.register("hello") {
    doLast {
        ant.withGroovyBuilder {
            "echo"("message" to "hello from Ant")
        }
    }
}
gradle hello输出
> gradle hello

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

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

您将嵌套元素传递给闭包内部的Ant任务. 通过调用与我们要定义的元素同名的方法,以与任务相同的方式定义嵌套元素.

例子3.将嵌套元素传递给Ant任务
build.gradle
task zip {
    doLast {
        ant.zip(destfile: 'archive.zip') {
            fileset(dir: 'src') {
                include(name: '**.xml')
                exclude(name: '**.java')
            }
        }
    }
}
build.gradle.kts
tasks.register("zip") {
    doLast {
        ant.withGroovyBuilder {
            "zip"("destfile" to "archive.zip") {
                "fileset"("dir" to "src") {
                    "include"("name" to "**.xml")
                    "exclude"("name" to "**.java")
                }
            }
        }
    }
}

您可以使用与访问任务相同的方式来访问Ant类型,方法是将类型的名称用作方法名称. 方法调用返回Ant数据类型,然后可以在构建脚本中直接使用它. 在以下示例中,我们创建一个Ant path对象,然后遍历它的内容.

例子4.使用Ant类型
build.gradle
task list {
    doLast {
        def path = ant.path {
            fileset(dir: 'libs', includes: '*.jar')
        }
        path.list().each {
            println it
        }
    }
}
build.gradle.kts
import org.apache.tools.ant.types.Path

tasks.register("list") {
    doLast {
        val path = ant.withGroovyBuilder {
            "path" {
                "fileset"("dir" to "libs", "includes" to "*.jar")
            }
        } as Path
        path.list().forEach {
            println(it)
        }
    }
}

有关AntBuilder更多信息, AntBuilder参见" Groovy in Action" 8.4或Groovy Wiki .

Using custom Ant tasks in your build

要使自定义任务在构建中可用,可以像在build.xml文件中一样使用taskdef (通常更容易)或typedef Ant任务. 然后,您可以像内置Ant任务一样引用自定义Ant任务.

例子5.使用定制的Ant任务
build.gradle
task check {
    doLast {
        ant.taskdef(resource: 'checkstyletask.properties') {
            classpath {
                fileset(dir: 'libs', includes: '*.jar')
            }
        }
        ant.checkstyle(config: 'checkstyle.xml') {
            fileset(dir: 'src')
        }
    }
}
build.gradle.kts
tasks.register("check") {
    doLast {
        ant.withGroovyBuilder {
            "taskdef"("resource" to "checkstyletask.properties") {
                "classpath" {
                    "fileset"("dir" to "libs", "includes" to "*.jar")
                }
            }
            "checkstyle"("config" to "checkstyle.xml") {
                "fileset"("dir" to "src")
            }
        }
    }
}

您可以使用Gradle的依赖关系管理来组装用于自定义任务的类路径. 为此,您需要为类路径定义一个自定义配置,然后向该配置中添加一些依赖项. 这在声明依赖项中有更详细的描述.

例子6.声明一个定制的Ant任务的类路径
build.gradle
configurations {
    pmd
}

dependencies {
    pmd group: 'pmd', name: 'pmd', version: '4.2.5'
}
build.gradle.kts
val pmd = configurations.create("pmd")

dependencies {
    pmd(group = "pmd", name = "pmd", version = "4.2.5")
}

要使用类路径配置,请使用定制配置的asPath属性.

示例7.一起使用定制Ant任务和依赖项管理
build.gradle
task check {
    doLast {
        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')
        }
    }
}
build.gradle.kts
tasks.register("check") {
    doLast {
        ant.withGroovyBuilder {
            "taskdef"("name" to "pmd",
                      "classname" to "net.sourceforge.pmd.ant.PMDTask",
                      "classpath" to pmd.asPath)
            "pmd"("shortFilenames" to true,
                  "failonruleviolation" to true,
                  "rulesetfiles" to file("pmd-rules.xml").toURI().toString()) {
                "formatter"("type" to "text", "toConsole" to "true")
                "fileset"("dir" to "src")
            }
        }
    }
}

Importing an Ant build

您可以使用ant.importBuild()方法将Ant构建导入到Gradle项目中. 导入Ant构建时,每个Ant目标都被视为Gradle任务. 这意味着您可以按照与Gradle任务完全相同的方式来操纵和执行Ant目标.

例子8.导入一个Ant版本
build.gradle
ant.importBuild 'build.xml'
build.gradle.kts
ant.importBuild("build.xml")
build.xml
<project>
    <target name="hello">
        <echo>Hello, from Ant</echo>
    </target>
</project>
gradle hello输出
> gradle hello

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

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

您可以添加一个依赖于Ant目标的任务:

例子9.依赖于Ant目标的任务
build.gradle
ant.importBuild 'build.xml'

task intro(dependsOn: hello) {
    doLast {
        println 'Hello, from Gradle'
    }
}
build.gradle.kts
ant.importBuild("build.xml")

tasks.register("intro") {
    dependsOn("hello")
    doLast {
        println("Hello, from Gradle")
    }
}
gradle intro输出
> gradle intro

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

> Task :intro
Hello, from Gradle

BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 executed

或者,您可以将行为添加到Ant目标:

例子10.向Ant目标添加行为
build.gradle
ant.importBuild 'build.xml'

hello {
    doLast {
        println 'Hello, from Gradle'
    }
}
build.gradle.kts
ant.importBuild("build.xml")

tasks.named("hello") {
    doLast {
        println("Hello, from Gradle")
    }
}
gradle hello输出
> gradle hello

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

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

Ant目标也有可能依赖Gradle任务:

例子11.依赖于Gradle任务的Ant目标
build.gradle
ant.importBuild 'build.xml'

task intro {
    doLast {
        println 'Hello, from Gradle'
    }
}
build.gradle.kts
ant.importBuild("build.xml")

tasks.register("intro") {
    doLast {
        println("Hello, from Gradle")
    }
}
build.xml
<project>
    <target name="hello" depends="intro">
        <echo>Hello, from Ant</echo>
    </target>
</project>
gradle hello输出
> gradle hello

> Task :intro
Hello, from Gradle

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

BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 executed

有时可能需要"重命名"为Ant目标生成的任务,以避免与现有Gradle任务发生命名冲突. 为此,请使用AntBuilder.importBuild(java.lang.Object,org.gradle.api.Transformer)方法.

例子12.重命名导入的Ant目标
build.gradle
ant.importBuild('build.xml') { antTargetName ->
    'a-' + antTargetName
}
build.gradle.kts
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

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

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

请注意,虽然此方法的第二个参数应该是Transformer ,但是在Groovy中进行编程时,由于Groovy支持将闭包自动强制转换为单抽象方法类型,因此我们可以简单地使用闭包而不是匿名内部类(或类似的内部类).

Ant properties and references

有几种方法可以设置Ant属性,以便Ant任务可以使用该属性. 您可以直接在AntBuilder实例上设置属性. Ant属性也可以作为Map来使用,您可以对其进行更改. 您还可以使用Ant property任务. 下面是一些有关如何执行此操作的示例.

例子13.设置一个Ant属性
build.gradle
ant.buildDir = buildDir
ant.properties.buildDir = buildDir
ant.properties['buildDir'] = buildDir
ant.property(name: 'buildDir', location: buildDir)
build.gradle.kts
ant.setProperty("buildDir", buildDir)
ant.properties.set("buildDir", buildDir)
ant.properties["buildDir"] = buildDir
ant.withGroovyBuilder {
    "property"("name" to "buildDir", "location" to "buildDir")
}

许多Ant任务在执行时都会设置属性. 有几种方法可以获取这些属性的值. 您可以直接从AntBuilder实例获取属性. Ant属性也可以作为Map使用. 以下是一些示例.

例子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']
build.gradle.kts
println(ant.getProperty("antProp"))
println(ant.properties.get("antProp"))
println(ant.properties["antProp"])

有几种方法可以设置Ant引用:

例子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.gradle.kts
ant.withGroovyBuilder { "path"("id" to "classpath", "location" to "libs") }
ant.references.set("classpath", ant.withGroovyBuilder { "path"("location" to "libs") })
ant.references["classpath"] = ant.withGroovyBuilder { "path"("location" to "libs") }
build.xml
<path refid="classpath"/>

有几种获取Ant参考的方法:

例子16.获取一个Ant参考
build.xml
<path id="antPath" location="libs"/>
build.gradle
println ant.references.antPath
println ant.references['antPath']
build.gradle.kts
println(ant.references.get("antPath"))
println(ant.references["antPath"])

Ant logging

Gradle将Ant消息优先级映射到Gradle日志级别,以便从Ant记录的消息出现在Gradle输出中. 默认情况下,这些映射如下:

Table 1. Ant message priority mapping
蚂蚁消息优先级 摇篮日志级别

VERBOSE

DEBUG

DEBUG

DEBUG

INFO

INFO

WARN

WARN

ERROR

ERROR

Fine tuning Ant logging

Ant消息优先级到Gradle日志级别的默认映射有时可能会出现问题. 例如,没有消息优先级直接映射到LIFECYCLE日志级别,这是Gradle的默认值. 许多Ant任务以INFO优先级记录消息,这意味着要从Gradle公开那些消息,必须在日志级别设置为INFO下运行构建,从而可能记录比期望更多的输出.

相反,如果Ant任务以太高的级别记录消息,则要抑制这些消息,将要求构建以更高的日志级别运行,例如QUIET . 但是,这可能会导致抑制其他期望的输出.

为了帮助解决这个问题,Gradle允许用户微调Ant日志并控制消息优先级到Gradle日志级别的映射. 这是通过使用AntBuilder.setLifecycleLogLevel(java.lang.String)方法设置应该映射到默认Gradle LIFECYCLE日志级别的优先级来完成的. 设置此值后,以配置的优先级或更高优先级记录的任何Ant消息将至少以LIFECYCLE记录. 低于此优先级记录的任何Ant消息最多将记录在INFO .

例如,以下内容更改了映射,以便在LIFECYCLE日志级别公开Ant INFO优先级消息.

例子17.调整Ant日志
build.gradle
ant.lifecycleLogLevel = "INFO"

task hello {
    doLast {
        ant.echo(level: "info", message: "hello from info priority!")
    }
}
build.gradle.kts
ant.lifecycleLogLevel = AntBuilder.AntMessagePriority.INFO

tasks.register("hello") {
    doLast {
        ant.withGroovyBuilder {
            "echo"("level" to "info", "message" to "hello from info priority!")
        }
    }
}
gradle hello输出
> gradle hello

> Task :hello
[ant:echo] hello from info priority!

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

另一方面,如果将lifecycleLogLevel设置为ERROR ,那么将不再以WARN日志级别记录以WARN优先级记录的Ant消息. 现在,它们将以INFO级别记录,并且默认情况下将被禁止.

API

Ant集成由AntBuilder提供.


1 . 在Groovy中,您可以执行字符串. 要了解有关使用Groovy执行外部流程的更多信息,请参阅" Groovy in Action" 9.3.2或Groovy Wiki.