Gradle: How to create multiple jar?

丶灬走出姿态 提交于 2019-12-08 02:52:09

问题


I'm new to Gradle and Groovy, and I'd hope there would be something to solve my problem.

I have several packages, each of which needs to be compiled into one jar.
One solution I've found is to create multiple tasks that are of Jar type, but I'd like to avoid copy/paste and end up with a giant gradle file whenever I add a new package to my project.

My current implementation is to have multiple jar tasks, like this one :

task jarFoo(type: Jar) {
    baseName = "foo"
    version = "1.0.0"
    String className = baseName.capitalize()

    from(sourceSets.main.output) {
        include "$baseName/**"
    }

    from {
        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }

    manifest {
        attributes "Implementation-Title": "$className",
                "Implementation-Version": "$version",
                "Main-Class": "$baseName.$className"
    }
}

It works like a charm, however I add packages very often and I will end up with a lot of packages, therefore a lot of tasks and a lot of copied/pasted code.

After fiddling with build.gradle file, I've found that I needed to extend from Jar in order to get a jar created.

So here's the code for the class so far :

class JarTask extends Jar {
    String jarName = "default"
    String jarVersion = "1.0.0"

    @TaskAction
    def jar() {
        baseName = jarName
        version = jarVersion
        String className = baseName.capitalize()

        // Thanks Opal for reminding that sourceSets
        // is defined in project.
        from(project.sourceSets.main.output) {
            include "$baseName/**"
        }

        from {
            configurations.compile.collect {
                it.isDirectory() ? it : zipTree(it)
            }
        }

        manifest {
            attributes "Implementation-Title": "$className",
                    "Implementation-Version": "$version",
                    "Main-Class": "$baseName.$className"
        }
    }
}

task jarFoo(type: JarTask) {
    jarName = "foo"
}

task jarBar(type: JarTask) {
    jarName = "bar"
    jarVersion = "1.2.42"
}

The problem is that the jar that is created ignores basically everything in the method: it contains only a MANIFEST.MF containing one line with the manifest version and is given the name of the project, not the name given in task. Nothing else.

If needed, you can find the code online in my GitHub repo (mainly in French).

Any idea would be truly appreciated!


回答1:


Here is another easier option that allows to pass parameters. I found the inspiration on this topic : https://discuss.gradle.org/t/passing-arguments-to-a-task/8427/20, which sounds exactly like what I was trying to do.

Here we basically define a method that returns a task, given some parameters. The rest is just testing if a version is given, or the code already given in question and adapted with @Opal great help.

It is sufficient to include the new builds in the artifacts block to make tasks available. Then, just run gradle jarqcm to build a single package or gradle assemble to compile everything.

apply plugin: "idea"
apply plugin: "java"

repositories {
    mavenCentral()
}

dependencies {
    compile "com.intellij:forms_rt:7.0.3"
    runtime "com.intellij:forms_rt:7.0.3"
}

def jarPackage(artifactName, artifactVersion) {
    if (artifactVersion == "" || artifactVersion == null) {
        artifactVersion = "1.0.0"
    }
    return tasks.create("jar${artifactName}", Jar) {
        baseName = artifactName
        version = artifactVersion
        String className = baseName.capitalize()

        from(sourceSets.main.output) {
            include "$baseName/**"
        }

        from {
            configurations.compile.collect {
                it.isDirectory() ? it : zipTree(it)
            }
        }

        manifest {
            attributes "Implementation-Title": "$className",
                    "Implementation-Version": "$version",
                    "Main-Class": "$baseName.$className"
        }
    }
}

artifacts {
    archives jarPackage("aleatoire", ""), jarPackage("calculatrice", "1.2.3"), jarPackage("copier", ""),
            jarPackage("qcm", "1.0.0")
}



回答2:


After you edited the question is easy. There's no property sourceSets for the given task (Jar in this case). sourceSets are defined on Project and every task that extends DefaultTask inherits project field from it's parent. So you just need:

from(project.sourceSets.main.output) {
   include "$baseName/**"
}

ANSWER

I hope you understand the difference between task configuration and execution phase. This is the problem that occurs here. Basically you extended Jar task which as all tasks of type Copy is not designed to be extended - see here. In task action you configure the artifacts to be copied but.. there's too late for configuration - it's execution phase. To solve the problem task rules may be used. I've modified the script and it's:

apply plugin: "idea"
apply plugin: "java"

repositories {
    mavenCentral()
}

dependencies {
    compile "com.intellij:forms_rt:7.0.3"
    runtime "com.intellij:forms_rt:7.0.3"
}

tasks.addRule('Pattern: build<ID>') { String taskName ->
    if (taskName.startsWith('build')) {
        task(taskName, type: Jar) {
            baseName = taskName - 'build'
            version = '1.0.0'
            String className = baseName.capitalize()            

            from(sourceSets.main.output) {
                include "$baseName/**"
            }

            from {
                configurations.compile.collect {
                    it.isDirectory() ? it : zipTree(it)
                }
            }

            manifest {
                attributes "Implementation-Title": "$className",
                        "Implementation-Version": "$version",
                        "Main-Class": "$baseName.$className"
            }
        }
    }
}

artifacts {
   archives project.tasks['buildqcm'], project.tasks['buildlistage'] //etc
}

and should invoked simply with gradle buildlistage buildqcm. You can make additional validation to check if <ID> passed is on the list of packages e.g. Hope that helps and sorry for having to wait so long :/



来源:https://stackoverflow.com/questions/29963959/gradle-how-to-create-multiple-jar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!