Web/Gradle 2020. 8. 17. 18:06

 

그래들 프로젝트를 사용중인데, 간혹 idea에서 "Could not initialize class org.codehaus.groovy.runtime.InvokerHelper"라는 에러 메시지가 뜨는 경우가 있다. 여러가지 요인이 있을 수 있지만, 필자가 저 에러를 보았던 순간은 jdk 1.8에서 jdk14 버전으로 올리면서 났던 에러 메시지 인데, 이유는 gradle version이 jdk14를 지원하지 못하는 낮은 버전이었기 때문이다.

 

 

그래서, 프로젝트 디렉토리중 "gradle/wrapper/gradle-wrapper.properties"에서 gradle 버전을 올려주어서 해결하였다.(5.x -> 6,3)

posted by 여성게
:
Web/Gradle 2019. 10. 21. 20:47

 

이번 포스팅은 간단하게 Gradle Task를 작성하는 방법이다. 모든 경우의 Task 작성 방법을 다루지는 않지만 몇가지 예제를 다루어볼 것이다.

 

1
2
3
4
5
task hello{
    doLast{
        println 'Hello'
    }
}
cs

 

위는 간단하게 'Hello'라는 문자열을 출력하는 태스크이다. 아래 명령으로 실행시킨다.

 

1
2
3
4
5
gradle -q hello
 
result->
Hello
 
cs

 

-q 옵션 같은 경우는 로그 출력없이 결과값만 출력하는 옵션이다. 만약 -q 옵션을 뺀다면 빌드에 걸린 시간등의 로그가 찍히게 된다.

 

디폴트 태스크 정의

gradle -q 라는 명령어로 실행하는 디폴트 태스크를 정의하는 방법이다. 보통 빌드전에 clean, install 등의 작업을 기계적으로 하는 경우가 많은데, 디폴트 태스크로 정의하여 사용하면 보다 간편하다.

 

1
2
//Default Task usecase : gradle -q
defaultTasks 'bye', 'variablePrint'
cs

 

 

태스크간 의존성

다음은 태스크간 의존성을 설정하는 방법이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Task 의존성설정
task bye{
    dependsOn 'hello'
    doLast{
        println 'bye'
    }
}
 
task hello{
    doLast{
        println 'Hello'
    }
}
 
cs

 

위 태스크는 bye를 실행하기 전에 hello Task를 실행시키는 의존성을 설정하였다.

 

1
2
3
4
5
6
gradle -q bye
 
rsult->
Hello
bye
 
cs

 

태스크에서 변수사용 하기

태스크에서 사용자 정의 변수를 정의해서 사용가능하다. 결과값은 생략한다.

 

1
2
3
4
5
6
7
8
9
10
//변수사용방법
task variableTask{
    ext.myProperty = 'testProperty'
}
 
task variablePrint{
    doLast{
        println variableTask.myProperty
    }
}
cs

 

사용자 정의 메서드 사용하기

gradle은 groovy, kotlin 스크립트를 이용한 빌드툴이다. 즉, 변수선언은 물론 메서드를 정의해서 사용가능하다.

 

1
2
3
4
5
6
7
8
9
10
//메서드 사용
task methodTask{
    doLast{
        printStr('method args')
    }
}
 
String printStr(String arg){
    println arg
}
cs

 

빌드스크립트 자체에 의존성 라이브러리가 필요할 때

프로젝트가 사용하는 라이브러리는 물론, 빌드 스크립트 자체가 어떠한 외부 라이브러리가 필요할 때가 있다. 왜냐? gradle 자체는 groovy 언어로 작성하기 때문에 다른 외부 라이브러리를 사용가능하다!

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
빌드스크립트 코드 자체가 외부 라이브러리를 필요로 할때
멀티 프로젝트 일 경우 루트 build.gradle에 선언하면
모든 하위 프로젝트 build.gradle에 반영된다.
 */
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath group: 'commons-codec', name: 'commons-codec', version: '1.2'
    }
}
 
import org.apache.*
 
task encode{
    doLast{
        Base64.Encoder encoder = Base64.getEncoder()
        println encoder.encode(variableTask.myProperty.getBytes())
    }
}
cs

 

태스크 수행 순서 제어

태스크의 수행 순서를 제어하는 방법이다.

 

1
2
3
4
5
6
7
8
9
task taskX{
    println 'taskX'
}
 
task taskY{
    println 'taskY'
}
 
taskX.mustRunAfter taskY
cs

 

If문을 이용한 태스크 생략

if문을 이용하여 특정 태스크를 생략할 수 있다.

 

1
2
3
4
5
6
7
8
9
task conditionTask{
    doLast{
        println 'conditinal Task'
    }
}
 
conditionTask.onlyIf{!project.hasProperty('skip')}
 
>gradle -q -Pskip conditionTask
cs

 

태스크 비활성화

태스크를 지우고 싶진 않고, 당장은 사용하지 않아도 추후에 사용될 수도 있다면 비활성화 기능을 사용해보아도 좋을 듯하다.

 

1
2
3
4
5
6
7
task disableTask{
    doLast{
        println 'disabled'
    }
}
 
disableTask.enabled=true
cs

 

 

여기까지 간단하게 Task를 작성하는 방법을 다루어봤다. 사실 반복문등을 사용하는 것도 가능하다. 많은 태스크 예제가 있지만, 여기까지 간단하게 gradle task 작성방법의 맛을 보았다.

posted by 여성게
:
Web/Gradle 2019. 10. 20. 21:03

 

이번 포스팅은 그래들을 이용한 자바 프로젝트 구성에 대해 다루어볼 것이다. 그래들로 자바 프로젝트를 초기화 하는 방법은 이전 포스팅에 있으니 참고 바란다.

 

2019/10/20 - [Web/Gradle] - Gradle - Gradle의 기본

 

Gradle - Gradle의 기본

이번 포스팅은 Gradle에 대한 기본을 다루어볼 것이다. 사실 Gradle이 뭔지 모르는 개발자는 거의 없을 것임으로, 자세한 설명은 하지 않을 것이다. Gradle은 빌드툴이다! (마치 Maven과 같은) Gradle 내부 프로..

coding-start.tistory.com

 

자바 타입으로 그래들 프로젝트를 생성하면 아래와 같은 기본 디렉토리 구조를 가진다.

 

src

    -main

       -java

    -test

       -java

 

그래들의 자바 플러그인의 Task 의존 관계는 아래 그림과 같다.

 

 

build를 실행하게 되면 compileJava와 test Task가 실행된다. 그런데 이전 단계 Task가 실패하면 다음 단계는 진행되지 않는다. 

 

-컴파일시 인코딩 오류가 날 경우

>gradle compileJava 

 

위와 같은 명령으로 컴파일 할때 인코딩 문제가 있다면 아래와 같이 옵션 값을 넣어준다.(build.gradle)

 

compileJava.options.encoding='UTF-8'

 

혹은 gradle.properties 파일에서 그래들의 jvmargs 환경변수로 값을 추가할 수도 있다.

 

org.gradle.jvmargs=-Dfile.encoding=UTF-8

 

 

-컴파일 단게에서 테스트 클래스들을 제외하는 방법

 

1
2
3
4
5
6
7
8
sourceSets{
    main{
        java{
            srcDirs = ['src','extraSrc']
            exclude 'test/*'
        }
    }
}
cs

 

컴파일 태스크가 완료되면 build 디렉토리에 컴파일된 클래스 파일들이 생겨난다. 그런데, 이전에 생성된 파일과 중복되지 않도록 파일을 삭제한 후에 컴파일해야 하는 경우가 있다. 이럴 때는 Clean Task를 사용한다. 해당 태스크를 이용하면 빌드한 결과물이 생성되는 build 디렉토리 내용 전체가 삭제된다. 또한, clean Task는 다른 Task와 조합해서 사용할 수 있다.

 

>gradle clean

 

위 명령을 실행하면 build 디렉토리가 삭제되는 것을 볼 수 있다.

 

-의존성 관리하기

자바는 JVM을 통해 운영체제에 독립적으로 동작하고, 라이브러리를 만들때에도 운영체제별로 만들지 않고 자바 런타임에 호환되도록 만들면 되므로 타 언어에 비해서 오픈소스나 라이브러리들이 많은 편이다. 그래들은 이러한 라이브러리들을 편리하게 관리할 수 있도록 지원한다.

 

1)자바 프로젝트의 라이브러리 스코프

개발을 진행할 때 대표적으로 세 가지의 작업(컴파일, 테스트, 실행)을 한다. 각 작업에서 사용되는 라이브러리가 매우 다양하다. 그래들에서는 사용하는 라이브러리가 중복되지 않도록 스코프를 지원한다. 자바 프로젝트에서 지원하는 스코프는 dependencies 명령으로 확인할 수 있다.

 

>gradle dependencies

 

스코프별로 포함된 라이브러리가 출력되는데, 주로 사용하는 스코프는 compile, testCompile, runtime이다.

 

스코프 Task 설명
compile compileJava 컴파일 시 포함해야 할 때
runtime - 실행시점에 포함해야 할 때
testCompile compileTestJava 테스트를 위한 컴파일 시 포함해야 할때
testRuntime test 테스트를 실행시킬 때

 

2)라이브러리 추가

 

1
2
3
4
5
6
7
8
9
10
11
12
dependencies {
    // This dependency is exported to consumers, that is to say found on their compile classpath.
    api 'org.apache.commons:commons-math3:3.6.1'
 
    // This dependency is used internally, and not exposed to consumers on their own compile classpath.
    implementation 'com.google.guava:guava:28.0-jre'
 
    // Use JUnit test framework
    testImplementation 'junit:junit:4.12'
 
    compile 'com.itextpdf:itextpdf:5.5.5'
}
cs

 

마지막에 compile scope로 라이브러리를 하나 추가하였다. 그리고 아래 Task를 실행하면 compile scope에 라이브러리가 추가된 것을 볼 수 있다.

 

>gradle dependencies

 

이제 컴파일 태스크를 실행하면 위의 의존 라이브러리를 내려받을 것이다.

 

3)패키징하기

Java 플러그인을 사용한 상태에서 build 명령을 사용하면 기본으로 JAR 형태로 팩킹된다. 그래들에서 JAR파일은 libs 디렉토리에 생성되며 기본값으로 설정되어 있다. JAR 파일은 두가지 형태가 있다.

 

  1. 실행하기 위한 형태로 배포하는 JAR
  2. 라이브러리로 사용하는 JAR

만약 라이브러리 용도로 사용하는 JAR라면 별도 설정할 것이 없지만, 이러한 JAR를 실행시키면 아래와 같은 예외 메시지가 나타날것이다.

 

"*.jar에 기본 Manifest 속성이 없습니다."

 

JAR를 gradle task로 실행시키기 위해서는 아래 설정을 build.gradle에 추가하고 run task를 수행하면 된다.

 

apply plugin: 'application'
mainClassName="package.classname"

 

>gradle run

 

gradle run 태스크를 수행하면 jar파일이 실행된다.

 

Maven 프로젝트를 Gradle 프로젝트로 변환

 

>gradle init --type pom

 

 

posted by 여성게
:
Web/Gradle 2019. 10. 20. 19:41

 

이번 포스팅은 Gradle에 대한 기본을 다루어볼 것이다. 사실 Gradle이 뭔지 모르는 개발자는 거의 없을 것임으로, 자세한 설명은 하지 않을 것이다. Gradle은 빌드툴이다! (마치 Maven과 같은)

 

Gradle 내부 프로젝트 인터페이스

Project

>final DEFAULT_BUILD_FILE

>DEFAULT_BUILD_DIR_NAME

>GRADLE_PROPERTIES

>SYSTEM_PROP_PREFIX

>Task task(String name, Closure configureClosure)

 

프로젝트 인터페이스는 그래들로 프로젝트를 설정하고 구성할 때 사용하는 파일로, 그래들 프로젝트를 논리적으로 표현하는 인터페이스이다. default_build_file 파일은 프로젝트 설정에 대한 정보를 담고 있으며, 값은 build.gradle로 정의되어 있다. 그래서 build.gradle 파일에서 빌드에 필요한 기본 설정을 하게 된다. default_build_dir_name은 빌드한 결과물(ex. jar,war..)이 저장되는 디렉토리이다. Maven에서는 target 디렉토리에 저장되는데, 그래들에서는 build 디렉토리에 저장된다. gradle_properties는 그래들에서 key/value 형태로 사용할 수 있는 프로퍼티파일에 대한 속성으로 그래들이 초기화되면 build.gradle 파일과 함께 생성되고 속성을 정의해서 사용할 수 있다. 프로퍼티 파일을 사용할 때 접두어가 SYSTEM_PROP인 이유는 SystemPropertiesHandler에서 프로퍼티 파일을 읽을 때 다른 속성값들과 구분하기 위해 SystemProp\\.(.*)")와 같은 형태를 사용하기 때문이다.

 

그래들 Task 인터페이스

Task

>TASK_NAME

>TASK_TYPE

>TASK_EDPENES_ON

>TASK_ACTION

>getProject(), getDependencies()

 

프로젝트는 Task 인터페이스를 가지고 있어서 Task는 프로젝트를 기준으로 실행된다. Task를 실행할 때 Task 인터페이스에서는 기본적으로 Task의 이름과 Task의 유형, Task의 의존성 여부, Task 액션 등을 속성으로 가지고 있다. 즉, Task 인터페이스를 Action을 가지고 있는 것이다.

 

Gradle Build Lifecycle

그래들은 크게 세 단계의 빌드 라이프 사이클을 가진다.

 

1)초기화(init)

그래들이 초기화될 때 settings.gradle과 build.gradle 파일의 상호작용을 통해서 build.gradle에 있는 프로젝트의 정보를 수집한다. settings.gradle 파일의 정보로 해당 프로젝트를 싱글 프로젝트로 구성할 것인지 멀티 프로젝트로 구성할 것인지 등을 결정하고 프로젝트의 인스턴스를 생성한다. 현재 작업 중인 루트 디렉토리에 settings.gradle 파일이 없으면 상위 디렉토리에 settings.gradle파일이 있는지 확인하고, 상위 디렉토리에도 존재하지 않는다면 해당 프로젝트를 싱글 프로젝트로 인식한다.

 

2)설정

프로젝트 인스턴스화가 끝나면 설정 정보가 프로젝트에 반영되는 단계이다.

 

3)실행

그래들은 이전 단계에서 구성된 Task의 부분집합을 이름으로 구분하고, 그 이름이 Gradle 명령에 전달되어 실행된다.

 

Gradle 설치

Mac OS 기준으로 설치가 진행되었음을 알려드립니다.

 

>brew install gradle

 

설치 끝!

 

빌드 초기화

그래들에는 빌드 초기화를 지원하는 명령이 있다. 또한 init 명령은 다섯 가지 타입을 지원한다.

 

  1. Basic
  2. Groovy-library
  3. Java-library
  4. Pom
  5. Scala-library

 

간단하게 Basic 타입으로 Gradle 프로젝트를 초기화해본다.

 

>gradle init --type basic

>Select build script DSL:

  1: Groovy

  2: Kotlin

>Enter selection (default: Groovy) [1..2] 1

>Project name(default:..) gradleBasic> gradle init --type basic

Select build script DSL:

  1: Groovy

  2: Kotlin

Enter selection (default: Groovy) [1..2] 1

Project name (default: gradleExam): gradleBasic

> Task :init

Get more help with your project: https://guides.gradle.org/creating-new-gradle-builds

BUILD SUCCESSFUL in 16s

2 actionable tasks: 2 executed

 

그래들 초기화가 완료되었다. 생성된 디렉토리를 살펴보면, 아래와 같은 파일들이 존재한다.

 

  1. build.gradle
  2. gradle
  3. gradlew
  4. gradlew.bat
  5. settings.gradle

대부분 설명한 파일들이며 추후에 자세히 다루어볼 것이고, 설명하지 않은 gradlew,gradlew.bat, gradle 디렉토리가 있을 것이다. 우선 gradlew는 그래들을 설치하지 않아도 사용할 수 있게하는 Wrapping된 명령이다. gradle 디렉토리에 들어가면 Wrapper를 이용하여 그래들을 사용할 수 있게 하는 파일들이 존재한다. 다음은 자바 프로젝트로 초기화하는 그래들 초기화 명령이다.

 

> gradle init --type java-library

 

Select build script DSL:

  1: Groovy

  2: Kotlin

Enter selection (default: Groovy) [1..2] 1

Select test framework:

  1: JUnit 4

  2: TestNG

  3: Spock

  4: JUnit Jupiter

Enter selection (default: JUnit 4) [1..4] 1

Project name (default: gradle): gradleJava

Source package (default: gradleJava): com.java.gradle

> Task :init

Get more help with your project: https://docs.gradle.org/5.6.3/userguide/java_library_plugin.html

BUILD SUCCESSFUL in 18s

2 actionable tasks: 2 executed

 

생성된 build.gradle을 살펴보자.

 

 

간단히 설정을 설명하자면, 그래들은 외부 저장소를 설정할 수 있다. 일반적으로 url로 다운로드 경로를 적지만, 위와 같이 jcenter() 혹은 mavenCentral() 메서드로 대체할 수 있다. 라이브러리를 사용할 때는 dependencies 블록 안에 라이브러리 그룹명과 패키지명, 버전을 

"그룹:라이브러리:버전" 형식으로 입력한다.

 

사용자 정의 Task 만들기

이번에는 init 명령으로 생성한 build.gradle 파일을 편집해서 그래들 Task를 만든다. 다음은 "Gradle Hello"을 출력하는 Task이다.

 

task hello {

        println 'Gradle Hello'

}

 

그래들에서 Task를 만들 때는 'task Task명'을 입력한다. 스크립트를 사용할 때 'function 함수명'을 입력하는 것과 유사하다. Task를 만들면 Task 목록에 등록되며 gradle tasks명령으로 확인할 수 있다. 사용자가 정의한 Task는 Other tasks에 표시된다. task를 실행해보자.

 

>gradle hello

 

> Configure project :

Gradle Hello

BUILD SUCCESSFUL in 588ms

 

실행 결과에는 println 메서드로 출력한 문자열이 표시된다.

 

Task 실행 순서 제어하기

 

task cellphone{

        description = 'Display calling message'

        doLast{

                println '통화하기'

        }

        doFirst{

                println '전화걸기'

        }

        doLast{

                println '전화끊기'

        }

}

 

> gradle cellphone

 

> Task :cellphone

전화걸기

통화하기

전화끊기

 

결과를 보면 doFirst 태스크가 먼저 실행된 것을 볼 수 있다. 나머지는 정의된 순서대로 수행되었다. 이렇게 선행관계를 줄 수도 있다. 다음은 디폴트 Task를 지정하는 방법이다.

 

디폴트 Task 지정

그래들에서는 기본으로 실행해야 하는 Task를 디폴트로 지정할 수 있다. 지금까지는 그래들을 실행할 때 'cellphone'과 같은 Task의 이름을 파라미터로 지정하였지만, Task를 디폴트로 지정하면 'gradle'만 입력해도 실행할 수 있다.

 

defaultTasks 'defaultTask'

 

task defaultTask{

        println 'Default Task Run !'

}

 

> gradle cellphone

> Configure project :

Default Task Run !

> Task :cellphone

전화걸기

통화하기

전화끊기

BUILD SUCCESSFUL in 721ms

1 actionable task: 1 executed

=========================

> gradle

> Configure project :

Default Task Run !

BUILD SUCCESSFUL in 537ms

 

특정 태스트를 실행하던, 특정 태스크 이름을 넘기지 않아도 디폴트 Task는 항상 실행되는 것을 볼 수 있다.

 

Task 의존성 설정

Task가 실행될 때 다른 Task도 함께 실행하려면 'depends On'으로 의존관계를 설정하면 된다.

 

task cellphone(dependsOn:'dependTask'){

        description = 'Display calling message'

        doLast{

                println '통화하기'

        }

        doFirst{

                println '전화걸기'

        }

        doLast{

                println '전화끊기'

        }

}

task dependTask{

        println 'Depends On Task'

}

 

여기까지 간단하게 그래들 초기화방법과 태스크를 정의해 실행해보았다. 다음 포스팅은 자바 프로젝트에 초점에 맞춰 더 다양하게 그래들 예제를 다루어볼 것이다.

posted by 여성게
: