我该如何为Gradle项目生成类路径?

7
我有一个包含多个包的Gradle项目。构建完成后,每个包都会在build/libs中生成其jar文件。外部的jar依赖项被拉入~/.gradle中。我现在想要通过命令行在本地运行服务,并使用正确的类路径。为此,我正在编写一个脚本来构建类路径。问题在于,该脚本无法理解所有外部依赖关系,因此无法构建类路径。Gradle是否有办法帮忙解决这个问题?理想情况下,我想在构建结束时将所有依赖项转储到一个文件夹中。
2个回答

15

首先,如果可以的话,我建议使用应用程序插件,因为它已经处理了这个问题。

如果你想自己将类路径转储到文件中,最简单的方法是:

task writeClasspath << {
    buildDir.mkdirs()
    new File(buildDir, "classpath.txt").text = configurations.runtime.asPath + "\n"
}

如果你想实际复制类路径上的所有库到一个目录中,可以执行以下操作:

task copyDependencies(type: Copy) {
    from configurations.runtime
    into new File(buildDir, "dependencies")
}

谢谢您的回答。如果我使用应用程序插件,如何控制JVM设置?我想通过命令行传递特定的设置来启动JVM。如果应用程序插件可以帮助我配置这个,那将非常有用。 - Sriram Subramanian
1
我找到了这个链接 - http://www.gradle.org/docs/current/dsl/org.gradle.api.Project.html#N13953。让我试着玩一下,看看它是否能够实现我想要的功能。 - Sriram Subramanian
我没有成功让它工作。我添加了应用程序插件并指定了主类名。运行gradle run时,我收到了类未找到的错误。此外,类和资源文件夹也没有被创建,因此我认为这是错误的原因。gradle run命令问题是 - /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/bin/java -Dfile.encoding=UTF-8 -cp /Users/name/gradleproject/build/classes/main:/Users/name/gradleproject/build/resources/main MainClass - Sriram Subramanian
我找到了问题所在。我的项目有多个包。每个包都有一个build/classes和build/resources文件夹,但是主项目没有一个。我不确定从哪里运行这个命令。 - Sriram Subramanian
当你说“具有多个包的项目”时,你是指多个子项目,对吗?情况是这样的,子项目的配置(运行时、编译等)与父项目的配置是独立的;它们之间互不包含。因此,在根目录下简单地构建应用程序是行不通的。但是,你应该能够在根项目中添加对子项目的依赖项,这样就可以解决问题了。 - Tom Anderson
显示剩余2条评论

2
您可以在构建脚本中尝试以下方法:
// add an action to the build task that creates a startup shell script
build << {
    File script = file('start.sh')

    script.withPrintWriter {
        it.println '#!/bin/sh'
        it.println "java -cp ${getRuntimeClasspath()} com.example.Main \"\$@\""
    }

    // make it executable
    ant.chmod(file: script.absolutePath, perm: 'u+x')
}

String getRuntimeClasspath() {
    sourceSets.main.runtimeClasspath.collect { it.absolutePath }.join(':')
}

谢谢。看起来很有前途。我可以把它添加到build.gradle文件的任何地方吗?另外,我想最好将类路径转储到某个地方,并让脚本引用文件中的内容。这使我能够拥有一个执行一堆事情并且不需要成为gradle脚本一部分的脚本。 - Sriram Subramanian
我更新了问题,展示了我尝试过的内容以及看到的错误。 - Sriram Subramanian
sourceSets.main.runtimeClasspath 基本上是一个 FileCollection,其中包含指向 1) 构建输出文件夹 (build/classes/main, build/references/main 等) 和 2) 外部 jar 依赖项的 File 对象,无论它们在哪个存储库中。您可以轻松地遍历此集合并将 jar 复制到任意文件夹中。 - zagyi
1
这正是应用程序插件所做的事情,只不过它以更豪华的方式完成——它生成一个非常便携的Unix shell脚本和一个Windows批处理脚本,并将所有依赖项复制到一个目录中,以便脚本和库可以一起分发。 - Tom Anderson
@TomAnderson,感谢你指出这个问题。当我最近有这个需求时,应用程序插件逃过了我的注意,因此我手动编写了上面的脚本。今天我也学到了一些新的东西,所以我给你的答案点了赞。 :) - zagyi
这绝对是比较晦涩的插件之一,而且很容易被忽略!值得知道的是,在Gradle维基上有一个社区插件列表:http://wiki.gradle.org/display/GRADLE/Plugins。 - Tom Anderson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接