Gradle놀이(3) - Custom Task, Plugin

정윤성·2022년 7월 2일

Gradle놀이

목록 보기
3/4

Task

Gradle에서 말하는 Task는 Action들의 집합으로 하나의 작업단위를 말한다

대표적으로 java라는 plugin을 추가하면 compileJava, compileTestJava 만약 spring을 추가한다면 bootJar, bootWar와 같이 다양한 작업들을 볼 수 있는데 이 것들을다 Task라고 한다

tasks.register("Task", MyTask)
task Task(type: MyTask)

Task는 위처럼 등록할 수 있다

Built-in

MyTask

build.gradle에 직접 작성하는 방식이다

def MyTask = tasks.register("MyTask") {
    doFirst {
        println "First"
    }
    println "Run"
    doLast {
        println "Last"
    }
}

위와같이 Task를 직접 build.gradle에 작성하면 된다

이때 doFirst, doLast를 이용하면 Task의 라이프사이클에 대해 관여할 수 있다

실제 Task에도 정상적으로 반영된걸 확인할 수 있다

이를 실행하면 정상적으로 출력이 된다

dependsOn

여기에 이제 간단한 속성을 주어 실제 build과정중 같이 실행될 수 있게도 해보자

def MyTask = tasks.register("MyTask") {
    println "Build Run!"
}

compileJava.configure {
    dependsOn MyTask
}
이를 실행해보면 build작업 전에 출력이되는걸 알 수 있다

이렇게 dependsOn을 사용해 Task간의 그래프를 형성시킬 수 있다

Copy

실제 파일들을 이동시켜보자

tasks.register("MyTask", Copy) {
    from 'src/main'
    into 'tasks'
}
정상적으로 복사가 된걸 확인할 수 있다

Copy라는 Task에는 내부적으로 from, into라는 메서드가 있는데 이를 이용해 이동경로를 지정하고 Action을 통해 실제 복사가 된다

public AbstractCopyTask from(Object... sourcePaths) {
	this.getMainSpec().from(sourcePaths);
    return this;
}

@TaskAction
protected void copy() {
	CopyActionExecuter copyActionExecuter = this.createCopyActionExecuter();
    CopyAction copyAction = this.createCopyAction();
    WorkResult didWork = copyActionExecuter.execute(this.rootSpec, copyAction);
    this.setDidWork(didWork.getDidWork());
}

실제 코드를 보면 위처럼 구현되어 있다

buildSrc

실제 gradle spec에서는 buildSrc를 이용하는 방식을 권장한다

이 방식을 사용하면 빌드에 대한 코드와 소스코드를 명확히 분리할 수 있고 언어마다 분리하여 Task를 기술하기에 매우 용이하다

실제 디렉토리 구조는 위와 같다

Task

ext {
    code=20220702
}

ext를 통해 code변수를 선언한다

Inject

abstract class GroovyInjectTask extends DefaultTask {

    private final String message;

    @Inject
    GroovyInjectTask(String message) {
        this.message = message;
    }

    @TaskAction
    void print() {
        println this.message
    }
}

tasks.register("GroovyInjectTask", GroovyInjectTask, "Hello Inject Task")

@Inject는 생성자를 통해 값을 넘겨줄 때 사용한다
@TaskAcation은 실제 Action이 실행될 때 어떻게 처리할지에 대한 내용을 기술한다

위처럼 출력된다

Input

abstract class GroovyInputTask extends DefaultTask {

    @Input
    int code;

    @TaskAction
    void print() {
        println this.code
    }
}

tasks.register("GroovyInputTask", GroovyInputTask) {
    code = this.code
}

@Input을 이용해 대입받으려는 값을 설정할 수 있다

Extenstion

interface GroovyMessageExtension {

    Property<Integer> getCode()
}

abstract class GroovyExtensionTask extends DefaultTask {

    @Input
    abstract Property<Integer> getCode()

    @Internal
    final Provider<String> message = code.map { "CODE - " + it }

    @TaskAction
    void print() {
        println message.get()
    }
}

project.extensions.create('codeExt', GroovyMessageExtension)

tasks.register("GroovyExtensionTask", GroovyExtensionTask) {
    code = codeExt.code
}

codeExt {
    code = this.code
}

Extension을 통해 property를 Lazy Init을 할수 있다

먼저 Extension을 생성한 뒤 이를 task에 등록하고 추 후 Extension을 변경하면 된다

실제 결과는 위처럼 출력된다

Plugin

Plugin은 Task들을 사전에 정의한 집합으로 Plugin을 등록시 미리 정의된 Task들을 사용할 수 있다

build-int

class GroovyInternalPlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {
        project.tasks.register("GroovyInjectTask", GroovyInjectTask, "Hello Inject Task")
    }
}

apply plugin: GroovyInternalPlugin

build.gradle내에 직접 Plugin을 추가한뒤 apply하면 실제 Task정보가 저장된다

plugin id

plugins {
    id 'groovy-gradle-plugin'
}

gradlePlugin {
    plugins {
        groovyPlugin {
            id = 'jys-groovy'
            implementationClass = 'GroovyPlugin'
        }
    }
}

위처럼 플러그인의 Id와 implementationClass를 등록해주면 groovy-gradle-plugin에서 이를 build 디렉토리에 알맞게 생성해준다

implementation-class=GroovyPlugin

build/pluginDescriptors밑에 id.properties에 보면 위처럼 정상적으로 등록되어있다


plugins {
    id 'java'
    id 'jys-groovy'
}

codeExt {
	code = 202207
}

위에서 등록한 id를 사용하려는 build.gradle로 가서 등록해주면 된다

밑에서 외부에서 등록한 extension을 설정하는 모습도 볼 수 있다

정상적으로 extension이 반영된 값이 출력된걸 알 수 있다

Java

plugins {
    id 'java-gradle-plugin'
}

gradlePlugin {
    plugins {
        javaPlugin {
            id = 'jys-java'
            implementationClass = 'JavaPlugin'
        }
    }
}

Groovy -> Java로 plugin을 받고 똑같이 plugin id를 설정해주면 된다


public class JavaPlugin implements Plugin<Project> {

    @Override
    public void apply(Project project) {
        project.task("JavaTask").doFirst(action -> {
            System.out.println("Run JavaTask");
        });
    }
}
정상적으로 JavaTask가 등록된걸 볼 수 있다

이외에 코틀린과 같은 다른언어도 처리방식은 똑같다

정리

  1. Task는 Action들의 집합이다
  2. Plugin은 Task의 집합이다
  3. Custom Task, Plugin은 buildSrc를 통해 선언하자

0개의 댓글