Gradle之多项目与混合构建

本文介绍了Gradle的多项目构建和混合构建。多项目构建允许组织大型项目为多个独立模块,通过allprojects和subprojects进行配置。混合构建旨在解决多项目构建的复杂性,允许独立项目的组合。它不支持native项目,需包含settings.gradle,且不能嵌套。通过dependencySubstitution处理依赖替换。文中还展示了Android项目如何实践混合构建,尽管aar目前不支持。
摘要由CSDN通过智能技术生成
Multi-project builds
  1. 随着大型的单项目构建发展所面临的各种挑战,多项目构建应运而生。

  2. 多项目构建的结构如下:包括一个root顶层项目(包括build和setting脚本),之下再包含一个或多个子项目(包含build脚本):

    root-project
    ├── build.gradle
    ├── gradle
    │   └── wrapper
    │       ├── gradle-wrapper.jar
    │       └── gradle-wrapper.properties
    ├── gradlew
    ├── gradlew.bat
    ├── log
    ├── settings.gradle
    └── sub-project
        ├── build.gradle
        └── src
            ├── main
            │   └── java
            │       └── App.java
            └── test
                └── java
                    └── AppTest.java
  3. Multi-project builds的特点是:

    • 包含多个独立模块,且每个模块可独自进行构建,如Android应用构建;
    • 各个子项目可以拥有独立的构建脚本,注意子项目的构建脚本是非必须的;
    • 根项目的配置文件可以被整个项目所共享,即公共配置应该在根项目的构建脚本声明;
    • 不一定都是build.gradle,也可以是.gradle后缀结尾
  4. 注意:不管是单个模块或多个模块task的构建,都会在task执行之前完成所有的构建配置(比如插件下载与使用等)。因此,小的配置的变动都需要重新配置整个项目。虽然gradle提出了Configuration on demand的方式,但稳定性难以保证。

  5. 在Multi-project builds中,从配置的作用范围来看,可粗略地分为cross project configuration和subproject configuration两种。

  6. 首先是cross project configuration:构建的配置是跨越脚本而覆盖整个项目的,比如在某个子项目的配置脚本中直接修改另一个子项目的配置脚本:

    Closure cl = { task -> println "I'm $task.project.name" }
    task('hello').doLast(cl)
    project(':bluewhale') {
        task('hello').doLast(cl)
    }

    使用allprojects会更简洁,注意:allprojects作用的范围是本项目及其子项目

    allprojects {
        task hello {
            doLast { task ->
                println "I'm $task.project.name"
            }
        }
    }

    总之,相比其它的构建系统,gradle的这种配置方式是以configuration injection的方式来实现。

  7. 另一是subproject configuration:子项目的配置行为分为两种,不仅能配置项目构建的通用配置,还能实现特定配置、项目过滤配置等功能:

    • common behavior:公共的配置,同样借助于allprojects和subprojects来完成;
    • specific behavior:特定配置,可在私有构建脚本上或在公共构建脚本中使用project来完成;
  8. task依赖:无依赖的同名task,执行顺序是字母顺序。为了保证的多个task的执行顺序,可借助于dependsOn来实现有序执行。如下dependsOn的用法:

    task action(dependsOn: ":producer:action") {
        doLast {
            println("Consuming message: ${rootProject.producerMessage}")
        }
    }
  9. 属性依赖:配置脚本中的属性同样可能存在读写的顺序依赖,可通过evaluationDependsOn解决这个问题,该evaluationDependsOn能保证依赖的项目会先执行,如下例子:

    evaluationDependsOn(':producer')
    
    def message = rootProject.producerMessage
    
    task consume {
        doLast {
            println("Consuming message: " + message)
        }
    }
  10. lib依赖:Gradle支持lib依赖,比如jar、aar等,需要借助于gradle的compile来完成依赖的构建,因此构建task的执行顺序也能得以保证。

  11. 局部编译:gradle -a build命令可加快编译速度,该命令不会编译依赖项目。

  12. 多项目构建的执行方式:

    • 直接切换目录到对应的子项目下,使用gradle命令运行;
    • 在根目录下执行指定子项目的的构建,如gradle :services:webservice:build,注意依赖也会参与执行。
  13. 小结:虽然Gradle的依赖管理非常灵活、功能强大,但如果在构建脚本当中滥用allprojects, subprojects、project、evaluationDependsOn等便利方法是会带来了构建项目之间的耦合问题,比较好的解耦方式是使用dependencies进行管理。

Composite builds
  1. 面对日益复杂的构建系统,为了解决多项目构建代码的限制,Gradle又提出了Composite builds,称为混合构建。其目的是为了拆分大型的多项目构建。

  2. 混合构建的项目结构通常如下,可以认为参与构建的项目都是独立的项目,拥有settings.gradle脚本:

    composite
    ├── rootProject1
    │   ├── build.gradle
    │   ├── settings.gradle
    │   └── src
    │       └── main
    │           └── java
    │               └── App.java
    └── rootProject2
        ├── build.gradle
        ├── settings.gradle
        └── src
            └── main
                └── java
                    └── Api.java
  3. 混合构建方式有两种使用方式:

    • 命令行方式:gradle –include-build root_project task
    • Setting.gradle脚本方式:使用includeBuild将外部工程引入。
  4. 混合构建的局限性:

    • 不支持native项目
    • 必须包含settings.gradle文件
    • 混合构建不能嵌套
    • 要保证所有参与构建的rootProject.name的唯一性,包括顶层项目名
  5. 依赖替换:通过dependencySubstitution完成includeBuild中相关模块的替换。

  6. 实例basic工程结构如下图

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值