Gradle -自定义task

本文详细介绍了如何在Gradle中自定义任务,包括使用DefaultTask和@TaskAction注解创建自定义ZipTask,以及利用afterEvaluate钩子函数动态调整任务依赖。还展示了如何通过插件机制实现更灵活的项目构建。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 了解task

task是gardle中最小的任务单元,任务之间可以进行复杂的操作(如动态创建任务,多任务间依赖调用等等)。gradle的执行其实就是由各种任务组合执行,来对项目进行构建的。

使用gradlew help命令,任何gradle项目都有一个该task,可以执行此命令观察taks执行的流程是否如预期。 可以使用工具查看,还可以通过 gradlew tasks 命令查看可运行任务。

使用gradlew tasks --all 命令查看所有任务。

使用gradlew A B 命令表示执行任务A和B,支持驼峰简写。

2 自定义Task 

在build.gradle中自定义任务:

task <任务名>{ .. },在Gradle5.x以上已经删除<<操作符这种写法。

{ ... }执行的是配置阶段的代码,执行阶段要处理的逻辑需要调用doFirstdoLast方法,在闭包中实现。doFirst{}表示任务执行开始时调用的方法,doLast{}表示任务执行结束调用的方法。

task A(dependsOn:[B]){ .. } 表示任务A依赖于任务B,那么B执行在A之前。

自定义的任务默认分组到other中。

(1)自定义类继承DefaultTask

在方法上使用@TaskAction注解,表示任务运行时调用的方法。 使用@Input表示对任务的输入参数。 使用@OutputFile表示任务输出文件。 使用inputs,outputs直接设置任务输入/输出项。 一个任务的输出项可以作为另一个任务的输入项 (隐式依赖关系)。

class ZipTask extends DefaultTask {
    @Input
    @Optional
  // 表示可选
    String from
    File out
    ZipTask() {

        outputs.upToDateWhen {
            false//  增量构建,每次都会开启,不会跳过任务,构造函数中调用(如果没有更新就不会去构建,设置false将会每次都去构建)
        }
    }
    @TaskAction
    void fun() {
        println " @TaskAction fun()"
        println from
        println out
        //文件进行操作
        //inputs.files.first()
        println inputs.files.singleFile    
        def inFile = inputs.files.singleFile 

        def file = outputs.files.singleFile 
        file.createNewFile()  // 创建文件
        file.text = inFile.text 
    }
}

task myTask(type: ZipTask) {    
    from = "a/b/c" // 输入
    out = file("test.txt") // 输出
    inputs.file file('build.gradle')   //输入文件的路径,这种写法不需要使用 @Input注解
    outputs.file file('test.txt')  //输出的路径
}

使用@TaskAction注解  相当于main()函数,在调用task ,则会自动调用内部有该注解的方法。

(2)下面使用task 完成以下任务

使用自定义任务,实现zip打包packageDebug输出的内容   

这里使用到内部的task Zip ,如何使用这个task 如下

task zip(type: Zip) {
    archiveName "outputs.zip"// 输出的文件名字
    destinationDir file("${buildDir}/custom")// 输出的文件存放的文件夹
    from "${buildDir}/outputs"// 输入的文件
}

好,现在我们是实现任务。

这里我们需要使用到afterEvaluate, afterEvaluate是一个钩子函数  会让闭包里面的内容 在编译结果后才会执行,看具体实现

afterEvaluate {
    println tasks.getByName("packageDebug")
    task zip(type: Zip) {
        archiveName "outputs2.zip"// 输出的文件名字
        destinationDir file("${buildDir}/custom")// 输出的文件存放的文件夹
        from tasks.getByName("packageDebug").outputs.files// 输入的文件
        tasks.getByName("packageDebug").outputs.files.each {
            println it
        }
    }
}

Gradle内部的其他钩子函数。

gradle.beforeProject {
    println "gradle.beforeProject"
}
gradle.afterProject {
    println "gradle.afterProject"
}
gradle.taskGraph.whenReady {  
    println "gradle.taskGraph.whenReady"
}
beforeEvaluate {
    // 在root无效
    println "beforeEvaluate"
}
afterEvaluate {
    println "afterEvaluate"
}

为什么会需要到这些钩子函数,这里我们要了解下gradle的运行阶段,如下图

1 初始化阶段 :

如 setting.gradle 的执行

2 配置阶段(最重要的阶段):

buildGradle 内部创建的是project,所以默认作用域是project.

gradle.beforeProject()这些gradle引用的每一个工程在配置阶段都会去调用这些方法

project.beforeEvaluate()方法 只会在当前工程配置阶段会被调用。由于作用域是project所以project可以去省略。

给gradle 设置监听

gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {
    @Override
    void beforeEvaluate(Project project) {
        println "beforeEvaluate"
    }
    @Override
    void afterEvaluate(Project project, ProjectState state) {
        println "afterEvaluate"
    }
})
gradle.addBuildListener(new BuildListener() {
    @Override
    void buildStarted(Gradle gradle) {
    }
    @Override
    void settingsEvaluated(Settings settings) {
    }
    @Override
    void projectsLoaded(Gradle gradle) {
    }
    @Override
    void projectsEvaluated(Gradle gradle) {
    }
    @Override
    void buildFinished(BuildResult result) {
    }
})

3执行阶段 

 

3 脚本二进制插件(通过实现Plugin)

class MyPlugin implements Plugin<Project> {
    @Override
    void apply(Project target) {
        println "MyPlugin apply"
        target.afterEvaluate {
            println target.tasks.getByName("packageDebug")
            target.task(type: Zip, "zipDebug") {
                archiveName "outputs4.zip"// 输出的文件名字
                destinationDir target.file("${target.buildDir}/custom")// 输出的文件存放的文件夹
                from target.tasks.getByName("packageDebug").outputs.files// 输入的文件
                target.tasks.getByName("packageDebug").outputs.files.each {
                    println it
                }
            }
        }
    }
}

apply 为入口函数跟,内部实现跟上面。当然这块代码也是可以写在java 工程中的

public class MyPlugin2 implements Plugin<Project> {

    @Override
    public void apply(Project target) {
        target.afterEvaluate(project -> {
            System.out.println(project.getTasks().getByName("packageDebug"));
            Map<String, Class<?>> type = new HashMap<>();
            type.put("type", Zip.class);
            Zip zipDebug2 = (Zip) target.task(type, "zipDebug2");
            zipDebug2.setArchiveName("outputs5.zip");
            zipDebug2.setDestinationDir(new File(target.getBuildDir().getAbsolutePath()+"/custom"));
            zipDebug2.from(target.getTasks().getByName("packageDebug").getOutputs().getFiles());
        });
    }
}

自定义Plugin结束后,只需要在buildgradle中进行配置

apply plugin: MyPlugin
apply plugin: MyPlugin2

 

 

### Gradle 8.11.1 运行时API信息与JAR文件路径问题 在使用Gradle 8.11.1时,运行时API的信息通常可以通过官方文档或源码进行查找。Gradle的官方文档提供了详细的API说明[^5],用户可以访问以下链接以获取最新的API文档:https://docs.gradle.org/8.11.1/javadoc/index.html。此外,Gradle的运行时API还包括了`org.gradle.api.file.DirectoryProperty`和`org.gradle.api.file.ProjectLayout`等类[^3],这些类用于处理项目布局和文件目录属性。 针对JAR文件路径问题,如果遇到无法正确生成或定位JAR文件的情况,可以参考以下配置方法。例如,在`build.gradle`文件中添加任务以确保依赖项被打包到最终的JAR文件中: ```groovy jar { from { configurations.runtimeClasspath.collect { zipTree(it) } } manifest { attributes 'Main-Class': 'org.subao.Application' } zip64 = true } ``` 上述代码片段展示了如何将运行时依赖项打包到JAR文件中,并指定主类为`org.subao.Application`[^2]。如果需要更灵活的任务定义,也可以通过自定义任务实现类似功能: ```groovy task jarWithDependency(type: Jar) { manifest { attributes 'Main-Class': 'com.test.popwin.FormatWindowEvent' } from { (configurations.runtimeClasspath).collect { it.isDirectory() ? it : zipTree(it) } } with jar zip64 = true } ``` 当遇到无法下载Gradle的问题时,可以通过修改`gradle-wrapper.properties`文件中的`distributionUrl`来指定镜像地址。例如,使用腾讯云镜像地址: ```properties distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.11.1-bin.zip ``` 阿里云和华为云也提供了类似的镜像支持,可以根据网络环境选择合适的镜像地址[^4]。 如果仍然存在JAR文件路径问题,建议检查以下几点: 1. 确保`build.gradle`文件中正确配置了依赖项。 2. 验证`gradle-wrapper.properties`文件中的`distributionUrl`是否指向正确的Gradle版本。 3. 检查构建过程中是否有错误日志输出,定位具体问题。 ###
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值