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 会传递依赖给上层 }
implementation 与 api 的区别在多项目中尤为关键: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 中启用:
propertiesorg.gradle.parallel=true org.gradle.caching=true org.gradle.configureondemand=true
循环依赖问题
项目 A 依赖 B,B 又依赖 A,Gradle 构建时会报错。解决方式是抽取公共部分到第三个模块,或者用 compileOnly/testImplementation 打断传递链。可通过 ./gradlew :app:dependencies --configuration runtimeClasspath 排查依赖链路。
追问
allprojects和subprojects有什么区别?——allprojects包含根项目,subprojects只作用于子项目。- 约定插件相比
subprojects闭包有什么优势?——可复用、可测试、支持按需引入,避免全局污染。 - 如何让子项目独立构建而不触发其他项目?——
configureondemand配合按需配置,Gradle 6+ 默认部分启用。