Создайте несколько shadowJars для каждого варианта приложения

Я экспериментирую с gradle и пытаюсь настроить систему, которая создает разные варианты (бренды) приложения, которые в основном различаются конфигурацией. Пока у меня есть две версии скриптов сборки - обе не работают.

Версия 1
Папка ресурсов первого варианта flavor-res добавляется к sourcesets, что приводит к перезаписи некоторых ресурсов по умолчанию. Правило задачи определяет задачи для каждого варианта, которые должны (в идеале) инициировать сборку всей банки.

Это отлично работает и создает требуемую банку для одного аромата за раз, например

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

Однако теперь сгенерированные банки имеют неверный формат. Первый аромат получает только артефакты для основного, но не показывает баночки. Во второй банке есть только манифест и ничего больше.

Каким будет правильный способ достижения этого.

PS: Нет, это не приложение для Android (вкус — это просто синоним бренда).


person Codeheda    schedule 22.06.2018    source источник


Ответы (1)


Я решил воссоздать сценарий сборки аромата, потому что его можно упростить до того, что у вас есть сейчас. Задача ShadowJar может сама обрабатывать копирование всех классов и ресурсов, нет необходимости определять отдельные. Я также взял некоторую конфигурацию по умолчанию, которая применялась бы к задаче shadowJar, и применил ее к пользовательским задачам ShadowJar, чтобы получить такое же поведение.

Сначала я создаю структуру быстрого тестового проекта, которую можно найти здесь: Структура теста

Затем я придумал следующий сценарий:


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

person Cybermaxke    schedule 04.07.2018
comment
Создается несколько целей, но только первая из них включает ресурсы из папки flavor. Все остальные цели не копируют/не перезаписывают какие-либо ресурсы. градация вкусаОдин вкусДва. В конце концов, мне нужна возможность делать несколько вещей, включая изменение исходных файлов и другие вещи для каждого варианта. Я не понимаю, почему первая цель всегда работает, а последующие нет, за исключением, может быть, того, что это как-то связано с определением того, когда цели обновлены. - person Codeheda; 06.07.2018