Inferred Task dependencies using Properties of simple types

Hi, I am wondering if its possible to use Properties of simple types to create inferred dependencies between Tasks. Properties of simple types can be used for Task inputs, but can they also be used for Task outputs, and can you wire them up like below?

https://docs.gradle.org/current/userguide/lazy_configuration.html#working_with_task_dependencies_in_lazy_properties

I could not get this idea to work, modified from the example above:

class Producer extends DefaultTask {
    final Property<String> message = project.objects.property(String)

        @TaskAction
        void produce() {
            message.set("Hello, World!")
        }
    }

class Consumer extends DefaultTask {
    @Input
    final Property<String> message = project.objects.property(String)

    @TaskAction
    void consume() {
        logger.quiet(message.get())
    }
}

task producer(type: Producer)
task consumer(type: Consumer)

// Connect the producer task output to the consumer task input
// Don't need to add a task dependency to the consumer task. This is automatically added
consumer.message = producer.message.map { it }

More Context : I am writing a plugin that works with Android Gradle Plugin (AGP). The AGP creates many tasks dynamically for each variant XXX. I wanted to create an ‘uploadXXX’ task for each variant that uploads the output from assembleXXX task to a service. These uploadXXX tasks should all depend on one gitLogTask’s output that formulates the logs since previous upload. The git logs should only be computed once, of course. Each uploadXXX task has 2 dependencies / inputs: the assembleXXX task output and the gitLogTask output, which in my mind would just be a Property.

What you are trying to do does not work because Producer.message is not a task output. While Gradle has the concept of input files and properties, it does not have output properties, only output files.
In example 5 of the page you referenced, Producer.outputFile is annotated with @OutputFile and therefore the producing task information is carried along with the Property instance. The example maps the contents of that file to the consumer’s input property. Perhaps you can adapt your code to use an intermediate file in a similar fashion.