Slackbot
09/11/2023, 11:32 AMVampire
09/11/2023, 11:51 AMThomas Broyer
09/11/2023, 11:51 AMJavaExec and rather make your own task that executes your class with an `ExecOperations`' javaExec.
That said, have you tried putting the @OutputDirectory on a property of the argument provider instead?
abstract class GenerateLexerTask
@Inject constructor(
private val objects: ObjectFactory
) : JavaExec() {
private val argumentProvider = ArgumentProvider(objects)
abstract val targetOutputDir get() = argumentProvider.targetOutputDir
// …
init {
// …
argumentProviders.add(argumentProvider)
}
}
internal class ArgumentProvider(
objects: ObjectFactory
) : CommandLineArgumentProvider /* XXX: you should implement Named too */ {
@get:OutputDirectory
val targetOutputDir = objects.directoryProperty()
override asArguments() = listOf(…)
}Vampire
09/11/2023, 11:54 AMThomas Broyer
09/11/2023, 11:58 AMVampire
09/11/2023, 12:01 PMVampire
09/11/2023, 12:02 PMVampire
09/11/2023, 12:02 PMVampire
09/11/2023, 12:17 PMVampire
09/11/2023, 12:18 PMabstract class GenerateLexerTask : JavaExec() {
@get:OutputDirectory
abstract val targetOutputDir: DirectoryProperty
@get:InputFile
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val sourceFile: RegularFileProperty
init {
mainClass = "jflex.Main"
argumentProviders.add {
listOf(
"-d",
targetOutputDir.get().asFile.absolutePath,
sourceFile.get().asFile.absolutePath,
)
}
}
}
val bar by tasks.registering(GenerateLexerTask::class) {
targetOutputDir = layout.buildDirectory.dir("bar")
sourceFile = layout.projectDirectory.file("gradle.properties")
}
val foo by tasks.registering {
inputs.files(bar)
}
and it works fineVampire
09/11/2023, 12:18 PMgw foo with 8.3 used and it failed for not finding the jflex.Main classMarcin Erdmann
09/11/2023, 1:00 PMget() on the properties first rather than map the properties and call get() at the end, I had a similar issue and I've learned never to map lazy properties in task actions from thatMarcin Erdmann
09/11/2023, 1:01 PMCommandLineArgumentProviderMarcin Erdmann
09/11/2023, 1:02 PMI'm not sure argument provider can have output annotations (that have an effect)?It can, @Vampire, there's
@Nested on org.gradle.process.JavaExecSpec#getArgumentProvidersThomas Broyer
09/11/2023, 1:05 PM@Option though (options need to be on the task, cannot be on a @Nested object; unless that changed since I tried it long ago)Marcin Erdmann
09/11/2023, 1:09 PM@OptionMarcin Erdmann
09/11/2023, 1:10 PM@Option prior to you just now, Björn was raising output annotations not being effective.Vampire
09/11/2023, 1:11 PMargumentProviders.add {
listOf(
"-d",
targetOutputDir.asFile.map { it.absolutePath }.get(),
sourceFile.asFile.map { it.absolutePath }.get(),
)
}
reproduces the errorThomas Broyer
09/11/2023, 1:14 PMBut I don't see anybody else mentioningIndeed. I was just widening the all property annotations. I meanprior to you just now, Björn was raising output annotations not being effective.@Option
@Nested works in some cases (input and output) but not others (option)Marcin Erdmann
09/11/2023, 1:29 PM@Option is a completely separate thing as it has nothing to do with inputs and outputs from the incremental build point of view. 🤷Marcin Erdmann
09/11/2023, 1:29 PMPhilip W
09/11/2023, 1:40 PMPhilip W
09/11/2023, 1:54 PMMarcin Erdmann
09/11/2023, 2:05 PMCommandLineArgumentProviderMarcin Erdmann
09/11/2023, 2:06 PMVampire
09/11/2023, 2:07 PMCommandLineArgumentProvider even if it doesn't look like it. 🙂
The Kotlin lambda implements the CommandLineArgumentProvider.Philip W
09/11/2023, 2:08 PMVampire
09/11/2023, 2:08 PMget() the property and do not need to map anymore. This argument provider method you implement is only executed at runtime, so no need to use mapVampire
09/11/2023, 2:08 PMPhilip W
09/11/2023, 2:10 PMPhilip W
09/11/2023, 2:10 PM@CacheableTask
abstract class GenerateLexerTask : DefaultTask() {
@get:OutputDirectory
abstract val targetOutputDir: DirectoryProperty
@get:InputFile
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val sourceFile: RegularFileProperty
@get:Inject
abstract val exec: ExecOperations
init {
exec.javaexec {
mainClass.set("jflex.Main")
argumentProviders.add(object: CommandLineArgumentProvider {
override fun asArguments(): Iterable<String> {
return listOf(
"-d",
targetOutputDir.get().asFile.canonicalPath,
sourceFile.get().asFile.canonicalPath,
)
}
})
}
}
}Vampire
09/11/2023, 2:10 PMPhilip W
09/11/2023, 2:11 PMVampire
09/11/2023, 2:12 PM.path is probably an extension function you define somewhere else in your code. 🙂Philip W
09/11/2023, 2:13 PMPhilip W
09/11/2023, 2:13 PMmap { it.asFile.canonicalPath }Philip W
09/11/2023, 2:16 PMCommandLineArgumentProvider at all and not just ListProperty<String>...Vampire
09/11/2023, 2:24 PM-all distribution, but the -bin distribution. The -all distribution has only one use-case. During editing build scripts and only if they are written with Groovy DSL.
When only executing the build or having Kotlin build scripts anyway, the -all distribution just wastes space, time, and bandwith of everyone and everything executing the build.Vampire
09/11/2023, 2:24 PMtargetOutputDir.get().asFile.canonicalPath that does fail with the error you mentioned?Philip W
09/12/2023, 7:52 AMThomas Broyer
09/12/2023, 10:40 AM.get() on the mapped property though: https://github.com/hfhbd/gradle-jvmargprovider-bug/blob/gradle83/gradle/build-logi[…]main/kotlin/org/jetbrains/grammarkit/tasks/GenerateLexerTask.ktVampire
09/12/2023, 11:08 AMmap her as we advised above. 🙂Philip W
09/12/2023, 11:09 AMget() first without another provider does work with Gradle 8.3, thank you, I missed this combination after creating the reproducer. And it does work!
Yes, I already created an issue: https://github.com/gradle/gradle/issues/26340Marcin Erdmann
09/12/2023, 11:55 AM