Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running a task within a custom task in Gradle

I'm trying to write a custom Gradle plugin using Java. One of the things I'll need to do within this plugin is copy all the defined dependencies into a folder. I've found out how you can do this using a task in the build.gradle file:

task copyDeps(type: Copy) {
    from configurations.runtime
    into 'build/lib'
}

However, I'm struggling to figure out how I would run this task from within my own custom task. I've tried doing this:

public class MyTask extends DefaultTask {

    @TaskAction
    public void executeTask() {
        Copy copyTask = new Copy();
        copyTask.into(libFolder).from(getProject().getConfigurations().getByName("runtime").execute();
    }
}

However, when I run this I get the exception:

Task of type 'org.gradle.api.tasks.Copy' has been instantiated directly which is not supported. Tasks can only be created using the DSL.

I understand what it is trying to say, but I haven't been able to find out I would be able to execute this task using the DSL from within Java.

like image 753
Brian DiCasa Avatar asked Dec 06 '15 21:12

Brian DiCasa


People also ask

How do I run multiple tasks in Gradle?

Executing Multiple Tasks You can execute multiple tasks from a single build file. Gradle can handle the build file using gradle command. This command will compile each task in such an order that they are listed and execute each task along with the dependencies using different options.

How do I run a list of tasks available in Gradle tasks?

Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. #165.

What is the use of Buildscript in Gradle?

Gradle builds a script file for handling two things; one is projects and other is tasks. Every Gradle build represents one or more projects. A project represents a library JAR or a web application or it might represent a ZIP that is assembled from the JARs produced by other projects.


1 Answers

You can't create tasks within tasks in Gradle. If you want to write a custom plugin with a task as you have described, the way to go is to write a custom plugin class and within that plugin class you declare a task of type Copy that does what you want to do. This could look like this:

class MyCustomPlugin extends Plugin<Project> {

    void apply(Project project) {
        project.tasks.create("copyDeps", Copy.class) {
            from configurations.runtime
            into 'build/lib'
        }
    }

}

Now, if you apply this plugin within your buildscript:

apply plugin:MyCustomPlugin

you automatically have a task named "copyDeps" of type Copy in your build.

One more thing:

Sometimes it can be convenient to do a simple copy operation in a custom task. This can be done using the project.copy util method. A task like this would look this

public class MyTask extends DefaultTask {

    @TaskAction
    public void executeTask() {
        project.copy {
            into(libFolder)
            from(project.configurations.runtime)
        }
    }
}

With plain java it would look like this:

public class MyTask extends DefaultTask {

    @TaskAction
    public void executeTask() {
        project.copy(new Action<CopySpec>() {
            @Override
            void execute(CopySpec copySpec) {
                copySpec.into(libFolder);
                copySpec.from(getProject().getConfigurations().getByName("runtime"));
            }
        });

    }
}

One last thing:

You should never call Task#execute() your own. This method is considered to be internal API in Gradle and executing it directly causes unexpected behaviour. (for example it breaks Gradles' incremental build feature)

like image 70
Rene Groeschke Avatar answered Oct 07 '22 12:10

Rene Groeschke