gradle

3. Android Gradle Plugin Extend해보기

리워크 2022. 10. 23. 01:31

이전 글에서 Plugin이 무엇인지 알아보고 이를 Script로 관리하는 방법이 아닌 객체로 저장하여 관리하는 방법에 대해서 간략하게 알아보았다.

 

Android Gradle Plugin을 사용한다는 것은 말 그대로 해당 클라이언트를 위해서 구축된 Build Task모델을 가지고와서 사용한다는 말이다.

 

다른 Plugin이 환경설정을 위해서 Extension을 제공하고 있다는 것을 알고있다.

 

Android에서도 이런 Extension을 제공하고있으며, 아래의 두 페이지에서 확인할 수 있다.(나는 위에꺼가 더 좋음)

 

https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-master-dev:build-system/gradle-core/src/main/java/com/android/build/gradle/BaseExtension.kt 

 

https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-master-dev:build-system/gradle-core/src/main/java/com/android/build/gradle/BaseExtension.kt

 

cs.android.com

https://google.github.io/android-gradle-dsl/3.3/com.android.build.gradle.AppExtension.html#com.android.build.gradle.AppExtension:compileSdkVersion

 

AppExtension - Android Plugin 3.3.0 DSL Reference

The android extension for application plugins. For the base module, see BaseExtension For optional apks, this class is used directly. MethodDescriptionflavorDimensions(dimensions)Specifies the names of product flavor dimensions for this project. useLibrary

google.github.io

 

 

BaseExtension을 파생시켜서 각 필요한 Application, Library등의 Module이 적용시킬 Extension이 나누어져 있으며

com.android.application의 경우는 ApplicationExtension을 사용하여 환경설정을 하면된다.

 

NowInAndroid코드를 확인해보면, 여기서는 ApplicationExtension을 사용하기보다 BaseAppModuleExtension을 사용하고있으며 그 이유는 나도 아직 잘 몰라서 나중에 좀 더 알게되면 다시 써보겠음...

 

나는 그냥 ApplicationExtension을 쓰겠음..

 

그럼 처음 생성한 App모듈의 Build.Gradle을 Plugin 객체로 묶어보자 

 

새로 생성한 App의 Build.Gradle을 2편에서 설명했던 방식으로 Plugin객체를 구성하자면 아래와 같다.

 

1. Build-Logic의 Build.Gradle에 Dependency추가

 

다만 ApplicationExtension을 사용하려면 또 Dependency를 통해서 라이브러리를 사용할 수 있어야하므로 아래의 Dependency추가가 필요하다.

dependencies{
    implementation("com.android.tools.build:gradle:7.3.1")
    implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10")
}

 

2. Plugin객체 구현

 

 

아래의 객체들은 Plugin임..

class AndroidComposePlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target){
            pluginManager.apply("com.android.application")

            extensions.configure<ApplicationExtension>{
                androidComposeConfig(this)
            }
        }
    }
}

class AndroidBasicAppPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target){

            pluginManager.apply("com.android.application")
            pluginManager.apply("org.jetbrains.kotlin.android")


            extensions.configure<ApplicationExtension>{
                kotlinAndroidConfig(this)
                defaultConfig.targetSdk = 33
            }
        }
    }

}

internal fun Project.androidComposeConfig(
    commonExtension: CommonExtension<*,*,*,*>
)
{
//        val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")

        commonExtension.apply {
            buildFeatures {
                compose = true
            }

            composeOptions {
                kotlinCompilerExtensionVersion = "1.3.2"
            }
        }
}

internal fun Project.kotlinAndroidConfig(
    commonExtension: CommonExtension<*,*,*,*>
) {
    commonExtension.apply {
        compileSdk = 33

        defaultConfig {
            minSdk = 21
        }

        compileOptions {
            sourceCompatibility = JavaVersion.VERSION_1_8
            targetCompatibility = JavaVersion.VERSION_1_8
//            isCoreLibraryDesugaringEnabled = true
        }

        kotlinOptions {
            // Treat all Kotlin warnings as errors (disabled by default)
            // Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties
            val warningsAsErrors: String? by project
            allWarningsAsErrors = warningsAsErrors.toBoolean()

            freeCompilerArgs = freeCompilerArgs + listOf(
                "-opt-in=kotlin.RequiresOptIn",
                // Enable experimental coroutines APIs, including Flow
                "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
                "-opt-in=kotlinx.coroutines.FlowPreview",
                "-opt-in=kotlin.Experimental",
                // Enable experimental kotlinx serialization APIs
                "-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
            )

            // Set JVM target to 1.8
            jvmTarget = JavaVersion.VERSION_1_8.toString()
        }


    }
}

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

위처럼 생성한 객체를 Gradle을 통해서 ID를 설정해보고 위의 Plugin을 적용시키면 잘 동작하는 것을 확인할 수 있다.

 

3. Build-Logic의 Build.Gradle에 Plugin정의하고 App의 Gradle에 적용

 

gradlePlugin{
    plugins{
        create("androidComposePlugin"){
            id = "com.vlm.android.compose"
            implementationClass = "AndroidComposePlugin"
        }
    }

    plugins{
        create("androidBasicAppPlugin"){
            id = "com.vlm.android.application"
            implementationClass = "AndroidBasicAppPlugin"
        }
    }
}