自定义Gradle配置与SourceSet下Module-Info依赖无法解析问题
当使用自定义配置driver和自定义sourceSetdriver执行Gradle同步/编译/构建时,module-info.java中的requires org.postgresql.jdbc;无法解析。
自定义配置的build.gradle
plugins { id 'java-library' //用于创建分离API和实现的Java库 } configurations{ driver } dependencies { driver group: 'org.postgresql', name: 'postgresql', version: '42.6.0' } sourceSets{ driver{ java{ srcDirs = ['src'] } } } compileJava.dependsOn(compileDriverJava)
module-info.java
module database.driver { requires java.base; // 核心依赖(内部) requires java.sql; // SQL模块(外部)依赖 requires org.postgresql.jdbc; // PostgreSQL驱动(内部)依赖 }
而使用默认的implementation配置和main sourceSet时,依赖可正常解析且构建无问题:
默认配置的build.gradle
plugins { id 'java-library' //用于创建分离API和实现的Java库 } dependencies { implementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0' } sourceSets{ main{ java{ srcDirs = ['src'] } } } compileJava.dependsOn(compileDriverJava)
自定义配置的依赖为何对module-info.java不可见?是否因未使用main sourceSet导致?
- 执行
./gradlew dependencies显示自定义配置driver的依赖已解析; compileJava本身无源码集,依赖于compileDriverJava;- PostgreSQL驱动为自动模块,Manifest中包含
Automatic-Module-Name: org.postgresql.jdbc; - 附
./gradlew dependencies输出结果:
> Task :dependencies ------------------------------------------------------------ Root project 'database.driver' ------------------------------------------------------------ annotationProcessor - 源码集'main'的注解处理器及其依赖。 无依赖 api - 源码集'main'的API依赖。(n) 无依赖 apiElements - main的API元素。(n) 无依赖 compileClasspath - 源码集'main'的编译类路径。 无依赖 compileOnly - 源码集'main'的仅编译依赖。(n) 无依赖 compileOnlyApi - 源码集'main'的仅编译API依赖。(n) 无依赖 default - 默认产物的配置。(n) 无依赖 driver \--- org.postgresql:postgresql:42.6.0 \--- org.checkerframework:checker-qual:3.31.0 driverAnnotationProcessor - 源码集'driver'的注解处理器及其依赖。 无依赖 driverCompileClasspath - 源码集'driver'的编译类路径。 无依赖 driverCompileOnly - 源码集'driver'的仅编译依赖。(n) 无依赖 driverImplementation - 源码集'driver'的仅实现依赖。(n) 无依赖 driverRuntimeClasspath - 源码集'driver'的运行时类路径。 无依赖 driverRuntimeOnly - 源码集'driver'的仅运行时依赖。(n) 无依赖 implementation - 源码集'main'的仅实现依赖。(n) 无依赖 mainSourceElements - 主源码集包含的源码目录列表。(n) 无依赖 runtimeClasspath - 源码集'main'的运行时类路径。 无依赖 runtimeElements - main的运行时元素。(n) 无依赖 runtimeOnly - 源码集'main'的仅运行时依赖。(n) 无依赖 testAnnotationProcessor - 源码集'test'的注解处理器及其依赖。 无依赖 testCompileClasspath - 源码集'test'的编译类路径。 无依赖 testCompileOnly - 源码集'test'的仅编译依赖。(n) 无依赖 testImplementation - 源码集'test'的仅实现依赖。(n) 无依赖 testResultsElementsForTest - 包含测试套件测试目标运行测试二进制结果的目录。(n) 无依赖 testRuntimeClasspath - 源码集'test'的运行时类路径。 无依赖 testRuntimeOnly - 源码集'test'的仅运行时依赖。(n) 无依赖
核心原因
自定义配置driver没关联到driver源码集的编译类路径里。Gradle的源码集默认会用对应命名的xxxImplementation、xxxCompileOnly这类自动生成的配置来构建编译/运行时类路径,你手动创建的driver配置不属于这个范畴,所以不会被加入到driverCompileClasspath,导致编译module-info.java时找不到模块依赖。
另外,你让compileJava依赖compileDriverJava,但compileJava对应的main源码集本身没任何依赖,driver源码集的编译类路径也没包含PostgreSQL驱动,自然解析失败。
解决方法
有两种可行的修改方式:
方式一:用Gradle为自定义源码集生成的默认配置
Gradle创建自定义源码集driver时,会自动生成driverImplementation、driverCompileOnly等配置,直接用这些配置加依赖就行,不用手动建driver配置:
plugins { id 'java-library' } sourceSets{ driver{ java{ srcDirs = ['src'] } } } dependencies { // 使用自动生成的driverImplementation配置 driverImplementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0' } compileJava.dependsOn(compileDriverJava)
这样Gradle会自动把driverImplementation的依赖加入driverCompileClasspath和driverRuntimeClasspath,编译时就能正常解析module-info.java里的requires声明。
方式二:手动把自定义配置关联到源码集的编译类路径
如果一定要保留手动创建的driver配置,需要把它添加到driver源码集的编译类路径中:
plugins { id 'java-library' } configurations{ driver } sourceSets{ driver{ java{ srcDirs = ['src'] } // 将自定义driver配置加入到编译类路径 compileClasspath += configurations.driver // 若需要运行时也可用,同时加入运行时类路径 runtimeClasspath += configurations.driver } } dependencies { driver group: 'org.postgresql', name: 'postgresql', version: '42.6.0' } compileJava.dependsOn(compileDriverJava)
验证
修改后执行./gradlew dependencies,查看driverCompileClasspath会发现已经包含PostgreSQL驱动依赖,此时重新同步/编译就能正常解析module-info.java中的模块声明了。
内容的提问来源于stack exchange,提问作者mahee96

