Plugin에 대한 기본적인 설명은 앞에서 진행하였다.
1. AGP란
AGP(Android Gradle Plugin)는 안드로이드 앱의 빌드 및 배포 과정을 관리하는데 사용되는 다양한 플러그인(빌드, 테스트, 배포 등)을 포함하는 플러그인이고, AGP의 내용을 아래의 build-system프로젝트에서 관리한다.
안드로이드 스튜디오를 사용하는 입장에서, 해당 프로젝트는 Android Studio 프로젝트 안에 포함되어 관리하고 있어 특별한 등록 절차없이 간단하게 우리는 AGP를 사용할 수 있다(어떤식으로 받아오고 적용하는지는 모름)
Android Code Search에 AGP와 관련된 코드를 어디서 확인할 수 있는지 알아보자
platform/tools/base - Android Code Search
위 사이트를 들어가면, Tools/Base를 rootProject로하여 기본적인 설명과 함께 structure을 확인할 수 있다.
이 중 우리가 눈여겨 보아야 할 것은 build-system이다.
build-system - Android Code Search
2. com.android.application
Build-system은 나에게 익숙하지 않은 구조를 가지고 있는데,
Build-system/gradle-core, Build-system/gradle-api 둘 사이의 종속성 관리가 Bazel에 의해서 내가 아는 Gradle종속성 관리와 다르게 이루어 지고 있다.
특히, gradle-api모듈이 gradle-core모듈을 dependencies에 명시하지 않았지만, gradle-core에 정의한 com.android.build.gradle.internal.plugins.AppPlugin를 사용할 수 있는게 의아하다(아마 Bazel을 공부해야 이 부분은 해결될 것 같다)
com.android.application은 우리가 안드로이드 앱을 만들때 항상 plugin으로 추가하는 항목이다.
다른 com.android.library도 있겠지만, application extension을 많이 사용하니 이를 위주로 알아본다.
이는 platform/tools/base/build-system/gradle-core/build.gradle에 정의되어있다(build-system 앞쪽은 생략하겠음)
해당 build.gradle에는 아래와 같이 플러그인과 dependencies가 정의되어 있는데
//build-system/gradle-core/build.gradle
plugins {
id 'java-gradle-plugin' //(1)
...
}
gradlePlugin {
plugins { //(2)
comAndroidApplication {
id = "com.android.application"
implementationClass = "com.android.build.gradle.AppPlugin"
}
...
}
dependencies {
api project(':base:gradle-api') //(3)
...
}
(1) 'java-gradle-plugin' 해당 플러그인을 사용하면 정의하는 plugin을 자동으로 META-INF디렉토리에 정의해준다.
보통 위의 (2)같이 build.gradle에서 커스텀 플러그인을 정의해줘야 하지만, (1)을 사용하면 build.gradle에서 따로 정의하지 않아도 자동적으로 ID가 생성되며 타 커스텀 플러그인처럼 사용할 수 있다는 뜻이다.
다만, 추가적인 설명이 필요하다면 (2)처럼 plugins블럭을 사용해야한다.
(2) 안드로이드 앱에 추가하는 com.android.application 플러그인의 정체다.
com.android.build.gradle.AppPlugin을 확인해야하는데 이는 (3)gradle-api모듈에 포함되어 있다.
//build-system/gradle-api/src/main/java/com/android/build/gradle/AppPlugin.kt
class AppPlugin: BasePlugin() {
override fun apply(project: Project) {
super.apply(project)
project.apply(INTERNAL_PLUGIN_ID)
}
}
private val INTERNAL_PLUGIN_ID = mapOf("plugin" to "com.android.internal.application")
AppPlugin에 적용되는 INTERNAL_PLUGIN_ID의 com.android.internal.application 플러그인은
gradle-api모듈이 아닌 아래 경로와 같이 gradle-core모듈에 정의되어 있다.
하지만 모든 모듈을 뒤져보더라도 build.gradle에 com.android.internal.application으로 ID를 지정한 Plugin은 찾아볼 수 없다.
이는gradle-core의
build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AppPlugin.java
위 경로에 생성한 Plugin이
gradle-core/build.gradle에 적용된 (1)에 의해 자동적으로 아래와 같은 파일이 생성, 이를 gradle-api에서 사용한 것이다.
//build-system/gradle-core/src/main/resources/META-INF/gradle-plugins/com.android.internal.application.properties
implementation-class=com.android.build.gradle.internal.plugins.AppPlugin
(3) API 설정
추후에 Dependency에 대해서 알아볼거지만, 현재의 모듈(A)이 API로 가져온 모듈(B) 내용을 포함하게 하여, A모듈을 종속성 추가한 다른 C모듈은 직접 B모듈을 추가하지 않더라도 B모듈을 사용할 수 있도록 한다.
3. Extension?
앞의 내용은 사실 우리가 직접 사용할 Extension을 사용하기 위해 설명한 내용이다.
아래와 같은 형태를 Gradle파일에서 볼 수 있는데,
여기의 Android블럭이 com.android.application이 제공하는 Extension이다.
즉 Application의 환경설정을 이러한 Extension으로 사용자에게 설정할 수 있도록 해준다.
예전에 Gradle Plugins에 Extenstion을 만드는 과정을 따라해 본 경험이 있는데()
Extension은 Plugin이 어떻게 동작할지 환경설정을 할 수 있도록 만들어주는 설정 객체이다.
간단한 예로, 우리가 Android App을 빌들하기 위해 com.android.application을 plugins를 활용하여 가져오지만, 해당 플러그인을 활용하면서 compile SDK나 applicationId등은 각 프로젝트마다 다르고, 이를 plugins를 가져와서 활용하는 사람에게 설정하도록 결정권을 넘겨준다.
Extension을 정의하는 과정은
1) interface로 Extension 설정 객체를 정의한다.
2) Extension을 적용할 수 있는 Plugin에, 만든 Extension을 적용한다
안드로이드에서 사용하는 Extension도 위와 같은 과정을 거져 적용한다.
1) Extension 생성(baseExtension, applicationExtension 등)
해당 파일의 경로는 아래와 같다
build-system/gradle-api/src/main/java/com/android/build/api/dsl/ApplicationExtension.kt
build-system/gradle-api/src/main/java/com/android/build/api/dsl/CommonExtension.kt
2) Extension을 AppPlugin에 적용
해당 코드는 너무 복잡해서 이해는 잘 안가지만 아래와 같이 getExtensions().create()~에서 android 블럭을 사용할 수 있는 extension을 적용하고 있다.
project.getExtensions().create(
new TypeOf<>() {},
"android", instanceType,dslServices,bootClasspathConfig,
buildOutputs,dslContainers.getSourceSetManager(),extraModelInfo,
applicationExtension,stats
);
여기에 ApplicationExtension의 구현체를 보면
interface ApplicationExtension :
CommonExtension<
ApplicationBuildFeatures,
ApplicationBuildType,
ApplicationDefaultConfig,
ApplicationProductFlavor,
ApplicationAndroidResources,
ApplicationInstallation>,
ApkExtension,
TestedExtension {
val dependenciesInfo: DependenciesInfo
fun dependenciesInfo(action: DependenciesInfo.() -> Unit)
val bundle: Bundle
fun bundle(action: Bundle.() -> Unit)
val dynamicFeatures: MutableSet<String>
val assetPacks: MutableSet<String>
val publishing: ApplicationPublishing
fun publishing(action: ApplicationPublishing.() -> Unit)
override val androidResources: ApplicationAndroidResources
override val installation: ApplicationInstallation
val privacySandbox: PrivacySandbox
fun privacySandbox(action: PrivacySandbox.() -> Unit)
}
위와 같이 지정할 수 있는 val과 dsl로 정의할 수 있도록 fun이 같은 이름으로 정의되어 있다.
그리고 각각의 기능은 android블럭에서 불러 사용할 수 있다.
우리가 익숙한 compileSDK 등의 환경설정은 눈에 보이지 않는데, 이는 CommonExtension에 포함되어 있다.
다음으로는 Extension을 활용하여, 안드로이드에서 바이너르 플러그인을 정의하는 방법을 알아보겠다.
CommonExtension.kt - Android Code Search
'gradle' 카테고리의 다른 글
3. Gradle Plugin 알아보기 (0) | 2024.08.22 |
---|---|
2. Gradle의 TASK 이해하기 (0) | 2024.08.16 |
1. Gradle이 무엇이고, 왜 쓰는가? (0) | 2024.08.16 |
3. Android Gradle Plugin Extend해보기 (0) | 2022.10.23 |
2. Gradle의 Plugin (0) | 2022.10.21 |