이동식 저장소

sourceCompatibility vs. targetCompatibility 본문

Secondary/Gradle

sourceCompatibility vs. targetCompatibility

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

App level build.gradle 파일에는 sourceCompatibilitytargetCompatibility라는 속성이 정의되어 있다. 

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에서 실행할 수 없다는 뜻이니까. 하지만 불가능한 설정은 아니다.

 

하지만 sourceCompatibilitytargetCompatibility보다 높을 수는 없다. 상식적으로 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