将所有依赖项从一个Gradle模块导入到另一个模块

将所有依赖项从一个Gradle模块导入到另一个模块,gradle,android-gradle-plugin,Gradle,Android Gradle Plugin,我的构建中有两个模块,一个Android应用程序和一个Java库。(旁白是,Java库将针对Android应用程序中的类运行jvm测试。因为它需要Gradle Java插件,而这与Gradle Android插件不兼容,所以我不得不将它们分开。) 在java模块中,我希望自动导入其他模块的所有依赖项,以避免它们保持同步 如何配置一个模块的compileTest依赖项以匹配另一个模块compile依赖项 (欢迎使用这两个插件的备选建议。)如果您编写以下代码,您将在模块2中获得模块1的编译依赖项,即

我的构建中有两个模块,一个Android应用程序和一个Java库。(旁白是,Java库将针对Android应用程序中的类运行jvm测试。因为它需要Gradle Java插件,而这与Gradle Android插件不兼容,所以我不得不将它们分开。)

在java模块中,我希望自动导入其他模块的所有依赖项,以避免它们保持同步

如何配置一个模块的
compileTest
依赖项以匹配另一个模块
compile
依赖项


(欢迎使用这两个插件的备选建议。)

如果您编写以下代码,您将在模块2中获得模块1的
编译
依赖项,即模块2中的
测试编译
依赖项:

dependencies { 
    testCompile project(':module1') 
}
在module2的
build.gradle
文件中。正如您自己在评论中所说,如果模块2中没有应用android插件,那么模块1中应用的android插件将不会产生依赖关系

编辑:添加了以下关于如何在单独脚本中定义依赖项的描述

如注释中所述,另一种方法是在定义每个第三方依赖关系的单独脚本中添加属性。我倾向于在我参与的每个多项目构建中都这样做。事实上,由于我已经习惯了
dependencies.gradle
文件的存在,我实际上也在单个项目构建中这样做

这个想法很简单:

  • 添加一个单独的脚本,其中包含定义第三方依赖关系的属性
  • 在每个模块中应用此脚本
  • 使用属性,而不是到处重复硬编码
通过这种方式,您可以在一个位置定义所有依赖项,从而提高依赖项定义的可读性,并且您的模块永远不会彼此“不同步”(例如,两个模块取决于同一库的不同版本)。另外一个好处是,您可以将属于同一个属性的多个依赖项组合在一起

示例:

假设我们有问题中描述的两个模块。模块1使用一些第三方库。模块2应该测试模块1,除了它自己的一些库之外,还需要模块1中定义的每个库

依赖项。渐变

ext {
    JAVAX_MAIL = 'javax.mail:mail:1.4.5'
    JODA_TIME = 'joda-time:joda-time:2.1'
    LOG4J = 'log4j:log4j:1.2.16'
    SPOCK = [
            'org.spockframework:spock-core:0.7-groovy-2.0',
            'org.objenesis:objenesis:1.2',
            'cglib:cglib-nodep:2.2.2'
    ]

    // Note: I don't usually combine dep's like this, it's just for illustration.
    //       I prefer to spell them out to make it more explicit.
    MODULE_1_DEPS = [ JAVAX_MAIL, LOG4J ]
}
apply from: "$rootDir/dependencies.gradle"

dependencies {
    compile MODULE_1_DEPS
}
apply from: "$rootDir/dependencies.gradle"

dependencies {
    compile JODA_TIME, LOG4J
    testCompile MODULE_1_DEPS, SPOCK
}
模块1/build.gradle

ext {
    JAVAX_MAIL = 'javax.mail:mail:1.4.5'
    JODA_TIME = 'joda-time:joda-time:2.1'
    LOG4J = 'log4j:log4j:1.2.16'
    SPOCK = [
            'org.spockframework:spock-core:0.7-groovy-2.0',
            'org.objenesis:objenesis:1.2',
            'cglib:cglib-nodep:2.2.2'
    ]

    // Note: I don't usually combine dep's like this, it's just for illustration.
    //       I prefer to spell them out to make it more explicit.
    MODULE_1_DEPS = [ JAVAX_MAIL, LOG4J ]
}
apply from: "$rootDir/dependencies.gradle"

dependencies {
    compile MODULE_1_DEPS
}
apply from: "$rootDir/dependencies.gradle"

dependencies {
    compile JODA_TIME, LOG4J
    testCompile MODULE_1_DEPS, SPOCK
}
模块2/build.gradle

ext {
    JAVAX_MAIL = 'javax.mail:mail:1.4.5'
    JODA_TIME = 'joda-time:joda-time:2.1'
    LOG4J = 'log4j:log4j:1.2.16'
    SPOCK = [
            'org.spockframework:spock-core:0.7-groovy-2.0',
            'org.objenesis:objenesis:1.2',
            'cglib:cglib-nodep:2.2.2'
    ]

    // Note: I don't usually combine dep's like this, it's just for illustration.
    //       I prefer to spell them out to make it more explicit.
    MODULE_1_DEPS = [ JAVAX_MAIL, LOG4J ]
}
apply from: "$rootDir/dependencies.gradle"

dependencies {
    compile MODULE_1_DEPS
}
apply from: "$rootDir/dependencies.gradle"

dependencies {
    compile JODA_TIME, LOG4J
    testCompile MODULE_1_DEPS, SPOCK
}
注意:如果将属性“组合”到列表中,则可能需要展平列表。例如:
MY_DEP=[DEP1,DEP2].flatte()
。也许gradle是为你做的,我真的不知道——我还没有测试过


另外请注意:这里的示例只是说明如何实现您想要的,它们在任何方面都不完整。

如果您只是在模块2中的
build.gradle
文件中编写
dependencies{testCompile project(':module1')}
,那么您不从模块1获得依赖项吗?哦,这确实有效。起初我很困惑,因为当我尝试这样做时,它缺少了很多Android依赖项。但是看起来这些依赖项没有被列为依赖项,因为Android项目应用了Android插件,因此我不得不在第二个模块中手动添加。但是列出的依赖项确实会被导入。如果你加上这一点作为答案,我会接受的。有趣的是,它引入了声明的依赖项,而不是可传递的依赖项,即使主模块与可传递的依赖项一起编译得很好。这令人惊讶,而且可能会成为一个问题。在多项目构建中,我倾向于创建一个依赖项定义为属性的
dependencies.gradle
文件。这样,我可以得到更可读的依赖项定义,并将所有依赖项定义保存在一个地方。这些属性甚至可以包含多个依赖项(如列表),因此,如果这样做有意义的话,您可以将所有需要的依赖项组合成一个,我想在您的案例中就是这样。如果你愿意的话,我可以编辑我的答案,包括一个这样的例子。我很感激,从维护的角度来看,这听起来很不错。