hi, i am having trouble setting up a separate `sou...
# community-support
g
hi, i am having trouble setting up a separate
sourceSet
for our generated code. i am working on a kotlin plugin for our build - the goal is that each project that has generated code should produce a single jar that contains all the generated and non-generated files. I was able to achieve this:
Copy code
val mainSourceSet = extensions.getByType<SourceSetContainer>().named("main").get()

val generatedSourceSet: SourceSet = extensions.getByType<SourceSetContainer>().create("generated") {
    it.java.srcDir(outputDir)
    it.compileClasspath += mainSourceSet.compileClasspath
}

mainSourceSet.apply {
    compileClasspath += generatedSourceSet.output
}

tasks.named<Jar>("jar") {
    from( generatedSourceSet.output )
}
with this, all the expected classes show up in the
jar
however the problem is that in builds that include this build, we get a compilation error when we refer to any of the generated classes - and i can't figure out what's going wrong.
e
local builds use the output classes directory directly, there's no need for them to go through the jar
if you added the generated sources to the main sourceset instead of creating a new sourceset for them,
Copy code
sourceSets.named("main") { java.srcDir(generated) }
then everything would work without other manipulation
☝️ 1
v
With
generated
being the task that generates the code and has its outputs configured properly, so that also all source consumers automatically have the necessary task dependencies.
y
what @ephemient said, but it is also best to have the java compile taskl`dependsOn` the generating task.
e
no, why. do what Vampire says and use a task reference in
srcDirs
which will set up the dependencies for anything that consumes them including JavaCompile
y
Heeha, I have to go and test that now as I don't think it worked in older versions of Gradle. Damn muscle memory 😄
v
At least it works for many many years already. 🙂 Practically any explicit
dependsOn
where the left-hand side is not a lifecycle task is a code smell that usually means you are not wiring outputs and inputs together properly. 🙂
g
previously we had the code generation as part of the
main
source set, and while most things worked fine, that has some issues: code checks, like
spotbugs
had to be disabled, because they consistently fail on the generated code. that is not great, if we have both generated and non-generated code in the project. the idea with creating a separate source set for the generated code is that we can just blanket disable code checks for that source set, and that seems to be simpler than setting up exclusion configuration.
v
If you really need to then do not make the jar just package it or you miss it everywhere else. Make your main sourceset depend on the generated source set for example, that might work somehow. Or make a sibling project just for the generated code that your main project depends on. But imho really, just configure your tools properly to ignore generated classes if you don't want them checked. For example you can configure Spotbugs to ignore all classes annotated with a given annotation. So just make sure all your generated classes are annotated with a specific annotation and then exclude that from Spotbugs.
e
javax.annotation.Generated is common for example
v
Not all tools can work with that one though as it unfortunately has source retention and some tools work on class files.
e
oh and since the package seemed a bit unfamiliar to me… it moved to javax.annotation.processing.Generated but that wasn't the first google hit. that's slightly annoying
v
Yeah, and unfortunately they also didn't "fix" the retention in that one
JaCoCo for example also automatically ignores all classes that have any annotation with simple name
Generated
, but afair also needs higher than source retention, but an own annotation is quickly written and added if needed, I did that in the past.
g
hm...
spotbugs
can ignore based on the annotations, but only if there is an exclude filter xml configured for it, which is not convenient to create for every project (we are looking at potentially 20+ projects with some amount of generated code like this)
e
if you have a convention plugin anyway, just set up a default exclusion for spotbugs in there
g
not a lot of options to do it unfortunately: https://github.com/spotbugs/spotbugs-gradle-plugin/blob/master/src/main/kotlin/com/github/spotbugs/snom/SpotBugsTask.kt i could do exclusion through the
excludeFilter
- but that requires an extra xml in every project.
e
no it doesn't, you can
Copy code
spotbugs {
  excludeFilter = rootProject.file("spotbugs-exclude.xml")
g
yeah, that could work!