이전 글에서 언급했든 우리는 안드로이드를 개발하면서 계속 plugin을 사용해 왔다.
안드로이드의 Gradle Plugin은 쉽게 말해 Gradle의 작업(Task)들을 묶어둔 하나의 작업 단위 이다. 애플리케이션의 빌드과정을 관리하고 필요한 Task를 정의해 주어 관련된 복잡한 작업을 손쉽게 처리할 수 있도록 도와준다.
구체적으로 Gradle에 관한 글은 나중에 추가로 작성하도록하겠다.
모듈에 특정한 컨벤션을 적용하는 플러그인
앞선 글로 version catalog를 사용해 dependency의 버전을 일괄적으로 관리하는 방법을 알아보았다.
Convention Plugin은 여기서 한발 더 나아가 각 모듈에서 공통된 빌드 구성을 뽑아내고 이를 재사용할 수 있도록 구성하는 방법이다.
이러한 방식은 다음과 같은 이점을 가질 수 있다.
build-logic:convention모듈을 Java or Kotlin Library로 생성한다.
그리고 convention안의 build.gradle.kts 파일을 다음과 같이 선언한다.
plugins {
`kotlin-dsl`
}
group = "com.sixkids.ulban.buildlogic"
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
dependencies{
compileOnly(libs.android.gradle.plugin)
compileOnly(libs.kotlin.gradle.plugin)
}
컴파일 시점에만 필요한 내용을 compileOnly로 선언해 준다고 한다(사실 여기에 구체적으로 어떤 것들이 들어가야하는지 좀더 확인해 볼 필요가 있다.)
이후 build-logic의 하위에 settings.gradle.kts 파일을 생성하고 다음과 같이 작성한다.
//settings.gradle.kts
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
rootProject.name = "build-logic"
include(":convention")
마지막으로 프로젝트 root의 settings.gradle.kts에서 자동으로 생성된
include(":build-logic")과 include(":build-logic:convention")를 지워줘고 pluginManagement에 includeBuild("build-logic")을 넣어준다.
pluginManagement {
repositories {
...
includeBuild("build-logic")
}
}
...
include(":app")
include(":domain")
include(":data")
//include(":build-logic") 제거
//include(":build-logic:convention") 제거
Const.kt
object Const {
const val COMPILE_SDK = 34
const val MIN_SDK = 26
const val TARGET_SDK = 34
val JAVA_VERSION = JavaVersion.VERSION_17
}
//KotlinAndorid.kt
internal fun Project.configureKotlinAndroid(
commonExtension: CommonExtension<*, *, *, *, *, *>,
){
commonExtension.apply {
compileSdk = Const.COMPILE_SDK
defaultConfig {
minSdk = Const.MIN_SDK
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables{
useSupportLibrary = true
}
}
buildTypes {
named("release"){
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = Const.JAVA_VERSION
targetCompatibility = Const.JAVA_VERSION
}
kotlinOptions {
jvmTarget = Const.JAVA_VERSION.toString()
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
}
internal fun CommonExtension<*, *, *, *, *, *>.kotlinOptions(
block: KotlinJvmOptions.() -> Unit
){
(this as ExtensionAware).extensions.configure("kotlinOptions", block)
}
공통으로 사용되는 gradle의 속성값들을 뽑아내어 확장 함수로 선언한다.
//AndroidApplicationConventionPlugin.kt
@Suppress("unused")
internal class AndroidApplicationConventionPlugin : Plugin<Project>{
override fun apply(target: Project) {
with(target){
with(pluginManager){
apply("com.android.application")
apply("org.jetbrains.kotlin.android")
}
extensions.configure<ApplicationExtension>{
configureKotlinAndroid(this)
defaultConfig.targetSdk = Const.TARGET_SDK
}
}
}
}
프로젝트에 맞게 컨벤션을 생성하면 된다.
build-logic:convention 모듈의 build.gradle.kts 파일에 새로 생성한 컨벤션을 등록해 준다.
gradlePlugin {
plugins {
register("androidApplication"){
id="sixkids.android.application"
implementationClass = "AndroidApplicationConventionPlugin"
}
}
}
이제 version catalog와 함께 플러그인을 사용 할 수 있다.
[plugins]
sixkids-android-application = { id = "sixkids.android.application", version = "unspecified" }
직접 만든 플러그인을 등록하고 원하는 모듈에서 해당 플러그인을 불러와 사용할 수 있다.
plugins{
...
alias(libs.plugins.sixkids.android.application)
}
따봉박고 갑니다