I'm trying to create a Gradle build script that will build a Java .jar
file in 'release' or 'debug' modes and am having trouble parametrizing the script.
The question is: What is an idiomatic way to do this in a Gradle script, using the Java plugin? (or, if there's no idiomatic way, what's a hacky solution that actually works?)
I don't mind the method of parametrization, just as long as the command-line and IDE invocations can easily choose between the two output options. The jar file will be used as a library in other projects, e.g. an Android app and a JavaFX app, so I would like the method of parametrization to be invokable/depended-on from their own Gradle scripts.
Ideally I'd like to 'emulate' the Android gradle plugin's ability to have a Debug/Release version of every task, i.e.
$ ./gradlew build
$ ./gradlew assembleRelease
$ ./gradlew checkDebug
but failing that even a top level buildDebug and buildRelease would be suitable.
This section isn't really relevant to the question.
I have the following gradle file/project:
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'
}
This works fine and produces the jar file:
$ ls TestGradleModule/build/libs/
TestGradleModule-1.0-release.jar
which, when the extracted classes are inspected with javap
, doesn't contain any debug information. Hurrah. No we need a way to make a debug version.
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
}
}
This didn't work, as the debug project is always built, even if buildRelease is the task given on the command line. I guess this is because the code for both tasks is run at Configuration time (Gradle build lifecycle), whereas I only want one to run. So I guess I want to run them at Execution time?
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
}
}
}
This is even worse. The output file is always 1.0-release, and that's because of the 'default' at the top level. If I comment that out then a versioned jar is not made, instead the default of TestGradleModule.jar
is made. It seems that the contents of the doLast blocks are completely useless in their effect upon the compileJava task (but there's no warning about this?). I guess these modifications are too late to be done at execution time, or that there's something else that needs to be done so that the compileJava tasks is "configured" differently?
I noticed the manual for the Java plugin contained a reference to buildConfigName
and uploadConfigName
, and claimed they depend on "The tasks which produce the artifacts in configuration ConfigName.". Given that I was failing to parametrize stuff at Configuration time, the plugin's ability to do that looked promising:
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'
}
but:
buildRelease
or buildDebug
to the output of ./gradlew tasks --all
, as I expected it to. But I could run those tasks.buildRelease
and buildDebug
, not e.g. assembleRelease
etcbuildRelease
didn't seem to depend on anything when run so therefore had no useful effect.As a final attempt I've tried to create all of the appropriate tasks and linking the dependencies for everything. I tried iterating over the tasks and adding the dependencies:
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
*/
}
}
but
In short, I have no idea what I'm doing. As a last resort I could just create all of the tasks manually, but that seems to defeat the point of using the the java plugin and is very spammy?
To do that, just pick the Gradle Remote Debug configuration and then click the Debug icon on the project to be debugged. For more info, you can read the Gradle documentation. Follow us for more productivity tools & ideas for Android, Kotlin & Gradle projects.
The result JAR will be created in build/libs/ directory by default.
After many hours of searching ...
The "Configure by DAG" section of the "Build Script Basics" Gradle
tutorial describes a way to do this, i.e.
https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#configure-by-dag
Quote from the tutorial
"Gradle has a configuration phase and an execution phase. After the configuration phase, Gradle knows all tasks that should be executed. Gradle offers you a hook to make use of this information. A use-case for this would be to check if the release task is among the tasks to be executed. Depending on this, you can assign different values to some variables."
Here is an example of applying gradle.taskGraph.whenReady{}
using buildRelease()
and buildDebug()
tasks...
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 is a total bear to learn. I sure do miss good ol' make.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With