Best practice for code generation

I have seen various approaches of implementing code generation in Gradle, so I would be interested if there are any best practices about:

  • Is it better to generate the output under the sources directory (i.e. src/main/java-foobar-generated) or under the output (i.e. build/generated/java-foobar)
  • If the generation is driven from a model that is not required at runtime, would you put that as a resource in a separate source-set (i.e. src/foobar-gen/resources/my-model.txt), or as a directory under existing source sets (i.e. src/main/foobar-gen/my-model.txt).
  • What would be a good way to remove stale generated sources (i.e. if the generator provides a list of created files and we want to remove the leftovers)
  • Whether the code generation task should extend from SourceTask, JavaExec or just DefaultTask?

Any tips and pointers to best practices or Gradle facilities that may come in handy, would be appreciated.

Conceptually it’s cleaner to generate to the build folder. But unfortunately IntelliJ still cannot deal with this (they exclude the whole build folder from indexing etc.). So many people work around this by generating to a src folder. I can only encourage you to poke the Jetbrains guys about this silly behavior :slight_smile:

Ideally you give your users a sane default which they can easily override to adapt to their project structure.

src/main/foobar-gen looks like the right approach to me. Unfortunately this requires the internal SourceDirectorySetFactory. For Xtext, I went with a completely separate sourceSet concept instead of using the one from the Java plugin, both to avoid internal API and because Xtext can be used to generate anything, not just Java.

Your generator will have to tell you which generated file was created from which input file, so you can delete them incrementally. The Xtext generator does that by itself, so I didn’t need to do anything in the Gradle plugin.

SourceTask seems like a good starting point for most code generators.