我正在尝试创建一个Gradle构建脚本,该脚本将在“发布”或“调试”模式下构建Java .jar
文件,并且在参数化脚本时遇到问题。
问题是:使用Java插件在Gradle脚本中执行此操作的惯用方法是什么? (或者,如果没有惯用的方法,什么是真正有用的hacky解决方案?)
我不介意参数化的方法,只要命令行和IDE调用可以轻松地在两个输出选项之间进行选择。 jar文件将用作其他项目中的库,例如一个Android应用程序和一个JavaFX应用程序,所以我希望参数化方法可以从他们自己的Gradle脚本中调用/依赖。
理想情况下,我想'模仿'Android gradle插件能够拥有每项任务的调试/发布版本,即
$ ./gradlew build
$ ./gradlew assembleRelease
$ ./gradlew checkDebug
但即使是顶级buildDebug和buildRelease也不合适。
此部分与问题无关。
我有以下gradle文件/项目:
group 'TestGradleProjectGroup'
apply plugin: 'java'
sourceCompatibility = 1.8
version '1.0-release'
compileJava {
options.debug = false
}
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
}
这很好用并生成jar文件:
$ ls TestGradleModule/build/libs/
TestGradleModule-1.0-release.jar
,当使用javap
检查提取的类时,不包含任何调试信息。欢呼。不,我们需要一种方法来制作调试版本。
version '1.0-release'
compileJava {
options.debug = false
}
task buildRelease(type: GradleBuild, dependsOn: build) {
project.version = '1.0-release'
compileJava {
options.debug = false
}
}
task buildDebug(type: GradleBuild, dependsOn: build) {
project.version = '1.0-debug'
compileJava {
options.debug = true
}
}
这不起作用,因为总是构建调试项目,即使buildRelease是命令行上给出的任务。我想这是因为这两个任务的代码都是在配置时运行(Gradle build lifecycle),而我只想运行一个。所以我想我想在执行时运行它们?
version '1.0-release'
compileJava {
options.debug = false
}
task buildRelease(type: GradleBuild, dependsOn: build) {
doLast {
project.version = '1.0-release'
compileJava {
options.debug = false
}
}
}
task buildDebug(type: GradleBuild, dependsOn: build) {
doLast {
project.version = '1.0-debug'
compileJava {
options.debug = true
}
}
}
情况更糟。输出文件始终是1.0版本,这是因为顶层的“默认”。如果我发表评论然后没有制作版本化的jar,则会生成默认的TestGradleModule.jar
。似乎doLast块的内容对compileJava任务的影响完全没用(但是没有关于这个的警告?)。我想这些修改为时已晚,无法在执行时完成,或者还有其他需要完成的事情,以便compileJava任务以不同方式“配置”?
我注意到the Java plugin的手册包含对buildConfigName
和uploadConfigName
的引用,并声称它们依赖于“在配置ConfigName中生成工件的任务。”。鉴于我在配置时未能对参数进行参数化,插件执行此操作的能力看起来很有希望:
group 'TestGradleProjectGroup'
apply plugin: 'java'
sourceCompatibility = 1.8
configurations {
debug
release
}
version '1.0-release'
compileJava {
options.debug = false
}
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
}
但:
buildRelease
或buildDebug
添加到./gradlew tasks --all
的输出中。但我可以完成这些任务。buildRelease
和buildDebug
,而不是assembleRelease
等buildRelease
在运行时似乎没有任何依赖,因此没有任何有用的效果。作为最后的尝试,我尝试创建所有适当的任务并链接所有内容的依赖项。我尝试迭代任务并添加依赖项:
gradle.taskGraph.whenReady { taskGraph ->
taskGraph.allTasks.each { taskIter ->
println("iterating" + taskIter)
def releaseTask = project.task(taskIter.name + "Release")
def debugTask = project.task(taskIter.name + "Debug")
taskIter.dependsOn += [releaseTask, debugTask].toSet()
println("new taskIter.dependsOn:" + taskIter.dependsOn)
/*
set debug mode here,
copy over effects of task to debug/release
disable effects of task
*/
}
}
但
简而言之,我不知道自己在做什么。作为最后的手段,我可以手动创建所有任务,但这似乎打败了使用java插件的点,并且非常垃圾?
答案 0 :(得分:4)
经过几个小时的搜索......
“构建脚本基础知识”Gradle
教程的“按DAG配置”部分介绍了执行此操作的方法,即
https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#configure-by-dag
从教程中引用
“Gradle具有配置阶段和执行阶段。在配置阶段之后,Gradle知道应该执行的所有任务.Gradle为您提供了一个钩子来利用这些信息。一个用例就是检查是否发布任务是要执行的任务之一。根据这一点,你可以为一些变量分配不同的值。“
以下是使用gradle.taskGraph.whenReady{}
和buildRelease()
任务应用buildDebug()
的示例...
gradle.taskGraph.whenReady { taskGraph ->
if (taskGraph.hasTask(buildRelease)) {
compileJava.options.debug = false
project.version = '1.0-release'
} else if (taskGraph.hasTask(buildDebug)) {
compileJava.options.debug = true
project.version = '1.0-debug'
}
}
task buildRelease(type: GradleBuild, dependsOn: build) {
}
task buildDebug(type: GradleBuild, dependsOn: build) {
}
IMO,Gradle是一个值得学习的熊。我确实错过了很好的制作。
答案 1 :(得分:3)
您是否需要使用一次gradle创建两个罐子?如果没有,它可以像使用gradle的其他参数一样简单,例如
compileJava {
options.debug = project.hasProperty('debugBuild')
}
gradle assemble -PdebugBuild
也不是说你可以在gradle论坛上得到更好的帮助。
答案 2 :(得分:1)
您的问题很详细,因为您对问题进行了深入分析。虽然我相信如果你能以更简单的方式思考,这个问题就可以解决了 因此,如果我们认为简单,您的案例的可能解决方案是在完成发布后运行调试任务。请参阅以下示例:
compileJava {
options.debug = false
}
task buildRelease(type: GradleBuild, dependsOn: build) {
doLast {
project.version = '1.0-release'
compileJava {
options.debug = false
}
}
}
task buildDebug(type: GradleBuild, dependsOn: build) {
doLast {
project.version = '1.0-debug'
compileJava {
options.debug = true
}
}
}
// Here you are telling the buildDebug task to be executed right after the
// buildRelease task is finalized.
buildDebug.mustRunAfter buildRelease
以上述方式,您可以控制任务执行的顺序,而不会在它们之间引入明确的依赖关系。
答案 3 :(得分:1)
不确定但是我的gradle-java-flavours插件可能会对此有所帮助。例如:
plugins {
id "com.lazan.javaflavours" version "1.2"
}
javaFlavours {
flavour 'debug'
flavour 'release'
}
debugJar {
version = "${project.version}-debug"
}
releaseJar {
version = "${project.version}-release"
}
每种风味都可以获得自己的Jar
和JavaCompile
任务等,您也可以为每种风格指定自定义资源,资源,测试和依赖关系。
有关可用的任务,目录和配置的更多概述,请参阅here;有关涵盖功能的测试,请参阅here。
这种方法与您的GradleBuild
风格不同,因为"风味"可以愉快地生活在一个项目中,该项目构建多个工件,而不是使用两个不同的参数运行两次项目。