Gradle에서 말하는 Task는 Action들의 집합으로 하나의 작업단위를 말한다
대표적으로 java라는 plugin을 추가하면 compileJava, compileTestJava 만약 spring을 추가한다면 bootJar, bootWar와 같이 다양한 작업들을 볼 수 있는데 이 것들을다 Task라고 한다
tasks.register("Task", MyTask)
task Task(type: MyTask)
Task는 위처럼 등록할 수 있다
build.gradle에 직접 작성하는 방식이다
def MyTask = tasks.register("MyTask") {
doFirst {
println "First"
}
println "Run"
doLast {
println "Last"
}
}
위와같이 Task를 직접 build.gradle에 작성하면 된다
이때 doFirst, doLast를 이용하면 Task의 라이프사이클에 대해 관여할 수 있다
실제 Task에도 정상적으로 반영된걸 확인할 수 있다
이를 실행하면 정상적으로 출력이 된다
여기에 이제 간단한 속성을 주어 실제 build과정중 같이 실행될 수 있게도 해보자
def MyTask = tasks.register("MyTask") {
println "Build Run!"
}
compileJava.configure {
dependsOn MyTask
}
이를 실행해보면 build작업 전에 출력이되는걸 알 수 있다
이렇게 dependsOn을 사용해 Task간의 그래프를 형성시킬 수 있다
실제 파일들을 이동시켜보자
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());
}
실제 코드를 보면 위처럼 구현되어 있다
실제 gradle spec에서는 buildSrc를 이용하는 방식을 권장한다
이 방식을 사용하면 빌드에 대한 코드와 소스코드를 명확히 분리할 수 있고 언어마다 분리하여 Task를 기술하기에 매우 용이하다
실제 디렉토리 구조는 위와 같다
ext {
code=20220702
}
ext를 통해 code변수를 선언한다
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이 실행될 때 어떻게 처리할지에 대한 내용을 기술한다
위처럼 출력된다
abstract class GroovyInputTask extends DefaultTask {
@Input
int code;
@TaskAction
void print() {
println this.code
}
}
tasks.register("GroovyInputTask", GroovyInputTask) {
code = this.code
}
@Input을 이용해 대입받으려는 값을 설정할 수 있다
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은 Task들을 사전에 정의한 집합으로 Plugin을 등록시 미리 정의된 Task들을 사용할 수 있다
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정보가 저장된다
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이 반영된 값이 출력된걸 알 수 있다
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가 등록된걸 볼 수 있다
이외에 코틀린과 같은 다른언어도 처리방식은 똑같다