【问题标题】:My gradle configuration does not use the correct classpath during build我的 gradle 配置在构建期间未使用正确的类路径
【发布时间】:2011-08-26 18:17:47
【问题描述】:

我有一个多项目设置(ProjectB -> ProjectA),我正在使用 flatDir 在每个项目中指定一个 lib 目录。

项目A:

repositories {
    flatDir name: 'localRepository', dirs: 'lib'
}

dependencies {
    compile group: 'com.google.guava', name: 'guava', version: 'r08'
    compile group: 'com.miglayout', name: 'miglayout', version: '3.7.4'
    testCompile group: 'junit', name: 'junit', version: '4.+'
    testCompile group: 'org.easymock', name: 'easymock', version: '2.5.2'
}

项目B:

repositories {
    flatDir name: 'localRepository', dirs: 'lib'
}

dependencies {
    compile group: 'yan', name: 'yan', version: '5.0.2'
    runtime group: 'yan', name: 'jfunutil', version: '5.0.2'
    compile project(':ProjectA')
    testCompile group: 'junit', name: 'junit', version: '4.+'
    testCompile group: 'org.easymock', name: 'easymock', version: '2.5.2'

}

当我对 ProjectB 使用 gradle dependencies 时,会生成正确的依赖关系列表,显示来自 ProjectA 的传递依赖关系(例如,包括 guava-r08)。但是我gradle build的时候,实际用于javac的classpath只包含了ProjectB的直接依赖,以及构建ProjectA生成的jar。

另一个烦恼似乎是 testCompile,我必须重新声明 ProjectB 对 junit 的依赖,否则 gradle dependencies 将不会成功。

非常感谢任何指针 - 我是 Gradle 新手。

【问题讨论】:

    标签: build classpath gradle


    【解决方案1】:

    关于您的项目结构...

    使用单个 lib 文件夹而不是为每个项目创建一个似乎是一个更好的主意。

    你的目录结构是这样的:

    project/settings.gradle
    project/ProjectA/lib
    project/ProjectA/src
    project/ProjectB/lib
    project/ProjectB/src
    

    您想为每个子项目创建一个 lib 文件夹有什么特别的原因吗?这似乎是一个更好的主意:

    project/settings.gradle
    project/lib
    project/ProjectA/src
    project/ProjectB/src
    

    您可以在项目的根目录 (project/build.gradle) 中创建一个 build.gradle,其中包含以下内容:

    subprojects{
       apply plugin: 'java'
       repositories {
            flatDir name: 'localRepository', dirs: "$rootProject.projectDir/lib"
       }
    }
    

    这样您就可以将所有依赖项放到项目/lib 中。

    关于您的测试依赖...

    您也可以将您的 testCompile 依赖项放入此根 build.gradle 文件中。它变成:

    subprojects{
       apply plugin: 'java'
       repositories {
            flatDir name: 'localRepository', dirs: "$rootProject.projectDir/lib"
       }
       dependencies{
            testCompile group: 'junit', name: 'junit', version: '4.+'
            testCompile group: 'org.easymock', name: 'easymock', version: '2.5.2'
       }
    }
    

    这样您就不必在每个子项目的 build.gradle 文件中指定 testCompile 依赖项。

    但是,当我 gradle build 时, 仅用于 javac 的实际类路径 包括直接依赖 ProjectB,以及生成的jar 正在建设 ProjectA。

    为了编译ProjectB,你只需要ProjectA。只有 ProjectA 是您的编译依赖项; ProjectA的编译依赖变成了ProjectB的传递依赖。

    【讨论】:

    • 感谢您的建议,但也许我把事情简化了太多。这个想法是 ProjectA 是一个通用库。它包含我的常用实用程序等,我还有 3 个其他项目(应用程序)依赖于 ProjectA。 ProjectA应该完全独立于其他项目,另外每个项目(项目B,C,D)彼此独立。这就是为什么我不太热衷于全局 lib 理念以及分层项目结构的原因。 (不过,我并没有完全拒绝 - 所以感谢您的努力!)
    【解决方案2】:

    我同意前面的回答。经过多次尝试,我们有相同的结构

    > shared
     - build.gradle
     - gradle.properties
     - settings.gradle
    > project-a 
     - gradle.properties
     - settings.gradle
    > project-b 
     - gradle.properties
     - settings.gradle
    

    Shared 包含所有通用代码,在我们的例子中,它处理签入、模块部署、代码质量 (cobertura)、编译等 Shared 还定义了由子项目继承的类路径,然后可以添加其他依赖项。

    对于您的问题:

    您是否在项目 A 中定义了以下内容?

    settings.gradle includeFlat('Project B')

    您是否在项目 B 中定义了以下内容?

    settings.gradle includeFlat('Project A')

    【讨论】:

    • 这看起来与之前的答案略有不同:在之前的答案中,似乎共享 lib 文件夹是在根项目中定义的,而 ProjectA 和 ProjectB 是根的子项目。在您的情况下,它看起来 shared 是 project-a 和 project-b 的兄弟。我更喜欢这种扁平的层次结构。考虑一下我是否有 shared-a 和 shared-b(两个独立的核心项目,可供应用级项目使用。您的解决方案是否支持这种结构?谢谢!
    • 是的,这就是我们使用它的方式,如果您愿意,我会发布更多详细信息,但我想您现在可能已经弄清楚了。我只是做了一个非常简单的项目并让结构正常工作,然后我添加了所有真实的代码。我发现 Gradle 的问题是文档不够成熟,你永远不知道哪种方式是最好的。我希望这不是一个因学习资源贫乏而消失的项目。..
    • 谢谢,但仍然卡住:我已经尝试过项目 B:includeFlat('Project A')。因为 B 依赖于 A,所以我不希望对 A 使用 includeFlat('Project B') (A 不应该对 B 有任何了解)。在 B 上执行 gradle build 时,我的构建现在失败 - gradle 确定它必须首先构建 A(是),但随后尝试解决 A 对 B 的 lib 文件夹的 jar 依赖项(否!),因此它没有找到任何 jar 并且项目 A 获胜不编译。这令人沮丧,因为看起来你的结构正是我所追求的 - 谢谢!
    • 好的,所以我认为缺少的部分是 project_a 需要了解 project_b,至少有一个参考。当我在 project_b 中运行编译时,我从 project_a 运行它,例如“gradle project_b:compile
    【解决方案3】:

    您原始帖子中的构建脚本很好。传递依赖解析不起作用的原因是项目只会使用自己的存储库来解析其配置。因此,解决问题的一种方法是只有一个 lib 目录。另一种解决方案是为 B 声明一个指向 A 的 lib 目录的第二个存储库。

    另一个烦恼似乎是 testCompile,我必须重新声明 ProjectB 对 junit 的依赖,否则 gradle 依赖将不会成功。

    不确定您在这里说什么,但这可能是我上面解释的结果。也许以下信息也有帮助:依赖于项目不会引入其testCompile/testRuntime 依赖项。预计您必须为每个需要它的项目声明 JUnit。为避免重复,您可以使用configuration injection 来声明您的项目之间的共性。以前的答案已经给出了具体的例子(例如subprojects { ... })。

    【讨论】:

      猜你喜欢
      • 2015-06-05
      • 2020-04-04
      • 2016-05-10
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 2020-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多