【问题标题】:Create multiple shadowJars for each flavor of application为每种应用程序创建多个 shadowJars
【发布时间】:2018-06-22 19:03:00
【问题描述】:

我正在尝试使用 gradle 并尝试设置一个系统来构建应用程序的不同风格(品牌),这些风格主要因配置而异。到目前为止,我有两个版本的构建脚本 - 都不起作用。

版本 1
第一个风味特定资源文件夹flavor-res添加到sourcesets,实现覆盖部分默认资源。任务规则定义了每种风味的任务,这应该(理想情况下)触发整个 jar 的构建。

这可以正常工作并生成所需的罐子,一次只针对一种口味,例如

gradle clean flavorOne 

但是shadowJar 任务只运行一次,如果我这样做的话

gradle clean flavorOne flavorTwo

精简脚本:

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}"
    }

}

感觉它可能不起作用,因为更改检测不知何故不起作用,我尝试了另一种方法。这是脚本的简化版本

第 2 版

修改了规则,为每个风味定义了一个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"]) {
    }
}
 }

但是,现在生成的 jar 格式不正确。第一种风味仅获得主要的工件,但没有显示罐子。第二个罐子只有清单,没有别的。

实现这一目标的正确方法是什么。

PS:不,它不是安卓应用(味道只是品牌的代名词)。

【问题讨论】:

    标签: java gradle jar build.gradle shadowjar


    【解决方案1】:

    我决定重新创建一个风味构建脚本,因为它可以简化为您现在所拥有的。 ShadowJar 任务可以自己处理复制所有的类和资源,不需要单独定义。我还采用了一些本应应用于shadowJar 任务的默认配置,并将其应用于自定义ShadowJar 任务以获得相同的行为。

    我首先构建了一个快速测试项目结构,可以在这里找到: Test Structure

    然后我想出了以下脚本:

    
        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) {}
        }
    
    

    【讨论】:

    • 构建了多个目标,但只有第一个目标包含来自风味文件夹的资源。所有其他目标都不会复制/覆盖任何资源。 gradle风味一种风味两种。最终,我需要有能力做几件事,包括为每种风格修改源文件和其他东西。我不明白为什么第一个目标总是有效,但不是后面的目标,除了它可能与检测目标何时更新有关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-20
    • 2018-06-24
    • 2022-09-28
    • 2015-04-12
    • 1970-01-01
    • 1970-01-01
    • 2016-12-21
    相关资源
    最近更新 更多