【问题标题】:Gradle: How to create multiple jar?Gradle:如何创建多个jar?
【发布时间】:2015-04-30 09:28:21
【问题描述】:

我是 Gradle 和 Groovy 的新手,我希望有一些东西可以解决我的问题。

我有几个包,每个包都需要编译成一个jar。
我发现的一种解决方案是创建多个 Jar 类型的任务,但我想避免复制/粘贴,并在我向项目中添加新包时最终得到一个巨大的 gradle 文件。

我目前的实现是有多个 jar 任务,比如这个:

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

它就像一个魅力,但是我经常添加包,我最终会得到很多包,因此会有很多任务和大量复制/粘贴的代码。

在摆弄build.gradle 文件后,我发现我需要从Jar 扩展才能创建一个jar。

到目前为止,这是该课程的代码:

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

问题在于,创建的 jar 基本上忽略了方法中的所有内容:它只包含一个 MANIFEST.MF,其中包含一行清单版本,并且给出了项目的名称,而不是任务中给出的名称。没有别的了。

如果需要,可以在我的GitHub repo(主要是法语)中在线找到代码。

任何想法都将不胜感激!

【问题讨论】:

  • 我无法复制它。
  • 你的意思是“优化”的代码对你有用吗?
  • 我编辑了问题以添加一些我在它上面所做的进展。
  • 我刚刚回答了这个问题,现在检查它是否有效。

标签: java groovy gradle build.gradle


【解决方案1】:

这是另一个更简单的选项,它允许传递参数。我找到了关于这个主题的灵感:https://discuss.gradle.org/t/passing-arguments-to-a-task/8427/20,这听起来和我想做的一模一样。

这里我们基本上定义了一个返回任务的方法,给定一些参数。剩下的只是测试是否给出了一个版本,或者是否已经给出了有问题的代码并在 @Opal 很大的帮助下进行了调整。

artifacts 块中包含新版本就足以使任务可用。然后,只需运行 gradle jarqcm 来构建单个包或运行 gradle assemble 来编译所有内容。

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】:

    编辑后问题很简单。给定任务没有属性sourceSets(在本例中为Jar)。 sourceSets 定义在 Project 上,每个扩展 DefaultTask 的任务都从其父级继承 project 字段。所以你只需要:

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

    回答

    希望您了解任务配置执行阶段之间的区别。这就是这里发生的问题。基本上你扩展了Jar 任务,因为Copy 类型的所有任务都不是为了扩展而设计的——参见here。在任务操作中,您配置要复制的工件,但是.. 配置为时已晚 - 这是执行阶段。要解决问题任务rules 可以使用。我已经修改了脚本,它是:

    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
    }
    

    并且应该使用gradle buildlistage buildqcm 简单地调用。您可以进行额外验证以检查 &lt;ID&gt; 传递是否在包列表中,例如希望对您有帮助,抱歉让您等了这么久:/

    【讨论】:

    • 感谢您的回答!它解决了Could not find property 'sourceSets' 错误。但是 jar 仍然几乎是空的(只是一个 MANIFEST 文件)并且带有项目名称,而不是任务中给出的名称。有什么想法吗?
    • 还没有。我会发布一个答案;)但如果你有什么建议,我很乐意测试它!
    • @Gabriel,目前状态如何?抱歉,原来的问题有很多修改,我现在不知道发生了什么?
    • 我编辑了这个问题。谢谢你告诉我它很疯狂!我真诚地希望现在更清楚,如果有什么问题,请告诉我。
    • 好的,现在看起来好多了。你有这个项目在线托管吗?
    猜你喜欢
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 2017-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多