Create empty default tasks across projects

(Jamie Olson) #1

I’ve noticed that gradle doesn’t have the same notion of build ‘stages’ as maven. It seems to me like it’d be useful to have some default ‘dummy’ packages, like prepare, compile, test, package, install, that tasks could just register dependencies for. This would make it a bit easier to manage multi-module build with different languages and build tasks.

This would also reduce the likelihood of certain name collisions since plugins wouldn’t have to use such easy to remember/type (read: short) task names. Instead they could just add tasks as dependencies of default build tasks.

(Peter Niederwieser) #2

There are already a bunch of so-called lifecycle tasks serving this purpose: ‘clean’, ‘assemble’, ‘check’, ‘build’, to name a few. Anything that you are missing particularly?

Gradle’s camel case abbreviation for task names should help to have longer task names that are nevertheless convenient to use.

(Jamie Olson) #3

Awesome, apparently I missed this. Are these documented anywhere? Are these always present? I noticed gradle usually complains when you create a task with a name that already exists, but it hasn’t complained when I created eg clean and check tasks.

Is the suggested best practice then to append e.g. plugin information to the task name? For example, one of my plugins is building packages for R code, so I’d just have checkR, buildR, etc. And then would “gradle build” also run buildR and any other build tasks?

Thanks for the tip on camel case, too. I think I’d seen that in the manual but had forgotten.

(Peter Niederwieser) #4

The lifecycle tasks aren’t “global” but are brought in by some plugins like ‘base’ and ‘java-base’ (which really is ‘jvm-base’). They are documented in the Gradle User Guide. Maybe some of the stuff in ‘java-base’ should go somewhere else, e.g. into a new ‘language-base’. These things are still being sorted out as we move into non-JVM land.

Typically, your plugin won’t have tasks as general as ‘classes’ and ‘check’. It will just make those tasks depend on its own, more specific tasks like ‘compileR’ and ‘testR’. Typically you won’t have to add task dependencies to ‘build’ directly, because ‘build’ depends on ‘classes’ and ‘check’ anyway. Have a look at the Groovy or Scala plugin to get some inspiration.

(Jamie Olson) #5

Sorry, am I missing something? The only reference I see to the lifecycle tasks in the base plugin are brief mentions that they exist: googled. I guess I should just look more closely at the gradle source.

(Peter Niederwieser) #6

From the user guide:

The Java plugin also adds a number of tasks which form a lifecycle for the project: […]

Gradle doesn’t have baked-in phases like Maven does. Instead, conventions like these lifecycle tasks are provided by plugins, and that’s also where they are documented. If you can think of a better way to document this, feel free to send a pull request.

(Jamie Olson) #7

I noticed that at least the java plugins explicitly apply other plugins (e.g. base) to their project. Is that the preferred strategy (instead of e.g. potentially awkward inheritance) ?

(Peter Niederwieser) #8

Yes, delegation is strongly preferred over inheritance.

(Jamie Olson) #9

Does anything bad happen if two plugins both attempt to apply BasePlugin.class?

(Peter Niederwieser) #10


(Jamie Olson) #11

So from the command line, “gradle check” will also run “checkR” task if it exists, but that doesn’t mean “checkR” will run when “check” is run as a dependency for “build” correct?

So I still need to add explicit dependencies to the lifecycle tasks, right?

(Peter Niederwieser) #12

You just need a dependency from ‘check’ on ‘checkR’. Just give it a try and see what happens.

(Jamie Olson) #13

Thanks again, I’ll stop pestering you with questions I can answer myself.

(Jamie Olson) #14

One last comment. I see build, clean, assemble and upload lifecycle tasks. I think it would be useful to have one additional lifecycle tasks e.g. “prepare” or “generate”. There are cases where it may be necessary to do either some additional configuration or downloading, etc before the rest of the build can begin.

I also think that the “check” lifecycle task in the java plugin is general enough to be pulled up into the base plugin. Documentation generation also could have a lifecycle task, e.g. javadoc, scaladoc, etc.

(Jamie Olson) #15

Also I thought “install” was available as a task with the java plugin, but I can’t seem to find it. Maybe it’s loaded when I specified the maven repo. Anyway, it seems like “install” would also make sense as a lifecycle task.

(Peter Niederwieser) #16

A task like ‘prepare’ that everything else depends on is a smell. Instead you should be specific about who depends on what. In cases where you absolutely need a global ‘prepare’, you should use a hook like gradle.buildStarted()’ rather than a task.

‘docs’ would certainly be a useful addition.

(Peter Niederwieser) #17

‘install’ is added by the Maven plugin. Not sure it would make sense as a lifecycle task, because it could mean many different things.

(Jamie Olson) #18

I think you have a good point. I think the concept of installation is pretty clear, but you’re right, even with a java project I want to know whether installation means put a jar in the maven repo, or install the jar and a sh script in /usr/local/

I think it’d be convenient to group those kinds of tasks, but it could certainly add a lot of ambiguity about what exactly is happening with the lifecycle.

(Jamie Olson) #19

I guess I meant something more like “generate”. In one case I’m extracting meta-data from source code annotations into a file(that’s required for the build to be up-to-date and check and install to succeed), in another I’m processing (java) annotations to generate ® source code, and in another I’m downloading source code from a repository (to package it locally for a remote installation).

(Jamie Olson) #20

Or should these simply be “build” tasks that all other “build” tasks depend on?