Apache Ant是在Java世界中具有悠久历史的构建工具,尽管有越来越少的团队,但它仍被广泛使用. 虽然灵活,但缺少约定和Gradle可以提供的许多强大功能. 迁移到Gradle是值得的,这样您的构建可以变得更苗条,更简单和更快,同时仍保留您使用Ant享受的灵活性. 您还将受益于对多项目构建的强大支持以及易于使用的灵活依赖管理.

从Ant迁移到Gradle的最大挑战是,没有标准的Ant构建之类的东西. 这使得很难提供具体说明. 幸运的是,Gradle具有与Ant的强大集成功能,可以使过程相对平稳. 甚至从基于Ivy的依赖项管理迁移也并非特别困难,因为Gradle具有基于依赖项配置的相似模型,该模型可与兼容Ivy的存储库一起使用.

我们将首先概述将构建从Ant迁移到Gradle时应考虑的事项,并提供一些有关如何进行的一般指导.

General guidelines

当您承诺将构建从Ant迁移到Gradle时,应牢记既有资源的性质以及最终用途. 您是否需要Gradle构建来反映现有Ant构建的结构? 还是您想改用Gradle惯用的方法? 您正在寻找的主要好处是什么?

要理解其含义,请考虑您可以针对的两个极端端点:

  • 通过ant.importBuild()导入的构建

    这种方法快速,简单,并且适用于许多基于Ant的构建. 最后,您得到的构建实际上与原始Ant构建完全相同,只是您的Ant目标成为了Gradle任务. 甚至保留了目标之间的依赖关系.

    缺点是您仍在使用Ant构建,必须继续对其进行维护. 您还将失去Gradle约定,许多插件,依赖管理等优点. 您仍然可以使用增量构建信息来增强构建,但是比正常的Gradle构建要付出更多的努力.

  • 惯用的Gradle构建

    如果您想将来对构建进行验证,那么这里就是您要结束的地方. 利用Gradle的约定和插件将导致更小,更易于维护的构建,其结构对于许多Java开发人员来说都是熟悉的. 您还将发现更容易利用Gradle的强大功能来提高构建性能.

    主要缺点是执行迁移所需的额外工作,尤其是在现有构建很复杂且具有许多项目间依赖关系的情况下. 但是,这种构建通常会从转向idomatic Gradle的过程中受益最大. 另外,Gradle提供了许多可简化迁移的功能,例如直接从Gradle构建中使用核心和自定义Ant任务的功能 .

从长远来看,理想情况下,您希望最终接近第二种选择,但是您不必一there而就.

接下来是一系列步骤,可帮助您确定要采用的方法以及如何执行该方法:

  1. 并排保留旧的Ant构建和新的Gradle构建

    您知道Ant构建是可行的,因此应该保留它,直到您确信Gradle构建会生成所有相同的工件,然后再做您需要的事情. 这也意味着用户可以在不获取源树的新副本的情况下尝试Gradle构建.

    在准备好进行切换之前,请勿尝试更改构建的目录和文件结构.

  2. 开发一种机制来验证两个构建产生相同的工件

    这是确保您的部署和测试不中断的至关重要的一步. 即使是很小的更改,例如JAR中清单文件的内容,也会引起问题. 如果您的Gradle构建产生与Ant构建相同的输出,这将使您和其他人对切换充满信心,并使更容易实施将带来最大收益的重大变更.

  3. 确定您是否具有多项目构建

    与单项目构建相比,多项目构建通常更难迁移且需要更多的工作. 在" 迁移多项目构建"部分中,我们提供了一些专用的建议来帮助完成该过程.

  4. 找出每个项目要使用的插件

    我们希望绝大多数的Ant构建都是基于JVM的项目 ,为此,有许多插件可以提供您所需的许多功能. Gradle不仅随附了核心插件 ,您还可以在Plugin Portal上找到许多有用的插件 .

    即使Java插件或其派生工具之一(例如Java库插件 )与您的构建不是很好的匹配,您也应至少考虑将Base Plugin用于其生命周期任务.

  5. 导入Ant构建或从头开始创建Gradle构建

    此步骤很大程度上取决于构建的要求. 如果精选的Gradle插件可以完成Ant构建所做的大部分工作,那么创建一个不依赖于Ant构建的新鲜Gradle构建脚本可能是有意义的,它自己实现缺少的部分或利用现有的部分蚂蚁任务 .

    另一种方法是将Ant构建导入到Gradle构建脚本中,并逐步替换Ant构建功能. 这样可以使您在每个阶段都有一个有效的Gradle构建,但是需要一些工作才能使Gradle任务与Ant任务一起正常工作. 您可以在使用导入的版本中了解有关此方法的更多信息.

  6. 为现有目录和文件结构配置构建

    Gradle利用约定来消除与旧版本相关联的许多样板,并在用户熟悉这些约定后使用户更轻松地使用新版本. 但这并不意味着您必须遵循它们.

    Gradle提供了许多配置选项,可以实现高度的自定义. 这些选项通常可以通过提供约定的插件使用. 例如,Java插件提供了用于生产Java代码的标准源目录结构src/main/java ,它允许您配置其他源路径 . 可以通过Project对象上的属性修改许多路径.

  7. 如果愿意,可以迁移到标准Gradle约定

    一旦确信Gradle构建会产生与Ant构建相同的工件和其他资源,就可以考虑迁移到标准约定,例如源目录路径. 这样做将允许您删除覆盖这些约定所需的额外配置. 新的团队成员还将发现更改后更容易使用构建.

    由您决定此步骤是否值得花费时间,精力和可能造成的中断,而这又取决于您的特定构建和团队.

本章的其余部分介绍了您在迁移期间可能要处理的一些常见方案,例如依赖关系管理和使用Ant任务.

Working with an imported build

许多迁移的第一步将涉及使用ant.importBuild() 导入Ant构建 . 如果这样做,那么如何在不立即替换所有内容的情况下过渡到标准Gradle构建?

要记住的重要一点是,Ant目标成为真正的Gradle任务,这意味着您可以执行诸如修改其任务依赖性,附加额外的任务动作等操作. 这使您可以用本地Gradle任务替代等效的Ant任务,并保持与其他现有任务的任何链接.

例如,假设您有一个Java库项目要从Ant迁移到Gradle. Gradle构建脚本中的代码行导入了Ant构建,现在想使用标准Gradle机制来编译Java源文件. 但是,您想继续使用现有的package任务来创建库的JAR文件.

以示意图的形式,情况如下所示,其中每个框代表一个目标/任务:

ant task migration

这个想法是用标准的Gradle compileJava任务代替Ant build任务. 此替换涉及几个步骤:

  1. 应用Java库插件

    这提供了图中所示的compileJava任务.

  2. 重命名旧的build任务

    名称build基本插件 (通过Java库插件)提供的标准build任务冲突.

  3. 配置编译以使用现有目录结构

    Ant构建很有可能不符合标准Gradle目录结构,因此您需要告诉Gradle在哪里可以找到源文件以及在哪里放置编译好的类,以便package可以找到它们.

  4. 更新任务依赖项

    compileJava必须依赖preparepackage必须依赖compileJava而不是ant_build ,而assemble必须依赖于package而不是标准Gradle jar任务.

应用插件就像在Gradle构建脚本的ant.importBuild()ant.importBuild()之前ant.importBuild()插入plugins {}块一样简单. 这是应用Java库插件的方法:

例子1.应用Java库插件
build.gradle
plugins {
    id 'java-library'
}
build.gradle.kts
plugins {
    `java-library`
}

要重命名build任务,请使用AntBuilder.importBuild()的变体,它接受一个转换器,如下所示:

例子2.重命名导入目标
build.gradle
ant.importBuild('build.xml') { String oldTargetName ->
    return oldTargetName == 'build' ? 'ant_build' : oldTargetName  // (1)
}
build.gradle.kts
ant.importBuild("build.xml") { oldTargetName ->
    if (oldTargetName == "build") "ant_build" else oldTargetName  // (1)
}
  1. build目标重命名为ant_build并使所有其他目标保持不变

构建Java和JVM项目一章中介绍了为源配置不同的路径,同时您可以以类似的方式更改已编译类的输出目录.

假设原始的Ant构建将这些路径存储在Ant属性中, src.dir用于Java源文件,而classes.dir用于输出. 这是配置Gradle使用这些路径的方法:

例子3.配置源集
build.gradle
sourceSets {
    main {
        java {
            srcDirs = [ ant.properties['src.dir'] ]
            outputDir = file(ant.properties['classes.dir'])
        }
    }
}
build.gradle.kts
sourceSets {
    main {
        java.setSrcDirs(listOf(ant.properties["src.dir"]))
        java.outputDir = file(ant.properties["classes.dir"] ?: "$buildDir/classes")
    }
}

最终,您应该尽可能地针对您的项目类型切换标准目录结构,然后就可以删除此自定义设置.

最后一步也很简单,涉及使用Task.dependsOn属性和Task.dependsOn()方法来分离和链接任务. 该属性适合替换依赖关系,而该方法是添加到现有依赖关系的首选方法.

这是示例场景所需的必需任务依赖项配置,应在Ant构建导入之后进行:

例子4.配置任务依赖性
build.gradle
compileJava.dependsOn 'prepare'  // (1)
package.dependsOn = [ 'compileJava' ]  // (2)
assemble.dependsOn = [ 'package' ]  // (3)
build.gradle.kts
tasks {
    compileJava {
        dependsOn("prepare")  // (1)
    }
    named("package") {
        setDependsOn(listOf(compileJava))  // (2)
    }
    assemble {
        setDependsOn(listOf("package"))  // (3)
    }
}
  1. 使编译取决于prepare任务

  2. ant_build任务中分离package ,并使它依赖于compileJava

  3. 分离assemble从标准Gradle jar任务assemble而成的,因此它取决于package

而已! 这四个步骤将成功用Gradle实现替换旧的Ant编译. 即使是很小的迁移也会有很大帮助,因为您将能够利用Gradle的增量Java编译来加快构建速度.

💡

这只是如何逐步执行迁移的演示. 由于这三个方面都已很好地集成在Gradle中,因此在此阶段包含资源处理(如属性文件)和打包内容可能更有意义.

您必须问自己的一个重要问题是,每个阶段要迁移多少任务. 您可以一次迁移的块越大越好,但是这必须抵消更改将影响Ant构建中的自定义步骤数量.

例如,如果Ant构建遵循相当标准的方法进行编译,静态资源,打包和单元测试,则可能值得将所有这些一起迁移. 但是,如果构建对编译后的类执行了一些额外的处理,或者在处理静态资源时执行了一些独特的处理,则可能值得将这些任务分成单独的阶段.

Managing dependencies

Ant构建通常采用以下两种方法之一来处理二进制依赖性 (例如库):

  • 将它们与项目一起存储在本地" lib"目录中

  • 使用Apache Ivy来管理它们

他们每个都需要使用不同的技术来迁移到Gradle,但是无论哪种情况,您都会发现过程很简单. 我们将在以下各节中详细介绍每种方案.

Serving dependencies from a directory

当您尝试迁移将其依赖项存储在本地或网络上的文件系统上的构建时,应考虑是否最终要使用远程存储库移至托管依赖项. 这是因为您可以通过以下两种方式之一将文件系统依赖项合并到Gradle构建中:

如果采用第一种方法,则更容易迁移到从Maven或Ivy兼容存储库提供的托管依赖项,但是这样做要求所有文件都符合命名约定" <moduleName>-<version>.<extension>".

如果将依赖项存储在标准的Maven存储库布局中- <repoDir>/<group>/<module>/<version> -那么您可以使用" file://" URL定义自定义Maven存储库 .

为了演示这两种技术,请考虑一个在其libs目录中具有以下库JAR的项目:

libs
├── our-custom.jar
├── log4j-1.2.8.jar
└── commons-io-2.1.jar

文件our-custom.jar缺少版本号,因此必须将其添加为文件依赖项. 但是其他两个JAR匹配所需的命名约定,因此可以声明为从平面目录存储库检索的常规模块依赖项 .

下面的示例构建脚本演示了如何将所有这些库合并到构建中:

例子5.声明文件系统提供的依赖
build.gradle
repositories {
    flatDir {
        name = 'libs dir'
        dir file('libs')  // (1)
    }
}

dependencies {
    implementation files('libs/our-custom.jar')  // (2)
    implementation ':log4j:1.2.8', ':commons-io:2.1'  // (3)
}
build.gradle.kts
repositories {
    flatDir {
        name = "libs dir"
        dir(file("libs"))  // (1)
    }
}

dependencies {
    implementation(files("libs/our-custom.jar"))  // (2)
    implementation(":log4j:1.2.8")     // (3)
    implementation(":commons-io:2.1")  // (3)
}
  1. 指定包含JAR文件的目录的路径

  2. 声明未版本化JAR的文件依赖关系

  3. 使用标准依赖关系坐标声明依赖关系-请注意,未指定任何组,但是每个标识符都有一个前导: ,表示一个空的组

上面的示例会将our-custom.jarlog4j-1.2.8.jarcommons-io-2.1.jarimplementation配置中,该配置用于编译项目的代码.

您也可以在这些模块依赖项中指定一个组,即使它们实际上没有组. 这是因为平面目录存储库只是忽略了信息.

如果以后再添加一个与Maven或Ivy兼容的常规存储库,则Gradle将优先从该存储库中下载用组声明的模块依赖关系,而不是从平面目录中下载.

Migrating Ivy dependencies

Apache Ivy是一个独立的依赖项管理工具,已与Ant一起广泛使用. 它的工作方式与Gradle类似. 实际上,它们都允许您

  • 定义自己的配置

  • 相互扩展配置

  • 将依赖项附加到配置

  • 解决来自Ivy兼容存储库的依赖关系

  • 将工件发布到兼容Ivy的存储库

最明显的区别是Gradle具有针对特定项目类型的标准配置. 例如, Java插件定义了一些配置,例如implementationtestImplementationruntimeOnly . 不过,您仍然可以定义自己的依赖项配置 .

这种相似性意味着从Ivy迁移到Gradle通常非常简单:

  • 将模块声明中的依赖项声明翻译为Gradle构建脚本的依赖项{}块,最好使用您所应用的任何插件提供的标准配置.

  • 将模块描述符中的所有配置声明转录到构建脚本的configuration {}块中,以获取任何无法用Gradle的标准配置替代的自定义配置.

  • 将解析器从您的Ivy设置文件转录到构建脚本的存储库{}块中.

Ivy提供了一些Ant任务,这些任务处理Ivy的获取依赖项的过程. 该过程的基本步骤包括:

  1. 配置 -应用常春藤设置文件中定义的配置

  2. 解决 -找到声明的依赖项,并在必要时将其下载到缓存

  3. 检索 -将缓存的依赖项复制到另一个目录

Gradle的过程类似,但是您不必显式调用前两个步骤,因为它会自动执行它们. 第三步根本不会发生-除非您创建要执行的任务-因为Gradle通常通常直接在类路径中使用依赖项缓存中的文件,并将其用作组装应用程序包的源.

让我们更详细地了解Ivy的步骤如何映射到Gradle:

Configuration

Gradle的大多数与依赖项相关的配置都包含在构建脚本中,如您所看到的,诸如dependencies {}块之类的元素一样. 另一个特别重要的配置元素是resolutionStrategy ,可以从依赖项配置中访问它. 这提供了您可能从Ivy的冲突管理器中获得的许多功能,并且是控制可传递依赖项和缓存的有效方法.

一些Ivy配置选项在Gradle中没有等效项. 例如,由于Gradle确保其依赖项缓存是并发安全的,因此没有锁定策略. 也没有"最新策略",因为拥有可靠的单一冲突解决策略比较容易. 如果选择了"错误"版本,则可以使用强制版本或其他解决方案策略选项轻松覆盖它.

有关Gradle这方面的更多信息,请参见控制传递依赖的章节.

Resolution

在构建开始时,Gradle将自动解决您声明的所有依赖项并将其下载到其缓存中. 它在存储库中搜索那些依赖项,其搜索顺序由存储库的声明顺序定义.

值得注意的是,Gradle支持与Ivy相同的动态版本语法,因此您仍可以使用1.0.+类的版本. 如果需要,还可以使用特殊的latest.integrationlatest.release标签. 如果决定使用这种动态变化的依赖关系,则可以通过resolutionStrategy为它们配置缓存行为.

如果您使用动态和/或更改依赖关系,则可能还需要考虑依赖关系锁定 . 这是使构建更可靠并允许可复制的构建的一种方法.

Retrieval

如前所述,Gradle不会自动从依赖项缓存中复制文件. 它的标准任务通常直接使用文件. 如果要将依赖项复制到本地目录,则可以在构建脚本中使用以下复制任务:

例子6.将依赖项复制到本地目录
build.gradle
task retrieveRuntimeDependencies(type: Copy) {
    into "$buildDir/libs"
    from configurations.runtimeClasspath
}
build.gradle.kts
tasks {
    register<Copy>("retrieveRuntimeDependencies") {
        into("$buildDir/libs")
        from(configurations.runtimeClasspath)
    }
}

配置也是文件集合,因此为什么可以在from()配置中使用它. 您可以使用类似的技术将配置附加到编译任务或生成文档的任务. 有关更多示例和有关Gradle文件API的信息,请参见使用文件一章.

Publishing artifacts

使用Ivy管理依赖关系的项目也经常使用它来将JAR和其他工件发布到存储库. 如果您要迁移这样的构建,那么您将很高兴知道Gradle内置了对将工件发布到兼容Ivy的存储库的支持.

在尝试迁移构建的此特定方面之前,请阅读" 发布"一章,以了解Gradle的发布模型. 该章的示例基于Maven存储库,但Ivy存储库也使用相同的模型.

基本的迁移过程如下所示:

完成这些操作后,您将能够为每个发布生成一个Ivy模块描述符,并将它们发布到一个或多个存储库中.

假设您已经定义了一个名为" myLibrary"的发布和一个名为" myRepo"的存储库. 然后,Ivy的Ant任务将映射到Gradle任务,如下所示:

  • <deliver>generateDescriptorFileForMyLibraryPublication

  • <publish>publishMyLibraryPublicationToMyRepoRepository

还有一个方便的publish任务,可将所有出版物发布到所有存储库. 如果您希望限制将哪些出版物转到哪个存储库,请查看"出版"一章相关部分 .

关于依赖版本

在默认情况下,Ivy在生成模块描述符时会自动将动态依赖关系的版本替换为已解析的"静态"版本. 摇篮不会模仿这种行为:宣告依赖版本保持不变.

您可以使用Nebula Ivy Resolved Plugin复制默认的Ivy行为. 或者,您可以自定义描述符文件 ,使其包含所需的版本.

Dealing with custom Ant tasks

Ant的优点之一是创建自定义任务并将其合并到构建中相当容易. 如果您有这样的任务,则有两个主要选项可将它们迁移到Gradle构建:

第一个选项通常快速简便,但并非总是如此. 而且,如果要将任务集成到增量构建中,则必须使用增量构建运行时API . 您还经常需要处理笨拙的Ant路径和文件集.

如果有时间,从长远来看,第二个选项是可取的. Gradle任务类型往往比Ant任务更简单,因为它们不必使用基于XML的接口. 您还可以访问Gradle的丰富API. 最后,这种方法可以利用基于类型化属性的类型安全增量构建API .

Working with files

Ant有许多处理文件的任务,其中大多数具有Gradle等效项. 与从Ant到Gradle迁移的其他区域一样,您可以在Gradle构建中使用这些Ant任务 . 但是,我们强烈建议在可能的情况下迁移到本地Gradle构造,以使该构造受益于:

  • Incremental build

  • 易于与构建的其他部分集成,例如依赖项配置

  • 更多惯用的构建脚本

也就是说,使用没有直接等效项的Ant任务(例如<checksum><chown> . 即使这样,从长远来看,最好将它们转换为使用标准Java API或第三方库来实现同一目的的本地Gradle任务类型.

这是Ant构建所使用的最常见的文件相关元素,以及Gradle等效项:

  • <copy> -更喜欢Gradle Copy任务类型

  • <zip> (加上Java变体)—更喜欢Zip任务类型(加上JarWarEar

  • <unzip> —最好将Project.zipTree()方法与Copy任务一起使用

您可以看到Gradle文件API的几个示例,并在" 使用文件"一章中了解有关它的更多信息.

在路径和文件集上

Ant利用类路径结构和文件集的概念来使用户能够处理文件和目录的集合. Gradle有一个基于FileCollectionFileTree的更简单,更强大的模型,可以将其视为内部版本的对象. 两种类型均允许基于Ant的glob语法进行过滤,例如**/books_* . 在" 使用文件"一章中了解有关Gradle文件API的这些类型和其他方面的更多信息.

如果您需要与需要它们的Ant任务进行交互,那么仍然可以通过ant对象从内部构建Ant路径和文件集. 有关Ant集成的章节提供了同时使用<path><fileset>示例. FileCollection甚至有一个方法可以将文件集合转换为文件集或类似的Ant类型.

Migrating Ant properties

Ant利用属性映射来存储可在整个构建过程中重复使用的值. 这种方法的最大缺点是属性值都是字符串,并且属性本身的行为类似于全局变量.

💡
与Gradle中的Ant属性交互

有时,您可能想直接从Gradle构建中使用Ant任务,而该任务需要设置一个或多个Ant属性. 在这种情况下,您可以通过ant对象轻松设置这些属性,如使用Gradle中的Ant一章所述.

Gradle确实以项目属性的形式使用了类似的东西,这是参数化构建的合理方法. 这些可以从命令行,在gradle.properties文件中设置 ,甚至可以通过专门命名的系统属性和环境变量来设置.

If you have existing Ant properties files, you can copy their contents into the project’s gradle.properties file. Just be aware of two important points:

  • gradle.properties设置的属性不会覆盖在构建脚本中定义的具有相同名称的其他项目属性

  • 导入的Ant任务不会自动"查看" Gradle项目属性-您必须将它们复制到Ant属性映射中才能实现

要理解的另一个重要因素是,Gradle构建脚本可与面向对象的API一起使用,并且通常最好尽可能使用任务,源集和其他对象的属性. 例如,此构建脚本片段创建用于将Javadoc文档打包为JAR并将其解压缩的任务,并通过其属性链接任务:

例子7.使用任务属性代替项目属性
build.gradle
ext {
    tmpDistDir = file("$buildDir/dist")
}

task javadocJarArchive(type: Jar) {
    from javadoc  // (1)
    archiveClassifier = 'javadoc'
}

task unpackJavadocs(type: Copy) {
    from zipTree(javadocJarArchive.archiveFile)  // (2)
    into tmpDistDir  // (3)
}
build.gradle.kts
val tmpDistDir by extra { file("$buildDir/dist") }

tasks {
    register<Jar>("javadocJarArchive") {
        from(javadoc)  // (1)
        archiveClassifier.set("javadoc")
    }

    register<Copy>("unpackJavadocs") {
        from(zipTree(named<Jar>("javadocJarArchive").get().archiveFile))  // (2)
        into(tmpDistDir)  // (3)
    }
}
  1. 打包所有javadoc的输出文件-等同from javadoc.destinationDir

  2. 使用javadocJar任务持有的Javadoc JAR的位置

  3. 使用名为tmpDistDir的额外项目属性来定义" dist"目录的位置

从使用tmpDistDir的示例中可以看到,通常仍然需要通过属性定义路径等,这就是为什么Gradle还提供了可以附加到项目,任务和某些其他类型的对象上的额外属性的原因.

Migrating multi-project builds

多项目构建对于迁移是一个特殊的挑战,因为Ant中没有用于构建它们或处理项目间依赖关系的标准方法. 他们中的大多数人可能以某种方式使用<ant>任务,但这仅是一个可以说的内容.

幸运的是,Gradle的多项目支持可以处理相当不同的项目结构,并且在构建和维护多项目构建方面比Ant提供了更强大和有用的支持. ant.importBuild()方法还透明地处理<ant><antcall>任务,从而允许分阶段迁移.

我们将在此处建议一个迁移过程,并希望它可以适合您的情况,或者至少可以给您一些想法. 它像这样分解:

  1. 从学习Gradle如何配置多项目构建开始 .

  2. 在构建的每个项目中创建一个Gradle构建脚本,将其内容设置为此行:

    ant.importBuild 'build.xml'
    ant.importBuild("build.xml")

    build.xml替换为与项目相对应的实际Ant构建文件的路径. 如果没有相应的Ant构建文件,请将Gradle构建脚本保留为空. 在这种情况下,您的构建可能不适合这种迁移方法,但请继续执行以下步骤,以查看是否仍然存在进行分阶段迁移的方法.

  3. Create a settings file that includes all the projects that now have a Gradle build script.

  4. 实现项目间的依赖关系.

    多项目构建中的某些项目将取决于该构建中一个或多个其他项目产生的工件. 这样的项目需要确保它们所依赖的那些项目已经产生了工件,并且它们知道通往这些工件的路径.

    Ensuring the production of the required artifacts typically means calling into other projects' builds via the <ant> task. This unfortunately bypasses the Gradle build, negating any changes you make to the Gradle build scripts. You will need to replace targets that use <ant> tasks with Gradle task dependencies.

    例如,假设您有一个Web项目,该项目依赖于同一构建中的" util"库. " web"的Ant构建文件可能具有这样的目标:

    web/build.xml
        <target name="buildRequiredProjects">
            <ant dir="${root.dir}/util" target="build"/>  (1)
        </target>
    1. root.dir必须由构建定义

    如下面的示例所示,假定" web"项目的" compile"任务是需要事先构建" util"的事物,则可以用相应的Gradle构建脚本中的项目间任务依赖关系代替.

    web/build.gradle
    ant.importBuild 'build.xml'
    
    compile.dependsOn = [ ':util:build' ]
    web/build.gradle.kts
    ant.importBuild("build.xml")
    
    tasks {
        named<Task>("compile") {
            setDependsOn(listOf(":util:build"))
        }
    }

    它不像Gradle的项目依赖项那样健壮或强大,但是它解决了眼前的问题,而无需对构建进行大的更改. 请小心删除或覆盖对委派给其他子项目的任务的任何依赖,例如buildRequiredProjects任务.

  5. 确定不依赖于其他项目的项目,并将其迁移到惯用的Gradle构建脚本.

    Just follow the advice in the rest of this guide to migrate individual project builds. As mentioned elsewhere, you should ideally use Gradle standard plugins where possible. This may mean that you need to add an extra copy task to each build that copies the generated artifacts to the location expected by the rest of the Ant builds.

  6. 当项目完全依赖于具有完全迁移的Gradle构建的项目时,即可进行迁移.

    此时,您应该能够切换到使用附加到适当的依赖性配置的适当的项目依赖性.

  7. 一旦没有任何Ant构建依赖项目,请清理它们.

    在第5步中,我们提到您可能需要添加复制任务才能满足从属Ant构建的要求. 一旦这些构建已被迁移,就不再需要这种构建逻辑,应将其删除.

在该过程的最后,您应该拥有一个Gradle构建,您可以确信它可以按预期工作,并且构建逻辑比以前少得多.

Further reading

本章涵盖了特定于将Ant构建迁移到Gradle的主要主题. 剩下的就是迁移期间或迁移之后可能有用的其他一些方面:

最后,本指南仅涉及Gradle的一些功能,我们鼓励您从用户手册的其他章节以及教程式的Gradle Guides中了解其余内容.