如何在纯Java Gradle模块中模拟Android的productFlavors?

6

我需要三种不同的版本:

  • fake
  • staging
  • prod

fake 版本将提供类似于 FakeUser, FakeUserDb 的类 - 非常重要的是这些类不应该被编译进 prod 版本。

prodstaging 版本完全相同,除了我需要在 prodstaging 版本中编译不同的 String url

因此,我需要创建一个“抽象”的 real 版本,让 prodstaging 版本都继承它。

这可以很容易地使用 Android Gradle 插件完成,但我如何在纯 Java Gradle 模块中实现它呢?


你确定这些不能是构建类型吗?据我所知,构建类型是 Gradle 的一种东西,Android Gradle 插件正好利用了它。 - CommonsWare
哦,它们肯定可以成为buildTypes。在Android插件术语中,我只需要stagingDebug、prodRelease和fakeDebug。 - ZakTaccardi
@CommonsWare,buildType 是 Gradle 的概念,不仅仅是 Android 插件的概念吗?是否有关于纯 Java 的文档?每次谷歌搜索似乎都会导向 Android 插件。 - ZakTaccardi
@CommonsWare,似乎有传言说gradle支持在android插件之外使用这些东西,但是没有真正的文档说明。 - ZakTaccardi
也许这就是它?https://docs.gradle.org/current/userguide/java_software.html - ZakTaccardi
显示剩余2条评论
2个回答

6
对于每种风味,您需要:
  1. 创建一个 SourceSet 以便进行编译
  2. 使 $ {flavour} Compile 配置 扩展主编译配置(有关java插件创建的每个SourceSet的配置,请参见表45.6 此处
  3. 创建一个 JarTask (使用风味作为分类器)
  4. 发布jar工件,以便通过分类器引用该风味
类似这样:
def flavours = ['fake', 'staging', 'prod']
flavours.each { String flavour ->
    SourceSet sourceSet = sourceSets.create(flavour)
    sourceSet.java {
       srcDirs 'src/main/java', "src/$flavour/java"
    }
    sourceSet.resources {
       srcDirs 'src/main/resources', "src/$flavour/resources"
    }
    Task jarTask = tasks.create(name: "${flavour}Jar", type: Jar) {
       from sourceSet.output
       classifier flavour
    }
    configurations.getByName("${flavour}Compile").extendsFrom configurations.compile
    configurations.getByName("${flavour}CompileOnly").extendsFrom configurations.compileOnly
    configurations.getByName("${flavour}CompileClasspath").extendsFrom configurations.compileClasspath
    configurations.getByName("${flavour}Runtime").extendsFrom configurations.runtime

    artifacts {
       archives jarTask
    }
    assemble.dependsOn jarTask
}

然后,要在另一个项目中引用其中一种口味,您可以执行以下操作之一:

dependencies {
   compile project(path: ':someProject', configuration: 'fakeCompile')
   compile project(path: ':someProject', configuration: 'fakeRuntime')
   compile 'someGroup:someProject:1.0:fake'
   compile group: 'someGroup', name: 'someProject', version: '1.0', classifier: 'fake'
}

虽然这很有帮助,但这只涉及到sourceSets。它没有涉及配置,并且使某些Gradle模块依赖于另一个模块的配置。 - ZakTaccardi
1
太好了,谢谢!那么如何使用这些jar构件呢?比如说,如果你从一个兄弟Gradle模块中使用该jar,会怎样呢? - ZakTaccardi
稍作调整以创建每种风味的配置,并添加示例引用。 - lance-java
谢谢!这个工作得很好,除了我的fake/prod/staging配置无法访问我在依赖块中声明的任何第三方库。也就是说,main可以访问dependencies { compile "io.reactivex:rxjava:$rxJavaVersion" },但是fakestagingprod没有将rxjava编译到其类路径中。你该如何解决这个问题? - ZakTaccardi
谢谢,但不幸的是,仍然会抛出相同的错误。通过在以下要点中手动添加配置块,我修复了这些错误,并且:server:fakeClasses编译成功,但我更喜欢一种不那么手动的方法。https://gist.github.com/ZakTaccardi/af96c5bbed048b9465c5fa3db19cfe0b - ZakTaccardi
显示剩余13条评论

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接