이동식 저장소

sourceCompatibility vs. targetCompatibility 본문

Secondary/Gradle

sourceCompatibility vs. targetCompatibility

해스끼 2023. 3. 24. 21:39

App level ``build.gradle`` 파일에는 ``sourceCompatibility``와 ``targetCompatibility``라는 속성이 정의되어 있다. 

android {
    ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

이 속성들이 무엇을 의미하는지 공부해 보자.

sourceCompatibility

코드를 컴파일할 때 사용할 Java 버전을 의미한다. 예를 들어 ``sourceCompatibility``를 1.8로 설정하면, Java 1.8 이후 버전의 기능은 사용할 수 없다. 소스 코드에서 사용할 Java 버전이라고 기억해도 좋다.

targetCompatibility

만들어진 바이트코드가 실행될 수 있는 JVM 버전의 최솟값을 의미한다. ``targetCompatibility``가 1.8이라면 컴파일된 바이트코드는 JVM 1.8 이상 버전에서만 실행될 수 있다.

반드시 같아야 하는가?

그럴 필요는 없다. 코드에서 사용 가능한 기능과 바이트코드의 버전 사이에는 딱히 상관관계가 없기 때문이다. ``sourceCompatibility``를 1.8로, ``targetCompatibility``를 11로 설정할 수도 있다. 이렇게 하면 코드에서는 Java 1.8까지의 기능만을 사용할 수 있고, 만들어진 바이트코드는 JVM 11 이상에서만 실행될 수 있다. 

 

조금 이상한 설정이긴 하다. 1.8의 기능만을 사용하여 컴파일된 바이트코드를 정작 JVM 1.8에서 실행할 수 없다는 뜻이니까. 하지만 불가능한 설정은 아니다.

 

하지만 ``sourceCompatibility``가 ``targetCompatibility``보다 높을 수는 없다. 상식적으로 Java 11을 기반으로 컴파일된 바이트코드를 JVM 1.8에서 실행할 수는 없지 않겠는가?

compileOptions {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_1_8
}
* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> warning: source release 11 requires target release 11

JDK 버전과 반드시 같아야 하는가?

그럴 필요는 없다. JDK 버전보다 같거나 작은 값을 사용하면 된다. 왜 이게 가능한지는 글을 충분히 읽었다면 알 것이라 생각한다.

참고문헌

 

The Java Plugin

If a dependent project has changed in an ABI-compatible way (only its private API has changed), then Java compilation tasks will be up-to-date. This means that if project A depends on project B and a class in B is changed in an ABI-compatible way (typicall

docs.gradle.org

 

Comments