从自定义 gradle 插件获取 java 项目的资源路径

Getting the resource path of the java project from a custom gradle plugin

尝试在 java 中创建自定义 gradle 插件,我如何从任务 class 中获取资源路径?

public class MyCustomPlugin implements Plugin<Project> {

  @Override
  public void apply(Project project) {
    project.getTasks().register("doStuff", CustomTask.class);
  }
}
public class CustomTask extends DefaultTask {

  // How do I get java project resources dir from here?
  @Inject
  public CustomTask(ProjectLayout projectLayout) {
    directoryProperty = projectLayout.getBuildDirectory();
  }

  @TaskAction
  public void execute() {
    ...
  }



}

我建议不要获取任务中的目录,因为提供它的插件可能无法应用。相反,我会在注册任务的插件中执行此操作,这样您还可以确保实际应用了必要的插件。 Gradle 如果在没有为输入分配任何值的情况下使用任务,将显示错误,说明没有分配任何内容。

kotlin-dsl:

@CacheableTask
abstract class CustomTask : DefaultTask() {
    @get:InputFiles
    abstract val resources: FileCollection
    //...
}

我无法回答 @InputFiles 是否适合您的用例,因为我不知道您想对资源做什么。有关可用注释及其作用的更多信息,请参阅 Gradle 文档。

plugins {
    java
}

tasks.register<CustomTask>("customTask") {
    resources.set(sourceSets.main.map { it.resources })
}

注意 map {} 确保我们的任务依赖于 processResources 任务,这是自动为我们完成的,因为我们坚持使用 [=34] 的提供者 API =] 一切。

请注意,资源默认位于一个目录中,但并非必须如此。这就是资源定义为 SourceDirectorySet 而不是 Provider<Directory> 的原因。对于源自 SourceSetContainer 的任何内容也是如此。用 Java 源代码更容易解​​释:假设你有 Java 和 Kotlin,那么你将有 src/main/javasrc/main/kotlin,因此有 2 个目录。前者将有一个 **/*.java 包含过滤器,而后者有一个 **/*.kt 包含过滤器。如果我们只想获取所有来源,那么我们使用 sourceSets.main.map { it.java.sourceDirectories },如果我们想要获取两者之一,那就变得复杂了。

您可以通过 project.sourceSets 访问资源。

@Inject
  public CustomTask(Project project) {
    directoryProperty = project.projectLayout.getBuildDirectory();
    sourceSet = project.sourceSets.main
  }

另请参阅此处的参考文档:https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_project_layout

首先,您必须确保这是一个 Java 项目:从您的插件 (project.getPluginManager().apply("java")) 应用 "java" 插件,或者仅在"java" 插件已被用户应用 (project.getPluginManager().withPlugin("java", ignored -> { project.getTasks().register(…); });)。

然后您可以从主源集中获取资源:

SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
// Use named() instead of get() if you prefer/need to use providers
SourceSet mainSourceSet = sourceSets.get(SourceSet.MAIN_SOURCE_SET_NAME);
SourceDirectorySet resources = mainSourceSet.getResources();

顺便说一句,最好的做法是让任务只声明它们的输入和输出(例如,我需要一组目录或文件作为输入,而我的输出将是一个文件或一个目录)并让 默认 值的实际接线由插件完成。
您可以让插件无条件地注册任务,然后在应用 "java" 插件时有条件地将其输入配置到项目资源;或有条件地注册任务或无条件地应用 "java" 插件,如上所示。