I am trying to create a Gradle build script construct that will build a Java .jar file in release or debug mode, and I am having problems parameterizing the script.
Question: What is the idiomatic way to do this in a Gradle script using a Java plugin? (or, if there is no idiomatic way, what really harmful solution works?)
I am not opposed to the parameterization method, as long as command line calls and IDEs can easily choose between two output parameters. The jar file will be used as a library in other projects, for example. Android app and JavaFX app, so I would like the parameterization method to be invokable / dependend-on from their own Gradle scripts.
Ideally, I would like to "imitate" the capabilities of the Android Gradle plugin to have a Debug / Release version for each task, i.e.
$ ./gradlew build $ ./gradlew assembleRelease $ ./gradlew checkDebug
but it would not be possible to use even the top level buildDebug and buildRelease.
The material I tried
This section is not relevant.
starting point
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 creates a jar file:
$ ls TestGradleModule/build/libs/ TestGradleModule-1.0-release.jar
which, when tested classes are checked using javap , does not contain debugging information. Hooray. No, we need a way to make a debug version.
Add debug and release tasks
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 did not work, since the debugging project is always built, even if buildRelease is specified on the command line. I assume that this is because the code for both tasks runs during configuration ( Gradle build lifecycle ), while I only want it to run. So I probably want to run them at runtime?
Add some doLast tasks
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 this is because of the "default" at the top level. If I comment on this, then the jar version will not be created, instead the default TestGradleModule.jar will be performed. It seems that the contents of the doLast blocks are completely useless in their effect on the compileJava task (but there are no warnings about this?). I assume that these changes are too late for execution at runtime or that there is something else that needs to be done so that compileJava tasks are "configured" differently?
Using configurations?
I noticed the manual for the Java plugin contained a link to buildConfigName and uploadConfigName and claimed that they depend on "Tasks that produce artifacts in the ConfigName configuration." Given that I could not parameterize the material during setup, the plugin's ability to do this 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
- This did not add
buildRelease or buildDebug to the output ./gradlew tasks --all as I expected. But I could do these tasks. - It seemed that only
buildRelease and buildDebug , and not, for example, assembleRelease , etc. buildRelease didn't seem to depend on anything when it started, so it had no useful effect.
Iterate tasks?
As a last attempt, I tried to create all the relevant tasks and link the dependencies for everything. I tried iterating over tasks and adding 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
- This did not seem to create the tasks properly, they were not accessible from the command line, and the “build” was not run by “buildRelease”, etc.
- I would also have to “move” all “actions” from current, existing tasks to debug and release tasks, to avoid duplicating the effects of each of them. And I don’t know how to do it.
In short, I have no idea what I'm doing. As a last resort, I could just create all the tasks manually, but it seems to make the use of the java plugin and very spam senseless?