解决 Gradle 父项目的 subprojects 中无法获取子项目属性的问题
概要
最近在折腾 Gradle 的依赖版本统一管理,真的是一步一个坑。一开始求助于 ChatGPT ,提供了两个插件,一个是 java-platform ,另一个是 io.spring.dependency-management 。我选择了使用 java-platform ,但是各种尝试都是报错,大家有兴趣可以看看官网例子。
https://docs.gradle.org/current/userguide/java_platform_plugin.html
后来几番搜索,发现 Gradle7 之后又有一种新的版本管理的方式dependencyResolutionManagement
,官网介绍如下。
https://docs.gradle.org/current/userguide/platforms.html
但是官网的介绍太碎片化了,所以又百度了一下,找到了下面这个贴子,里面介绍得非常详细。
https://zhuanlan.zhihu.com/p/570009095?utm_id=0
主要内容
父项目 settings.gradle
rootProject.name = 'jia'
include 'jia-core', 'jia-mapper-common'
dependencyResolutionManagement {
versionCatalogs {
libs {
library('slf4j.api', 'org.slf4j:slf4j-api:1.7.30')
library('pagehelper', 'com.github.pagehelper:pagehelper:5.1.11')
library('mybatis-plus-core', 'com.baomidou:mybatis-plus:3.3.0')
library('jakarta.inject.api', 'jakarta.inject:jakarta.inject-api:2.0.1')
library('swagger.annotations', 'io.swagger:swagger-annotations:1.5.20')
library('lombok', 'org.projectlombok:lombok:1.18.20')
library('log4j', 'log4j:log4j:1.2.17')
library('slf4j-log4j12', 'org.slf4j:slf4j-log4j12:1.7.5')
}
}
}
父项目 build.gradle
allprojects {
group = 'cn.jia'
}
subprojects {
apply plugin: 'java-library'
apply plugin: 'maven-publish'
dependencies {
implementation libs.slf4j.api
annotationProcessor libs.lombok
compileOnly libs.lombok
}
java.sourceCompatibility = JavaVersion.VERSION_17
tasks.withType(JavaCompile).tap {
configureEach {
options.encoding = 'UTF-8'
}
}
test {
useJUnitPlatform()
}
processTestResources.dependsOn copyTestResources
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
repositories {
maven {
url = version.endsWith('SNAPSHOT') ? rootProject.ext.snapshotsRepoUrl : rootProject.ext.snapshotsRepoUrl
credentials {
username rootProject.ext.repoUsername
password rootProject.ext.repoPassword
}
}
}
}
}
jia-core 项目的 build.gradle
dependencies {
implementation libs.log4j
implementation libs.slf4j.api
implementation libs.slf4j.log4j12
implementation libs.lombok
testImplementation libs.junit.jupiter
testAnnotationProcessor libs.lombok
testImplementation libs.lombok
}
version = '1.1.1-SNAPSHOT'
description = 'jia-core'
jia-mapper-common 项目的 build.gradle
dependencies {
api project(':jia-core')
api libs.pagehelper
api libs.mybatis.plus.core
implementation libs.jakarta.inject.api
api libs.swagger.annotations
}
version = '1.1.1-SNAPSHOT'
description = 'jia-mapper-common'
问题发现
配置完之后,项目能跑起来了,终于可以进行统一版本管理,不用每个模块单独去升级依赖。接着就是要将 jia-core 模块发布到maven私服上了,用的是阿里的私仓, RELEASE 仓和 SNAPSHOT 仓是分开的。这时候问题出现了,我当前版本是 1.1.1-SNAPSHOT ,应该上传到 SNAPSHOT 才对,但却上传到 RELEASE 仓去了。
那肯定是 url 不对,只能调试一下,所以加打印了一下url。
repositories {
maven {
println version
url = version.endsWith('SNAPSHOT') ? rootProject.ext.snapshotsRepoUrl : rootProject.ext.snapshotsRepoUrl
credentials {
username rootProject.ext.repoUsername
password rootProject.ext.repoPassword
}
}
}
发现输出的却是unspecified
,明明 jia-core 项目的 build.gradle 中已经定义了 version ,但为什么就是识别不了。
问题解决
又是一轮各种尝试, Gradle 的指导文档真的很少,真心不想把 Gradle 官网翻一遍。
我分别在父项目的 allprojects 、 subprojects 、 ext 和子项目的 allprojects 、 subprojects 、 ext 中都加了定义了 version 。发现在父项目中定义的 version 都能识别到,而在子项目中定义的 version 都识别不到。
然后无意中看到一个贴子,说 Gradle 的加载顺序依次是父项目的 setting.gradle -> 父项目的 build.gradle -> 子项目的 build.gradle 。而 subprojects 是写在父项目的 build.gradle 上的,加载的时候还没加载子项目的 build.gradle ,自然是获取不了子项目的 version 。
其实官网也是有介绍的,只是英文实在不行,不容易理解。
https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:deferred_configuration
既然知道原因,那就好办了,只要把 publishing 方法用 afterEvaluate 包起来即可,目的是加载完所有配置文件再加载 publishing 方法,自然就能获取得到 version 了。
allprojects {
group = 'cn.jia'
}
subprojects {
apply plugin: 'java-library'
apply plugin: 'maven-publish'
dependencies {
implementation libs.slf4j.api
annotationProcessor libs.lombok
compileOnly libs.lombok
}
java.sourceCompatibility = JavaVersion.VERSION_17
tasks.withType(JavaCompile).tap {
configureEach {
options.encoding = 'UTF-8'
}
}
test {
useJUnitPlatform()
}
processTestResources.dependsOn copyTestResources
afterEvaluate {
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
repositories {
maven {
url = version.endsWith('SNAPSHOT') ? rootProject.ext.snapshotsRepoUrl : rootProject.ext.snapshotsRepoUrl
credentials {
username rootProject.ext.repoUsername
password rootProject.ext.repoPassword
}
}
}
}
}
}