Reputation: 4448
I’m writing a plugin to do some custom file indexing for an internal use-case we have where I currently work.
Doing some tinkering I’ve found that I can create my task/plugin in the rootProject’s buildSrc apply a task to each module via
subprojects {
apply plugin: MyCustomIndexerPlugin
}
My plugin's implementation looks like this, and works just fine in the context of that single module:
@Override
public void apply(Project project) {
Convention convention = project.getConvention();
System.out.println("Working: " + project.getName());
JavaPluginConvention javaPluginConvention = convention.getPlugin(JavaPluginConvention.class);
SourceSetContainer sourceSets = javaPluginConvention.getSourceSets();
TaskContainer taskContainer = project.getTasks();
MyCustomIndexerTask myCustomIndexerTask = taskContainer.create("myCustomIndexerTask", MyCustomIndexerTask.class, task -> task.setSourceSetContainer(sourceSets));
Task build = taskContainer.getByName("build");
build.dependsOn(myCustomIndexerTask);
}
And here is my task:
@TaskAction
public void taskAction() {
SortedMap<String, SourceSet> asMap = getSourceSetContainer().getAsMap();
for (String sourceSetName : asMap.keySet()) {
SourceSet sourceSet = asMap.get(sourceSetName);
Set<File> files = sourceSet.getAllJava().getFiles();
for (File file : files) {
System.out.println(sourceSetName + " -> " + file);
}
}
}
This is (sorta) okay as a proof of concept, but I’d like to have my custom task performed at the rootProject level. So after all modules build successfully I run my code against all sourceSets. Is this possible or do I need to somehow pass this data from module to module as my project builds?
I’m having a difficult time finding the right documentation to do the right meta-coding I need to perform.
Upvotes: 2
Views: 5422
Reputation: 185
Conventions are deprecated in Gradle as of 7.5.1 (The move to do so has been around since 2017)
You can accomplish the same results by using extensions:
rootProject.getSubprojects().forEach(subProject -> {
JavaPluginExtension javaExtension = subProject.getExtensions().getByType(JavaPluginExtension.class);
javaExtension.getSourceSets().forEach(set -> {
// do things with source-set
});
});
Upvotes: 3
Reputation: 17769
You can apply the plugin in the rootProject's build.gradle
file.
You could then do something like the following:
@Override
def apply(Project project) {
if (project != project.rootProject) { throw new IllegalStateException("Can only be applied to rootProject") }
def myCustomIndexerTask = taskContainer.create("myCustomIndexerTask", MyCustomIndexerTask.class)
project.tasks.getByName("build").dependsOn myCustomIndexerTask
project.subprojects.each { sp ->
sp.whenPluginAdded(JavaPlugin) { jp ->
def javaPluginConvention = sp.getConvention().getPlugin(JavaPluginConvention)
def sourceSets = javaPluginConvention.getSourceSets()
myCustomIndexerTask.addSourceSetContainer(sourceSets)
}
}
}
In your custom task you would then need to iterate over all the SourceSetContainers
that were added.
Upvotes: 3