Gradle 提供了与 Ant 的出色集成。您可以在 Gradle 构建中使用单个 Ant 任务或整个 Ant 构建。事实上,您会发现在 Gradle 构建脚本中使用 Ant 任务比使用 Ant 的 XML 格式更容易、更强大。您甚至可以将 Gradle 简单地用作强大的 Ant 任务脚本工具。
Ant可以分为两层。第一层是Ant语言。它提供文件的语法build.xml、目标的处理、宏定义等特殊结构等。换句话说,除了 Ant 任务和类型之外的所有内容。 Gradle 理解这种语言,并允许您将 Antbuild.xml直接导入到 Gradle 项目中。然后,您可以使用 Ant 构建的目标,就好像它们是 Gradle 任务一样。
Ant 的第二层是其丰富的 Ant 任务和类型,例如javac、copy或jar。对于这一层,Gradle 只需依赖 Groovy 和出色的AntBuilder.
最后,由于构建脚本是 Groovy 脚本,因此您始终可以将 Ant 构建作为外部进程执行。您的构建脚本可能包含以下语句"ant clean compile".execute():[ 1 ]
您可以使用 Gradle 的 Ant 集成作为将构建从 Ant 迁移到 Gradle 的路径。例如,您可以首先导入现有的 Ant 构建。然后,您可以将依赖项声明从 Ant 脚本移至构建文件。最后,您可以将任务移至构建文件,或用 Gradle 的一些插件替换它们。这个过程可以随着时间的推移分部分完成,并且您可以在整个过程中构建一个有效的 Gradle。
| Ant 集成与配置缓存 不完全兼容。使用Task.ant在任务操作中运行 Ant 任务可能有效,但不支持导入 Ant 构建。 |
在构建中使用 Ant 任务和类型
ant在您的构建脚本中, Gradle 提供了一个名为 的属性。这是对AntBuilder实例的引用。这AntBuilder用于从构建脚本访问 Ant 任务、类型和属性。从 Antbuild.xml格式到 Groovy 有一个非常简单的映射,如下所述。
您可以通过调用实例上的方法来执行 Ant 任务AntBuilder。您使用任务名称作为方法名称。例如,您echo通过调用该ant.echo()方法来执行 Ant 任务。 Ant 任务的属性作为 Map 参数传递给该方法。下面是该任务的示例echo。请注意,我们还可以混合 Groovy 代码和 Ant 任务标记。这可能非常强大。
tasks.register("hello") {
doLast {
val greeting = "hello from Ant"
ant.withGroovyBuilder {
"echo"("message" to greeting)
}
}
}
tasks.register('hello') {
doLast {
String greeting = 'hello from Ant'
ant.echo(message: greeting)
}
}
gradle hello> gradle hello > Task :hello [ant:echo] hello from Ant BUILD SUCCESSFUL in 0s 1 actionable task: 1 executed
您可以将嵌套文本作为任务方法调用的参数传递给 Ant 任务。在此示例中,我们将任务消息echo作为嵌套文本传递:
tasks.register("hello") {
doLast {
ant.withGroovyBuilder {
"echo"("message" to "hello from Ant")
}
}
}
tasks.register('hello') {
doLast {
ant.echo('hello from Ant')
}
}
gradle hello> gradle hello > Task :hello [ant:echo] hello from Ant BUILD SUCCESSFUL in 0s 1 actionable task: 1 executed
您将嵌套元素传递给闭包内的 Ant 任务。嵌套元素的定义方式与任务相同,通过调用与我们要定义的元素同名的方法。
tasks.register("zip") {
doLast {
ant.withGroovyBuilder {
"zip"("destfile" to "archive.zip") {
"fileset"("dir" to "src") {
"include"("name" to "**.xml")
"exclude"("name" to "**.java")
}
}
}
}
}
tasks.register('zip') {
doLast {
ant.zip(destfile: 'archive.zip') {
fileset(dir: 'src') {
include(name: '**.xml')
exclude(name: '**.java')
}
}
}
}
您可以像访问任务一样访问 Ant 类型,使用类型名称作为方法名称。该方法调用返回 Ant 数据类型,然后您可以直接在构建脚本中使用该数据类型。在下面的示例中,我们创建一个 Antpath对象,然后迭代它的内容。
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)
}
}
}
tasks.register('list') {
doLast {
def path = ant.path {
fileset(dir: 'libs', includes: '*.jar')
}
path.list().each {
println it
}
}
}
有关更多信息,AntBuilder请参阅“Groovy in Action”8.4 或Groovy Wiki。
在构建中使用自定义 Ant 任务
要使自定义任务在您的构建中可用,您可以使用taskdef(通常更容易)或typedefAnt 任务,就像在文件中一样build.xml。然后,您可以像引用内置 Ant 任务一样引用自定义 Ant 任务。
tasks.register("check") {
val checkstyleConfig = file("checkstyle.xml")
doLast {
ant.withGroovyBuilder {
"taskdef"("resource" to "com/puppycrawl/tools/checkstyle/ant/checkstyle-ant-task.properties") {
"classpath" {
"fileset"("dir" to "libs", "includes" to "*.jar")
}
}
"checkstyle"("config" to checkstyleConfig) {
"fileset"("dir" to "src")
}
}
}
}
tasks.register('check') {
def checkstyleConfig = file('checkstyle.xml')
doLast {
ant.taskdef(resource: 'com/puppycrawl/tools/checkstyle/ant/checkstyle-ant-task.properties') {
classpath {
fileset(dir: 'libs', includes: '*.jar')
}
}
ant.checkstyle(config: checkstyleConfig) {
fileset(dir: 'src')
}
}
}
您可以使用 Gradle 的依赖项管理来组装类路径以用于自定义任务。为此,您需要为类路径定义自定义配置,然后向该配置添加一些依赖项。这在声明依赖关系中有更详细的描述。
val pmd = configurations.create("pmd")
dependencies {
pmd(group = "pmd", name = "pmd", version = "4.2.5")
}
configurations {
pmd
}
dependencies {
pmd group: 'pmd', name: 'pmd', version: '4.2.5'
}
要使用类路径配置,请使用asPath自定义配置的属性。
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")
}
}
}
}
tasks.register('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')
}
}
}
导入 Ant 构建
您可以使用该ant.importBuild()方法将 Ant 构建导入到 Gradle 项目中。当您导入 Ant 构建时,每个 Ant 目标都被视为一个 Gradle 任务。这意味着您可以按照与 Gradle 任务完全相同的方式操作和执行 Ant 目标。
ant.importBuild("build.xml")
ant.importBuild '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 目标的任务:
ant.importBuild("build.xml")
tasks.register("intro") {
dependsOn("hello")
doLast {
println("Hello, from Gradle")
}
}
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 目标添加行为:
ant.importBuild("build.xml")
tasks.named("hello") {
doLast {
println("Hello, from Gradle")
}
}
ant.importBuild 'build.xml'
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 任务:
ant.importBuild("build.xml")
tasks.register("intro") {
doLast {
println("Hello, from Gradle")
}
}
ant.importBuild 'build.xml'
tasks.register('intro') {
doLast {
println 'Hello, from Gradle'
}
}
<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)方法。
ant.importBuild("build.xml") { antTargetName ->
"a-" + antTargetName
}
ant.importBuild('build.xml') { antTargetName ->
'a-' + antTargetName
}
<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 属性和参考
有多种方法可以设置 Ant 属性,以便 Ant 任务可以使用该属性。您可以直接在实例上设置属性AntBuilder。 Ant 属性也可以作为您可以更改的 Map 提供。您还可以使用 Antproperty任务。以下是如何执行此操作的一些示例。
ant.setProperty("buildDir", buildDir)
ant.properties.set("buildDir", buildDir)
ant.properties["buildDir"] = buildDir
ant.withGroovyBuilder {
"property"("name" to "buildDir", "location" to "buildDir")
}
ant.buildDir = buildDir
ant.properties.buildDir = buildDir
ant.properties['buildDir'] = buildDir
ant.property(name: 'buildDir', location: buildDir)
许多 Ant 任务在执行时都会设置属性。有多种方法可以获取这些属性的值。您可以直接从实例获取属性AntBuilder。 Ant 属性也可以作为 Map 提供。以下是一些示例。
<property name="antProp" value="a property defined in an Ant build"/>
println(ant.getProperty("antProp"))
println(ant.properties.get("antProp"))
println(ant.properties["antProp"])
println ant.antProp
println ant.properties.antProp
println ant.properties['antProp']
有多种方法可以设置 Ant 引用:
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") }
ant.path(id: 'classpath', location: 'libs')
ant.references.classpath = ant.path(location: 'libs')
ant.references['classpath'] = ant.path(location: 'libs')
<path refid="classpath"/>
有多种方法可以获取 Ant 引用:
<path id="antPath" location="libs"/>
println(ant.references.get("antPath"))
println(ant.references["antPath"])
println ant.references.antPath
println ant.references['antPath']
蚂蚁日志记录
Gradle 将 Ant 消息优先级映射到 Gradle 日志级别,以便从 Ant 记录的消息出现在 Gradle 输出中。默认情况下,它们映射如下:
| 蚂蚁消息优先级 | Gradle 日志级别 |
|---|---|
详细 |
|
调试 |
|
信息 |
|
警告 |
|
错误 |
|
微调 Ant 日志记录
Ant 消息优先级到 Gradle 日志级别的默认映射有时可能会出现问题。例如,没有直接映射到LIFECYCLE日志级别的消息优先级,这是 Gradle 的默认设置。许多 Ant 任务以INFO优先级记录消息,这意味着要公开来自 Gradle 的这些消息,必须在日志级别设置为 的情况下运行构建INFO,可能会记录比所需多得多的输出。
相反,如果 Ant 任务以过高的级别记录消息,则要抑制这些消息将需要构建在更高的日志级别运行,例如QUIET.然而,这可能会导致其他所需的输出被抑制。
为了解决这个问题,Gradle 允许用户微调 Ant 日志记录并控制消息优先级到 Gradle 日志级别的映射。这是通过使用AntBuilder.setLifecycleLogLevel(java.lang.String)LIFECYCLE方法设置应映射到默认 Gradle日志级别的优先级来完成的。设置此值后,以配置的优先级或以上优先级记录的任何 Ant 消息将至少在 处记录。低于此优先级记录的任何 Ant 消息最多将被记录。LIFECYCLEINFO
例如,以下更改映射,以便在日志级别公开Ant INFOLIFECYCLE优先级消息。
ant.lifecycleLogLevel = AntBuilder.AntMessagePriority.INFO
tasks.register("hello") {
doLast {
ant.withGroovyBuilder {
"echo"("level" to "info", "message" to "hello from info priority!")
}
}
}
ant.lifecycleLogLevel = "INFO"
tasks.register('hello') {
doLast {
ant.echo(level: "info", message: "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优先级记录的 Ant 消息将不再在WARN日志级别记录。它们现在将被记录在该INFO级别,并且默认情况下将被抑制。
应用程序编程接口
Ant 集成由AntBuilder提供。