Registering output from a custom task

This is another way to ask the same question I’ve been asking a couple of times, this time, with a very specific use-case.

I have a custom-task, that supports extensions (convention-mapping?), and that generates some output files. These output files needs to be registered on a specific sourceSet in the project. I’d like to make this registration within the task, but how to do this?

class MyTask extends DefaultTask {
  String myDir = 'build/generated/default'
  MyTask() {
    // This will NEVER work - since myDir is uninitialized (always /default)
    project.sourceSets.main.java.srcDirs += myDir
    project.afterEvaluate {
      // this will work, most of the times, but what if some of the evaluation 
      // depends on the sourceSets?
      project.sourceSets.main.java.srcDirs += getMyDir()
    }
  }

  @TaskAction
  void generateSources() {
    // this will ONLY work, when task is not UP-TO-DATE
    // otherwise generateSources isn't called
    project.sourceSets.main.java.srcDir += getMyDir()
    // place stuff in myDir
  }

  @AfterEvaluate
  void setUp() {
    // If only we had this...
    project.sourceSets.main.java.srcDir += getMyDir()
  }
}

I must be missing something - it doesn’t make sense, that given all the other Gradle goodies - this (rather simple) concept can not be done in a reliable way?

Use @OutputDirectories, @OutputDirectory, @OutputFiles or @OutputFile annotation to indicate task’s outputs.

class MyTask extends DefaultTask {
  @OutputDirectory
  File myDir = project.file('build/generated/default')

  // your codes
}

I should have been clearer in my original post.

I know how to register the outputs of a task - but in the current custom-task-support, that is all you can do.

How would you (using the output annotations), add the tasks outputs to a specific sourceSet - in a reusable way? I.e. not just do it manually for each task-creation in the gradle-project?