안드로이드

Version Catalog 도입기 (3)

최효식 2024. 3. 30. 23:12

이제 마지막으로 Convention 모듈을 만들어 커스텀 플러그인 설정을 하는 방법을 설명 하겠습니다.

 

예를 들어 모듈별로 필요한 플러그인 들을 여러개 추가 할 때 마다 build.gradle에 중복 코드가 많아지는데 커스텀 플러그인 을 통해서 효과적으로 관리를 할 수 있게 됩니다.

 

 

1. build-logic 모듈을 생성하고 settings.gradle.kts 만 남겨 놓습니다.

 

 

2. build-logic 모듈 안에 convention 모듈을 생성 합니다.

 

 

 

3. root 디렉토리의 setting.gradle 에서 build-logic , convention 모듈을 지웁니다.

pluginManagement {
    includeBuild("build-logic") // 필수
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }

}
rootProject.name = "LedBillboard"
include ':app'

 

 

4. build-logic 의 settings.gradle 에 versionCatalog 에 대해 명시합니다.

 

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }

    versionCatalogs {
        create("libs") {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}

rootProject.name = "build-logic"
include(":convention")

 

 

5. convention module 안의 패키지에서 Android Kotlin 과 Compose 세팅을 도와주는 확장 함수를 만들어 줍니다.

 

  • Android kotlin 관련
internal fun Project.configureKotlinAndroid(
    commonExtension: CommonExtension<*, *, *, *>,
) {
    commonExtension.apply {
        compileSdk = 34

        defaultConfig {
            minSdk = 24

            testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
            vectorDrawables.useSupportLibrary = true
        }

        compileOptions {
            sourceCompatibility = JavaVersion.VERSION_11
            targetCompatibility = JavaVersion.VERSION_11
        }

        kotlinOptions {
            jvmTarget = JavaVersion.VERSION_11.toString()
        }
    }
}

fun CommonExtension<*, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) {
    (this as ExtensionAware).extensions.configure("kotlinOptions", block)
}

 

  • Android compose 관련
internal fun Project.configureAndroidCompose(
    commonExtension: CommonExtension<*, *, *, *>,
) {
    val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")

    commonExtension.apply {
        buildFeatures.compose = true

        composeOptions {
            kotlinCompilerExtensionVersion =  libs.findVersion("composeCompiler").get().toString()
        }
    }

    dependencies {
        // Disabling to work with Alpha
//        "api"(platform(libs.findLibrary("compose.bom").get()))
        "implementation"(libs.findBundle("androidX-compose").get())
        "debugImplementation"(libs.findBundle("androidX-compose-debug").get())
    }
}

 

 

6. Plugin 클래스를 생성하여 위에서 정의한 확장함수를 이용하여 커스텀 plugin 을 만듭니다.

 

  • AndroidApplicationConventionPlugin
import com.android.build.api.dsl.ApplicationExtension
import com.example.ledbillboard.configureKotlinAndroid
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure

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)

                buildTypes {
                    release {
                        isMinifyEnabled = false
                        proguardFiles ("proguard-rules.pro")
                    }
                }

                packagingOptions {
                    resources {
                        excludes.add("/META-INF/{AL2.0,LGPL2.1}")
                    }
                }

            }
        }
    }
}

 

 

  • AndroidApplicationComposeConventionPlugin
import com.android.build.gradle.internal.dsl.BaseAppModuleExtension
import com.example.ledbillboard.configureAndroidCompose
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.getByType

class AndroidApplicationComposeConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            pluginManager.apply("com.android.application")
            val extension = extensions.getByType<BaseAppModuleExtension>()
            configureAndroidCompose(extension)
        }
    }
}

 

 

7. convention 모듈의 build.gradle.kts 에 gradlePlugin 을 세팅 해줍니다.

 

plugins {
    `kotlin-dsl`
}

group = "com.example.ledbillboard.buildlogic"

java {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
}

dependencies {
    compileOnly(libs.android.gradlePlugin)
    compileOnly(libs.kotlin.gradlePlugin)
//    compileOnly(libs.ksp.gradlePlugin)
}

gradlePlugin {
    plugins {
        register("AndroidApplicationPlugin") {
            id = "hyosik.plugin.application"
            implementationClass = "AndroidApplicationConventionPlugin"
        }
        register("AndroidApplicationComposePlugin") {
            id = "hyosik.plugin.application.compose"
            implementationClass = "AndroidApplicationComposeConventionPlugin"
        }
    }
}

 

 

8. 마지막으로 gradlePlugin 에 있는 register id 값을 다른 모듈에서 plugin 으로 추가를 하면 됩니다.

 

plugins {
    id("hyosik.plugin.application")
    id("hyosik.plugin.application.compose")
}

apply {
    from(rootProject.file("android.gradle"))
}

dependencies {

    implementation (libs.androidX.core.ktx)
    implementation (libs.androidX.lifecycle.runtimeTesting)
    implementation (libs.androidX.activity.compose)
    testImplementation (libs.junit)
    androidTestImplementation (libs.androidX.test.junit)
    androidTestImplementation (libs.androidX.test.espresso)
    androidTestImplementation (libs.androidX.compose.uiTestJunit)
    debugImplementation (libs.androidX.compose.tooling)
    debugImplementation (libs.androidX.compose.uiTestManifest)

}

 

 

 

build- logic 및 convention 모듈의 구조는 이렇게 나옵니다.

 

 

 

현재 저는 Application Plugin 과 Library Plugin 두가지를 만든 상황이고 앞으로 hilt 관련 Plugin 도 만들 생각입니다.

 

그럼 여기까지 Version Catalog 및 Convention Plugin 을 도입했던 경험이었습니다.