简体   繁体   English

为每种应用程序风格创建多个shadowJars

[英]Create multiple shadowJars for each flavor of application

I'm experimenting with gradle and trying to setup a system that builds different flavors (brands) of an application, which differ by configuration mainly. 我正在尝试使用gradle并尝试设置一个系统来构建应用程序的不同风格(品牌),这些系统主要因配置而异。 What I have so far are two versions of the build scripts - both not working. 到目前为止我所拥有的是两个版本的构建脚本 - 两者都不起作用。

Version 1 版本1
First flavor specific resource folder flavor-res is added to sourcesets , which achieves overwriting some default resources. 第一个特定于flavor的资源文件夹flavor-res被添加到sourcesets ,从而覆盖了一些默认资源。 A task rule defines tasks for each flavor, which should (ideally) trigger build of the whole jar. 任务规则定义每种风味的任务,这应该(理想情况下)触发整个jar的构建。

This works fine and generates the required jar, for one flavor at a time, like 这样可以正常工作并生成所需的罐子,一次一种口味,就像

gradle clean flavorOne 

but the shadowJar task runs only once, if I do 但是如果我这样做, shadowJar任务只运行一次

gradle clean flavorOne flavorTwo

Stripped down Script: 剥离脚本:

sourceSets {
    main {
        ...
        resources {
            srcDirs = ['src/main/resources', "${project.buildDir}/flavor-res/"]
        }
    }
}

shadowJar { classifier = 'SNAPSHOT' }

tasks.addRule("Pattern: flavor<Name>") { String taskName ->
if (taskName.startsWith("flavor")) {

    String flavorName = (taskName - "flavor")
    String flavorOutDir = "${project.buildDir}/${flavorName}"

    // Set output folder and jar name 
    task("${taskName}Configure") {
        outputs.dir(flavorOutDir)

        doFirst {
            archivesBaseName = flavorName
            project.buildDir = flavorOutDir
        }
    }

    // Copy res to folder used in sourcesets
    task("${taskName}CopyResources") {
        mustRunAfter = ["${taskName}Configure"]
        outputs.dir("${project.buildDir}/flavor-res")

        doFirst {
            copy {
                from "flavors/${flavorName}/"
                into "${project.buildDir}/flavor-res/"
            }
        }
    }

    shadowJar.mustRunAfter = ["${taskName}Configure", "${taskName}CopyResources"]

    // Define task that depends on shadowJar
    task(taskName, dependsOn: ["${taskName}Configure", "${taskName}CopyResources", 
         shadowJar]) {
        println "Configuring ${taskName}"
    }

}

Sensing that it probably doesnt work because the change detection somehow doesnt work, I tried an alternative approach. 感觉它可能不起作用,因为变化检测在某种程度上不起作用,我尝试了另一种方法。 Here is a simplified version of script 这是脚本的简化版本

Version 2 版本2

Modified the rule to define a shadowJar dynamic task for each flavor. 修改了规则,为每个flavor定义shadowJar动态任务。

/* Removed sourceSets in this version */

shadowJar { classifier = 'SNAPSHOT' }

tasks.addRule("Pattern: flavor<Name>") { String taskName ->
if (taskName.startsWith("flavor")) {

    String flavorName = (taskName - "flavor")
    String flavorOutDir = "${project.buildDir}/${flavorName}"

    // Set resources for main sourceset
    task("${taskName}Configure") {
        outputs.dir(flavorOutDir)

        doFirst {
            archivesBaseName = flavorName
            sourceSets.main.resources.srcDirs = ['src/main/resources', "${flavorOutDir}/flavor-res"]
            project.buildDir = flavorOutDir
        }
    }

    task("${taskName}CopyResources") {
        outputs.dir("${flavorOutDir}/flavor-res")
        dependsOn "${taskName}Configure"

        doFirst {
            copy {
                from "flavors/${flavorName}/"
                into "${project.buildDir}/flavor-res/"
            }
        }
    }

    // This should shadowJar for each flavor - but generate jars dont have the required artifacts.
    task ("${taskName}Build", type: ShadowJar) {

        from sourceSets.main.output
        configurations = [ configurations.runtime ] 
        classifier = 'SNAPSHOT'

        dependsOn "${taskName}CopyResources"
    }

    task(taskName, dependsOn: ["${taskName}Build"]) {
    }
}
 }

However, now, the generated jars are malformed. 但是,现在,生成的罐子格式不正确。 The first flavor gets just the artifacts for main, but no showed jars. 第一种味道只是主要的文物,但没有展示罐子。 The second jar has just the manifest and nothing else. 第二个罐子只有清单而没有其他东西。

What would be the correct way of achieving that. 实现这一目标的正确方法是什么?

PS: No, its not an android application (flavor is just a synonym for a brand). PS:不,它不是一个Android应用程序(味道只是一个品牌的同义词)。

I decided to recreate a flavor build script, because it can be simplified to what you have now. 我决定重新创建一个flavor构建脚本,因为它可以简化为现在的样式。 The ShadowJar task can handle copying all the classes and resources by itself, there is no need to define separate ones. ShadowJar任务可以自己处理复制所有类和资源,不需要定义单独的类和资源。 I also took some default configuration that would have been applied to the shadowJar task and applied this to the custom ShadowJar tasks to get the same behavior. 我还采用了一些应用于shadowJar任务的默认配置,并将其应用于自定义ShadowJar任务以获得相同的行为。

I first build a quick test project structure which can be found here: Test Structure 我首先构建一个快速测试项目结构,可以在这里找到: 测试结构

Then I came up with the following script: 然后我想出了以下脚本:


    import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

    plugins {
        id 'java'
        id "com.github.johnrengelman.shadow" version "2.0.4"
    }

    group 'your-group'
    version 'dev-SNAPSHOT'

    sourceCompatibility = 1.8

    repositories {
        mavenCentral()
    }

    dependencies {
        // Example dependency
        compile group: 'com.google.guava', name: 'guava', version: '19.0'
    }

    tasks.addRule("Pattern: flavor<Name>") { def taskName ->
        if (!taskName.startsWith("flavor")) {
            return
        }

        def flavorName = taskName - "flavor"
        // Define the shadow task
        def shadowTask = task ("${flavorName}ShadowJar", type: ShadowJar) {
            classifier = flavorName
            // Add our flavor resources, first to prioritize these resources
            from file("src/main/flavors/${flavorName}")
            // Include our project classes
            from project.sourceSets.main.output
            // Don't include duplicate resources, only the first ones added, in
            // this case the flavored resources will override the default ones
            duplicatesStrategy = DuplicatesStrategy.EXCLUDE
            // Some defaults taken from the default shadowJar task
            // https://github.com/johnrengelman/shadow/blob/master/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy#L48
            configurations = [ project.configurations.runtime ]
            manifest.inheritFrom project.tasks.jar.manifest
            exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA')
        }

        // Define the flavor task
        task ("${taskName}", dependsOn: shadowTask) {}
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM