对于下面的一段代码,“需要org.postgresql.jdbc;”尝试执行 Gradle-sync/assemble/build 并使用自定义配置“驱动程序”和自定义 sourceSet“驱动程序”时未解决。
build.gradle
plugins {
id 'java-library' //used to create java api and implementation separated libs
}
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; // core dependencies(internal)
requires java.sql; // sql module (externalized) dependencies
requires org.postgresql.jdbc; // postgresql driver (internal) dependencies
}
当使用默认的“实现”配置和默认的“主要”源集时,它已得到解决并且可以正常构建/组装而没有问题。
build.gradle
plugins {
id 'java-library' //used to create java api and implementation separated libs
}
dependencies {
implementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0'
}
sourceSets{
main{
java{ srcDirs = ['src'] }
}
}
compileJava.dependsOn(compileDriverJava)
为什么 module-info.java 的自定义配置依赖不可见,这是因为没有使用 sourceSet 'main' 的原因吗?
注意:在为 sourceSets 和依赖项任务使用自定义配置“驱动程序”时运行 ./gradlew dependencies,打印出依赖项已解决。
注意:compileJava 本身不执行任何操作,也没有任何 sourceSets 可以使用,因此不需要任何依赖项。但这取决于自定义配置编译'compileDriverJava'
注意:postgres 清单包含 Automatic-module-name 以表示它是一个自动模块
Manifest-Version: 1.0
Automatic-Module-Name: org.postgresql.jdbc
使用自定义配置“驱动程序”时“./gradlew dependencies”的输出
> Task :dependencies
------------------------------------------------------------
Root project 'database.driver'
------------------------------------------------------------
annotationProcessor - Annotation processors and their dependencies for source set 'main'.
No dependencies
api - API dependencies for source set 'main'. (n)
No dependencies
apiElements - API elements for main. (n)
No dependencies
compileClasspath - Compile classpath for source set 'main'.
No dependencies
compileOnly - Compile only dependencies for source set 'main'. (n)
No dependencies
compileOnlyApi - Compile only API dependencies for source set 'main'. (n)
No dependencies
default - Configuration for default artifacts. (n)
No dependencies
driver
\--- org.postgresql:postgresql:42.6.0
\--- org.checkerframework:checker-qual:3.31.0
driverAnnotationProcessor - Annotation processors and their dependencies for source set 'driver'.
No dependencies
driverCompileClasspath - Compile classpath for source set 'driver'.
No dependencies
driverCompileOnly - Compile only dependencies for source set 'driver'. (n)
No dependencies
driverImplementation - Implementation only dependencies for source set 'driver'. (n)
No dependencies
driverRuntimeClasspath - Runtime classpath of source set 'driver'.
No dependencies
driverRuntimeOnly - Runtime only dependencies for source set 'driver'. (n)
No dependencies
implementation - Implementation only dependencies for source set 'main'. (n)
No dependencies
mainSourceElements - List of source directories contained in the Main SourceSet. (n)
No dependencies
runtimeClasspath - Runtime classpath of source set 'main'.
No dependencies
runtimeElements - Elements of runtime for main. (n)
No dependencies
runtimeOnly - Runtime only dependencies for source set 'main'. (n)
No dependencies
testAnnotationProcessor - Annotation processors and their dependencies for source set 'test'.
No dependencies
testCompileClasspath - Compile classpath for source set 'test'.
No dependencies
testCompileOnly - Compile only dependencies for source set 'test'. (n)
No dependencies
testImplementation - Implementation only dependencies for source set 'test'. (n)
No dependencies
testResultsElementsForTest - Directory containing binary results of running tests for the test Test Suite's test target. (n)
No dependencies
testRuntimeClasspath - Runtime classpath of source set 'test'.
No dependencies
testRuntimeOnly - Runtime only dependencies for source set 'test'. (n)
No dependencies
好的发现了问题,似乎 gradle 解析器关心令牌声明的顺序,
问题是 sourceSets 在 dependencies 块之后被声明,当 dependencies 块被解析时,除了隐式配置外,只有一个名为
driver
的配置可用 default
所以我能够使用
driver group: 'org.postgresql', name: 'postgresql', version: '42.6.0'
并且它起作用了,因为它将依赖关系与自定义配置本身相关联。
但是没有看到有一个自定义的 sourceSet
driver
,正如@Vampire 所建议的那样,driverImplementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0'
指定了它的依赖项,我在发布到这里之前已经尝试过了。
所以 将 sourceSets 声明移动到 dependencies 之上 和 having
driverImplementation
instead of driver
解决了这个问题。
注意: 我已将自定义 sourceSet
driver
重命名为 foo
以检查它是否与自定义配置有任何互连,答案是没有。
所以基本上,如果我在添加 fooImplementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0'
后将依赖项块中的语句重命名为 sourceSets { foo }
,那么 gradle 能够将依赖项正确映射到 custom sourceSet foo.
我不确定 gradle 用户手册是否从新用户的角度准确地包含了这些细节/说明。
注意:虽然我的 gradle 问题已解决,但由于我正在使用 IntelliJ IDE 并且它仍然没有看到/识别自定义 SourceSet 中的依赖项并在 module-info.java 中显示错误但 gradle即使在 IDE 中编译也能正常工作。
IDE 可以看到依赖关系,并且在依赖关系块中使用
main
为 implementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0'
sourceSet 设置依赖关系时,不会在视觉上产生错误。
另一个解决方法是
implementation
配置从这个自定义配置 driver
使用 implementation.extendsFrom(driver)
扩展,然后只使用 driver group: 'org.postgresql', name: 'postgresql', version: '42.6.0'
以便依赖关系关联到自定义配置驱动程序,因此也隐式关联到实现。
注意: 这样做可以解决 IntelliJ IDE 中的依赖关系,并且 IDE 红色标记已删除。
案例一:
// DOESN'T WORK:
/*
Reasons:
1. sourceSets block declared after dependency block which contains the dependency
2. it will still fail because there is no implementation dependency for the custom sourceSet ie, missing `driverImplementation`
*/
configurations {
driver
}
dependencies {
driver 'org.postgresql:postgresql:42.6.0'
}
sourceSets{
driver{
java{
srcDirs = ['src/main/java']
}
}
}
task compile(){ //GRADLE-ERROR
dependsOn compileJava
dependsOn compileDriverJava
}
案例2:
// DOESN'T WORK:
/*
Reasons:
1. there is no implementation dependency for the custom sourceSet ie, missing `driverImplementation` because dependencies declaration are unique for custom configuration and custom sourceSets.
2. both sourceSets 'main' and 'driver' (custom sourceSet), FAILS
*/
configurations {
driver
}
sourceSets{
driver{
java{
srcDirs = ['src/main/java']
}
}
}
dependencies {
driver 'org.postgresql:postgresql:42.6.0'
}
task compile(){
dependsOn compileJava //FAILS
dependsOn compileDriverJava //FAILS
}
案例3:
PARTIALLY WORKS:
/*
Reasons:
1. there is implementation dependency for the custom sourceSet ie, `driverImplementation` contains required dependency.
NOTE: IDE still doesn't recognize the dependency since it is not on the main sourceSet.
2. hence compileJava for main sourceSet, FAILS.
3. however compileDriverJava for custom sourceSet 'driver', PASSES
*/
configurations {
driver
}
sourceSets{
driver{
java{
srcDirs = ['src/main/java']
}
}
}
dependencies {
driverImplementation 'org.postgresql:postgresql:42.6.0'
}
task compile(){
dependsOn compileJava //FAILS
dependsOn compileDriverJava //PASSES
}
案例4:
PARTIALLY WORKs:
/*
Reasons:
1. though there is NO implementation dependency for the custom sourceSet ie, `driverImplementation`, the main sourceSet indirectly extends the custom configuration's dependency for itself.
2. hence they become available and visible to the main sourceSet and IDE is able to resolve them too.
3. but due to REASON-1 the compilation of custom sourceSet fails ie, task compileDriverJava fails
4. however compileJava from main sourceSet passes and generates class files successfully.
*/
configurations {
driver
implementation.extendsFrom(driver)
}
sourceSets{
driver{
java{
srcDirs = ['src/main/java']
}
}
}
dependencies {
driver 'org.postgresql:postgresql:42.6.0'
}
task compile(){
dependsOn compileJava //PASSES
dependsOn compileDriverJava //FAILS
}
案例5
FULLY WORKs:
/*
Reasons:
1. there is implementation dependency for the custom sourceSet ie, `driverImplementation`.
2. due to REASON-1, compileDriverJava, PASSES
3. the implementation configuration extends from custom configuration driver inheriting all its dependencies.
4. due to REASON-3, compileJava, PASSES.
*/
configurations {
driver
implementation.extendsFrom(driver)
}
sourceSets{
driver{
java{
srcDirs = ['src/main/java']
}
}
}
dependencies {
driver 'org.postgresql:postgresql:42.6.0'
driverImplementation 'org.postgresql:postgresql:42.6.0'
}
task compile(){
dependsOn compileJava //PASSES
dependsOn compileDriverJava //PASSES
}