在module-info.javabuild.gradle中使用自定义配置时,未解决依赖关系(www.example.com中的“requires”)

vmdwslir  于 2023-04-12  发布在  Java
关注(0)|答案(1)|浏览(157)

对于下面的代码段,“需要org.postgresql.jdbc;“在尝试执行Gradle-sync/assemble/build并使用自定义配置'driver'和自定义sourceSet 'driver'时无法解析。

  • 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)

为什么自定义配置依赖项对于www.example.com不可见module-info.java,这是否是由于未使用sourceSet 'main'的原因?

注意:在sourceSets和dependencies任务中使用自定义配置'driver'时,运行./gradlew dependencies时,会打印出依赖关系已解决。
注意:compileJava本身不做任何事情,也没有任何sourceSet可以使用,因此不需要任何依赖关系。但它依赖于自定义配置编译'compileDriverJava'
注意:postgres manifest包含Automatic-module-name,表示它是一个自动模块

Manifest-Version: 1.0
Automatic-Module-Name: org.postgresql.jdbc

使用自定义配置“driver”时“./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
kb5ga3dv

kb5ga3dv1#

OK找到问题了,似乎gradle解析器关心令牌声明的顺序,
问题是,sourceSets是在dependencies块之后声明的,当dependencies块被解决时,除了隐式配置default之外,只有一个名为driver的配置可用
因此,我能够使用driver group: 'org.postgresql', name: 'postgresql', version: '42.6.0',并且它可以工作,因为它将依赖项与自定义配置本身相关联。
但是它没有看到有一个自定义的sourceSet driver,它的依赖关系是由driverImplementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0'指定的,我在这里发布之前已经尝试过了。
所以 * 将sourceSets声明移到依赖项之上 使用 * driverImplementation * 而不是 * driver * 解决了这个问题。*

注意:我已经将自定义sourceSet driver重命名为foo,以检查它是否与自定义配置有任何链接,答案是它没有。所以基本上,如果我在添加sourceSets { foo }后将dependencies块中的语句重命名为fooImplementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0',那么gradle就可以将依赖关系正确Map到自定义sourceSet foo

我不确定gradle用户手册是否包含了从新的用户Angular 来看的这些细节/澄清。

**注意:**虽然我的gradle问题已经解决了,但它并没有完全解决,因为我正在使用IntelliJ IDE,它仍然无法看到/识别自定义SourceSet中的依赖项,并在www.example.com中显示错误module-info.java,但gradle编译即使在IDE中也能正常工作。

在dependencies块中使用implementation group: 'org.postgresql', name: 'postgresql', version: '42.6.0'main sourceSet设置依赖关系时,IDE可以看到依赖关系,并且不会直观地产生错误。
另一种解决方法是implementation配置使用implementation.extendsFrom(driver)从这个自定义配置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            
}

案例二:

// 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
}

案例三:

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
}

相关问题