Paul Woitaschek
04/08/2021, 9:58 AMtasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
dependsOn(generateKotlinCodeTask)
}
However this one now fails on multiplatform.
I debugged the task names and I can make it work if I add that task dependency for KotlinNativeCompile
as well.
However I'm asking myself if this is the correct approach to hook code generation into the build process.Vampire
04/08/2021, 10:14 AMbuild/generated-sources/<taskName>/kotlin
and then wire the sources in properly. With Java it would be:
val mySourceGeneratingTask by tasks.registering(...) {
...
}
val generate by tasks.registering {
dependsOn(mySourceGeneratingTask)
}
sourceSets {
main {
java {
srcDir(mySourceGeneratingTask)
}
}
}
With Kotlin it is probably very similar, though I didn't try that yet.
The generate
task is purely optional I just like to have a lifecycle task that depends on all generation tasks.
And if you care about IntelliJ integration, you would also register that source directory as generated sources in the idea
plugin of course. 🙂Paul Woitaschek
04/08/2021, 10:20 AMfun generatedStoriesDirectory() = File(buildDir, "generated/stories/code")
Now I add that directory to the source set:
kotlin {
sourceSets {
commonMain {
kotlin.srcDir(generatedStoriesDirectory())
Pass the directory to my task:
val generateStoriesTask = tasks.register<GenerateStoriesTask>("generateStories") {
csvFile.set(File(projectDir, "stories.csv"))
output.set(generatedStoriesDirectory())
}
What I don't understand about your solution is where I would define that build directory. And how can a srcDir have a task as an inputVampire
04/08/2021, 10:23 AMdependsOn
if you can prevent it.
When using the task as src dir, it's output is used as sources.
And the added benefit is, that you have an implicit task dependency so whenever the sources are needed and the task is not yet run or out-of-date, it will automatically be run.
Even if you build a source jar or iterate over source files or similar.Vampire
04/08/2021, 10:24 AMPaul Woitaschek
04/08/2021, 10:26 AMPaul Woitaschek
04/08/2021, 10:27 AM@get:OutputDirectory
abstract val output: Property<File>
->
@get:OutputDirectory
val output: File = File(project.buildDir, "generated/stories/code")
And now I just register the task:
val generateStoriesTask = tasks.register<GenerateStoriesTask>("generateStories") {
csvFile.set(File(projectDir, "stories.csv"))
}
And use it as a srcDir: kotlin.srcDir(generateStoriesTask)
Thanks a lot, this makes way more sense now!Vampire
04/08/2021, 10:52 AMProperty<File>
, but DirectoryProperty
or RegularFileProperty
as that then also has the right semantics for example.
If you don't want it to be changeable anymore (changeable would be no problem it would still work) you could also use disallowChanges()
like
@get:OutputDirectory
abstract val output: DirectoryProperty
@get:Inject
abstract val layout: ProjectLayout
init {
output
.value(layout.buildDirectory.dir("generated/stories/code"))
.disallowChanges()
}
or a Provider<Directory>
like
@get:OutputDirectory
val output: Provider<Directory>
@get:Inject
abstract val layout: ProjectLayout
init {
output = layout.buildDirectory.dir("generated/stories/code")
}
This way you don't capture the buildDir
that is configured at the time the task is instantiated but will follow suit if the build directory gets reconfigured later.Paul Woitaschek
04/08/2021, 11:32 AM@get:InputFile
abstract val csvFile: RegularFileProperty
@get:Inject
internal abstract val layout: ProjectLayout
@get:OutputDirectory
internal abstract val output: DirectoryProperty
init {
@Suppress("LeakingThis")
output.value(layout.buildDirectory.dir("generated/stories"))
.disallowChanges()
}
Vampire
04/08/2021, 11:33 AMVampire
04/08/2021, 11:35 AMlayout
yeah, or maybe even protected
,
but why for the output
?
There are indeed situations where it is better or necessary to use the property or provider directly.
Just where you can use the task directly it is more concise to do soPaul Woitaschek
04/08/2021, 11:46 AMPaul Woitaschek
04/08/2021, 11:48 AMVampire
04/08/2021, 11:50 AMlayout
but imho output properties should be accessible for further wiring when wiring the task itself is not appropriate. 🙂Paul Woitaschek
04/08/2021, 11:51 AM