This message was deleted.
# community-support
s
This message was deleted.
v
Make your plugin register one task for generating Java sources and one task for generating resources. Maybe sure both tasks properly declare inputs and outputs. Register the tasks as source directories like
Copy code
sourceSets {
    java {
        srcDir(generateSourceTask)
    }
    resources {
        srcDir(generateResourcesTask)
    }
}
p
How does the task then know where to generate the files?
would the output just be the source directory? And would the task itself just decide which directories it wants to use?
t
The plugin should define an appropriate default output directory (separate from
src/main/java
and
src/main/resources
!) and the source set directory will now include that directory too, and know that it's generated by that task. The compilation and resource-processing tasks now have implicit dependencies on the code generation tasks through the source set; and the generation tasks' output directory is (re)configurable by the user and everything should just get the files from the correct location.
☝️ 1
p
When you say "the generation task's output directory is configurable by the user", I should also have the output directory as an input to the task, so the user can override the default?
t
Tasks should ideally not be opinionated: take this as input, do your work and output it there; then plugins instantiate them and arrange them and provide opinionated default values. If you structure your code like this, then your tasks will have an
@OutputDirectory
-annotated property to configure it, that the plugin will call with a good default value, and the user could reconfigure at its preferences. And if (because) you arrange tasks by wiring their inputs and outputs (possibly through a source set as suggested here), reconfiguring the task is taken into account by any task that (implicitly then) depends on it.
p
Oh, the user can directly reconfigure the value of an @OutputDirectory-annotated value? I thought I may need an @InputDirectory value that I then set the @OutputDirectory to.
v
Nah, that would not be a good idea
Because then it would be input and output and thus when it modified the outputs, immediately be out-of-date, unless you have run it a second time without changes.
So as Thomas said. :-)
p
Okay, I think I may still be a bit vague on the meaning of the annotations.
v
That a user configures a value does not mean it is input. Input is what the task when executed uses as input. Output is what the task when executed produces as output. Whether your plugin or the downstream user configures these values at configuration time does not change that.
p
If I had a String-output-property instead of a Directory- or File-output-property, it would not make sense for the user to configure it though, right?
v
You cannot have a string output property
Task outputs currently must always be file or directory
p
Oh! That makes so much more sense then. I missed that completely. Okay, thank you so much!
👌 1
It seems that gradle does not recognize srcDir in the following section in my build.gradle.kts:
Copy code
sourceSets {
    java {
        srcDir(createVersionClass)
    }
}
build.gradle.kts:25:9: Unresolved reference: srcDir
t
Should probably be:
Copy code
sourceSets { // SourceSetContainer
  main {     // SourceSet
    java {   // SourceDirectorySet
      srcDir(createVersionClass)
    }
  }
}
p
Ahh! Perfect, thanks!
It still does not work. It's giving me the error
Copy code
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: 
                            public val TaskContainer.createVersionClass: TaskProvider<CreateVersionClassFile> defined in org.gradle.kotlin.dsl
I am registering the task in my plugin-Class as such:
Copy code
GradleVersionerExtension extension = project.getExtensions().create("gradleVersioner", GradleVersionerExtension.class);
        project.getTasks().register("createVersionClass", CreateVersionClassFile.class, task->{
            task.getVersionOutputName().set(extension.getVersionClassName());
            task.getOutputDir().set(extension.getClassOutputDir().convention(project.getLayout().getBuildDirectory().get().dir("gradle-versioner-src")));
        });
And in the CreateVersionClassFile.java, I have:
Copy code
@OutputDirectory
    abstract public DirectoryProperty getOutputDir();
Am I missing anything else?
To me the error sounds like the task does not return what srcDir needs, right?
Strangely, this works:
Copy code
sourceSets{
    main{
        java{
            srcDir(tasks.getByName("createVersionClass"))
        }
    }
}
v
That's strange, I think it should work. Can you show an MCVE demonstrating the problem?
p
I'm having trouble creating a minimal example, because this is an issue with the interaction between a plugin. However if I include the openapi-generator plugin, which has a task that defines an output directory, I would suggest this as a minimal build.gradle.kts example:
Copy code
plugins {
    `java-library`
    id("org.openapi.generator") version "6.2.0"
}

repositories {
    mavenCentral()
}

sourceSets{
    main{
        java{
            srcDir(openApiGenerate)
        }
    }
}
the plugin defines a task openApiGenerate
In this example again, this works:
Copy code
plugins {
    `java-library`
    id("org.openapi.generator") version "6.2.0"
}

repositories {
    mavenCentral()
}

sourceSets{
    main{
        java{
            srcDir(tasks.getByName("openApiGenerate"))
        }
    }
}
v
That's minimal enough if it reproduces 😄
p
So yeah, the first example will not work, the second will
(thanks so much for your extensive help by the way)
👌 1
v
Works fine here, can you make it C(omplete)?
p
Complete?
v
Make a full build where it reproduces and attach it or upload it to GitHub or SwissTransfer.ch or whetever
p
You mean a full project?
v
yes
I copied your code into my play project and the build script compiled without problem
When I hit "reload all gradle projects" in IntelliJ IDEA, it will fail with the message
Copy code
Cannot convert the provided notation to a File or URI: extension 'openApiGenerate'.
The following types/formats are supported:
  - A String or CharSequence path, for example 'src/main/java' or '/usr/include'.
  - A String or CharSequence URI, for example 'file:/usr/include'.
  - A File instance.
  - A Path instance.
  - A Directory instance.
  - A RegularFile instance.
  - A URI or URL instance.
  - A TextResource instance.
(the message is different here than in my earlier project, because openApiGenerate seems to be also the name of the extension)
v
Exactly. And even if it were not the name of the extension, you couldn't use the task name out of the blue, but only with
tasks.
prefix or within
tasks { ... }
So this error message is expected
p
oh, so what would I need to do to make it compile?
v
Actually I now wonder why it worked in my play project
In the GitHub project you sent?
Copy code
srcDir(tasks.openApiGenerate)
p
Ah, let me try that in my other project then
yeah, that works! That's what I was missing
Superb! Thank you very much! Trying to convert a fairly large conglomerate of projects from sbt to gradle is quite a daunting task. But I think I'm starting to get the hang of it
👌 1
v
Ah, no, I get the same error in my play project. I didn't try to sync but just looked at the IDE which is not red as it takes
Any
and just does a runtime check
Now that I think about it, it even makes more sense.
Copy code
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: 
                            public val TaskContainer.createVersionClass: TaskProvider<CreateVersionClassFile> defined in org.gradle.kotlin.dsl
means "you are trying to get the property
createVersionClass
from an object that does not have such a property, there is such a property on
TaskContainer
but where you try to get it from is not of that type".