sourceCompatibility vs. targetCompatibility
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