모바일/Android

gradle을 이용한 커스텀 플러그인 만들기 이해

늘근이 2017. 1. 19. 23:25

그라들의 도큐멘테이션은 혀를 내두를 정도이다. 

무슨 그냥 빌드하는 놈이 이렇게 문서가 많은지.

물론 친절해서 좋은데, 처음보는 사람에게는 곤욕이다.


어쨌든, 플러그인을 만들기 위해 이해가 필요한 부분은 이 부분이였다. 

https://docs.gradle.org/current/userguide/custom_plugins.html


build.gradle

apply plugin: GreetingPlugin

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.task('hello') {
            doLast {
                println "Hello from the GreetingPlugin"
            }
        }
    }
}

Output of gradle -q hello

> gradle -q hello
Hello from the GreetingPlugin


위의 설명이 무엇인고로 하면, 커스텀 플러그인을 제작하기 위해서는 저렇게 Plugin인터페이스를 상속받는 놈을 하나 만드는데, apply() 메서드가 불려지면서, 실속없이 또 인사나 한다.

여기까지 이해는 쉽다. 그냥 클래스가 플러그인 아닌가? 그 안에 스칼라에서도 생성자와 비슷한 역할을 했던 적용메서드인 apply()를 해놓으면 역시나 작업을 하게끔한다.


이제 약간 이름에서부터 헷갈리는 Extension이라는 놈이 나오는데, 보통 이 놈은 뭔가의 확장팩..(응? 그건 expansion이였나??)이라는 뜻을 가진 놈이 아니덩가?

사실 그렇기 보다는 외부에서부터 무언가 다른 인자가 들어오면 그것을 이용가능케 해줄 helper가 나은 명명인것같기도 하다.


build.gradle

apply plugin: GreetingPlugin

greeting.message = 'Hi from Gradle'

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        // Add the 'greeting' extension object
        project.extensions.create("greeting", GreetingPluginExtension)
        // Add a task that uses the configuration
        project.task('hello') {
            doLast {
                println project.greeting.message
            }
        }
    }
}

class GreetingPluginExtension {
    def String message = 'Hello from GreetingPlugin'
}

Output of gradle -q hello

> gradle -q hello
Hi from Gradle

홈페이지에서 제공하는 위와같은 거시기를 보면, 사용자로부터 무언가 greeting.message라는 놈으로 들어온다는 상황을 가정한건데, 막상 플러그인 내부에서 저걸 처리할수 있는 놈이 없어 보인다. 따라서, greeting이라는 놈이 가지고 있는 message 를 담을만한 틀이 하나 있어야 하는데, 이 틀이 GreetingPluginExtension이라는 뜻으로 보인다. 

그렇다면, GreetingPluginExtension greeting = new GreetingPluginExtension() 

을 콜 해주어야 하는가? 여기는 groovy이기도 하고, 플러그인을 다루는 중이기 때문에

project.extension.create("greeting", GreetingPluginExtension) 이라고 메서드를 콜하면  greeting이라는 이름으로 익스텐션 타입의 객체를 하나 생성해라 

라는 뜻으로 보인다. 

이후에는 project.greeting.message 라는 형식으로 doLast를 한다면, 사용자로부터 받은 메시지인 Hi from Gradle 이 뜬다고 생각하면 될것이다. (Hello from GreetingPlugin 메시지는 그냥 디폴트 값으로 보인다. 플레이스홀더같은?)


build.gradle

apply plugin: GreetingPlugin

greeting {
    message = 'Hi'
    greeter = 'Gradle'
}

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.create("greeting", GreetingPluginExtension)
        project.task('hello') {
            doLast {
                println "${project.greeting.message} from ${project.greeting.greeter}"
            }
        }
    }
}

class GreetingPluginExtension {
    String message
    String greeter
}

Output of gradle -q hello

> gradle -q hello
Hi from Gradle

여기서부터는 어려울게 없다. 클래스 멤버가 두개로 늘어났을 뿐, 사용법은 똑같다. println으로 감싸져있어서 포맷상 $안에 표시되어있을뿐 걍 따로따로 project.greeting.message 와 project.greeting.greeter가 불려지는것을 같아 보인다. 

알아서 저 구멍에 메시지와 그리터가 들어가므로 답은 Hi from Gradle이라는 문자열이 뜨는것이다. 


이후에는 Lazy 형식의 task생성과 커스텀 플러그인을 와이어링 하는 방법에 대해 후술하고 있는데, 여기서는 지면이 부족하여 적지않는다.