根据平台切换Gradle中的依赖项

时间:2016-11-10 17:16:13

标签: java gradle

我正在尝试让Gradle在我的多项目构建中根据我是为桌面还是为Android构建来选择不同的依赖项。我有一个共同的子项目(库),我试图重用。但是,我无法让Gradle正确切换依赖配置。

我的主settings.gradle只包含所有依赖项:

// /settings.gradle
rootProject.name = 'myProject'

include 'androidUI'
include 'reusableLibrary'
include 'desktopUI'

现在,androidUIdesktopUI都将reusableLibrary指定为依赖项:

// /androidUI/build.gradle and /desktopUI/build.gradle
apply plugin: 'java'
dependencies {
    compile project(path: ':reusableLibrary', configuration: 'desktop')
}

reusableLibrary本身指定了两种配置,因为它的依赖关系是不同的,无论它是建立在桌面还是Android上:

// /reusableLibrary/build.gradle
apply plugin: 'java'
configurations {
    desktop {
        extendsFrom compile
    }
    android {
        extendsFrom compile
    }
}

dependencies {
    // Just examples, the real list is longer.
    // The point is that h2database is only included on desktop,
    // and ormlite is only included on Android.
    android 'com.j256.ormlite:ormlite-jdbc:5.0'
    desktop 'com.h2database:h2:1.4.192'
}

这个看起来对我来说很好。但是当我编译desktopUIandroidUI时,我可以看到尽管reusableLibrary依赖以我想要的方式包含在类路径中,由reusableLibrary本身提供的实际JAR 包含。这当然会导致构建失败。我怀疑我没有正确设置reusableLibrary;我不清楚configurations {}块做了什么。

为什么reusableLibrary中的编译项目不包含在UI项目的类路径中?以这种方式包含特定于平台的依赖项的规范方法是什么?

1 个答案:

答案 0 :(得分:1)

原始配置非常接近正确。关键是要从Gradle Java plugin's documentation

了解这种依赖图

Java dependency configurations

这是Java插件的各种依赖关系配置的可视化,这是Gradle-ese的"依赖关系列表。"当您向compile块添加dependencies {...}行时,您需要将Dependency元素添加到compile依赖关系列表中。

default依赖关系配置很特殊;它是compile project("path")行所包含的行,除非使用configuration:参数选择不同的行。这意味着在构建库时,runtime依赖关系列表(包含库本身的已编译jar )将添加到客户端项目的类路径中。

原始配置在此图表中创建了两个新节点desktopandroid,并使用compile将它们耦合到extendsFrom。它们没有以其他方式连接到图表!现在原始配置的问题是显而易见的:通过将上游项目切换到其中任何一个,它缺少来自runtime的编译代码。这解释了类路径遗漏。

解决方案比在desktop瞄准androidruntime更加微妙。为了确保在添加测试时所有内容都正确解耦,我们需要一个额外的依赖关系配置层,以使testCompile间接依赖于runtime。另外,库的源代码本身可能需要在类路径上进行类型检查;我们可以使用compileOnly。最终解决方案如下所示:

configurations {
    desktopCompile
    androidCompile

    compileOnly.extendsFrom desktopCompile
    testCompile.extendsFrom desktopCompile // Assuming tests run on the desktop

    desktop {
        extendsFrom desktopCompile
        extendsFrom runtime
    }
    android {
        extendsFrom androidCompile
        extendsFrom runtime
    }
}

dependencies {
    androidCompile "some.android:dependency"
    desktopCompile "other.desktop:dependency"
}