5月27日 23:17

Gradle 如何实现多项目构建?项目间依赖怎么配置?

Gradle 通过 settings.gradle 声明子项目,通过 project() 依赖建立项目间引用,配合 allprojects/subprojects 共享配置,实现多项目构建。

核心机制

多项目构建由一个根项目和若干子项目组成。settings.gradle 定义了哪些子项目参与构建,Gradle 据此建立项目间的依赖图并决定构建顺序。

groovy
// settings.gradle rootProject.name = 'my-project' include 'app', 'library', 'common' // 嵌套项目 include ':data:repository' project(':data:repository').projectDir = new File(rootDir, 'modules/data/repository')

项目间依赖配置

子项目之间通过 project() 函数声明依赖,Gradle 自动保证被依赖项目先构建:

groovy
// app/build.gradle dependencies { implementation project(':library') implementation project(':common') // 指定配置 implementation project(path: ':library', configuration: 'runtimeClasspath') } // library/build.gradle dependencies { api project(':common') // api 会传递依赖给上层 }

implementationapi 的区别在多项目中尤为关键:api 暴露依赖给消费方,implementation 则不传递。

共享配置的三种方式

1. allprojects / subprojects 注入

groovy
// 根 build.gradle allprojects { group = 'com.example' version = '1.0.0' repositories { mavenCentral() } } subprojects { apply plugin: 'java' java { sourceCompatibility = JavaVersion.VERSION_17 } }

2. 约定插件(Convention Plugin)

buildSrc 或独立插件项目中定义,比 subprojects 更灵活、可测试:

groovy
// buildSrc/src/main/groovy/my-java-convention.gradle plugins { id 'java-library' } java { sourceCompatibility = JavaVersion.VERSION_17 } // 子项目使用 // library/build.gradle plugins { id 'my-java-convention' }

3. 版本目录(Version Catalog)

toml
# gradle/libs.versions.toml [versions] spring-boot = "3.0.0" [libraries] spring-boot-web = { module = "org.springframework.boot:spring-boot-starter-web", version.ref = "spring-boot" }
groovy
// 子项目中使用 dependencies { implementation libs.spring.boot.web }

构建执行

bash
./gradlew projects # 查看项目结构 ./gradlew :app:build # 构建指定项目(自动构建其依赖项) ./gradlew build --parallel # 并行构建

并行构建需要在 gradle.properties 中启用:

properties
org.gradle.parallel=true org.gradle.caching=true org.gradle.configureondemand=true

循环依赖问题

项目 A 依赖 B,B 又依赖 A,Gradle 构建时会报错。解决方式是抽取公共部分到第三个模块,或者用 compileOnly/testImplementation 打断传递链。可通过 ./gradlew :app:dependencies --configuration runtimeClasspath 排查依赖链路。

追问

  • allprojectssubprojects 有什么区别?——allprojects 包含根项目,subprojects 只作用于子项目。
  • 约定插件相比 subprojects 闭包有什么优势?——可复用、可测试、支持按需引入,避免全局污染。
  • 如何让子项目独立构建而不触发其他项目?——configureondemand 配合按需配置,Gradle 6+ 默认部分启用。
标签:Gradle