[요약] Make your build faster and more robust with the latest Android Gradle plugin (Android Dev Summit '21)

[요약] Make your build faster and more robust with the latest Android Gradle plugin (Android Dev Summit '21)

Oct 31, 2021. | By: pluulove

Performance improvements

KSP

  • KAPT를 대체하는 Kotlin 용 Annotation Processor
  • KAPT 대비 최대 2배 이상 빠르게 실행 → 빌드 속도 향상
  • Room, Moshi 등에서 사용 중

non-transitive R classes

  • R class에는 해당 프로젝트에 선언된 리소스만 포함되고, 종속성에는 포함되지 않음으로 R 클래스의 크기가 줄어든다
  • Refactor > Migrate to Non-transitive R Classes로 실행할 수 있다
  • 새로운 모듈을 추가할 때 유용하며 활성화 시 40% 증분 시나리오의 향상이 있다
  • Clean Build는 5 ~ 10% 개선
  • Arctic Fox에서도 사용할 수 있다
  • 이미 AndroidX 라이브러리에서는 사용 중
# gradle.properties
android.nonTransitiveRClass=true

Lint

  • checkDependencies가 true로 설정되면 Lint 분석 작업을 모듈별로 병렬로 실행한다
  • AGP 7.1 alpha-13부터 Lint 분석 작업은 Gradle 빌드 캐시와 호환된다

  • AGP 4.2대비 약 2배의 성능 향상되었으며, AGP 7.1에서 훨씬 극적인 개선이 이루어짐
# gradle.properties
org.gradle.caching=true

일반적인 개선 사항

  • Gradle 빌드 캐시를 활성화하기 위해서 gradle.properties에 플래그를 추가해야 한다
  • Lint에 충분한 메모리가 할당되었는지 확인해야 한다
    • https://googlesamples.github.io/android-custom-lint-rules/user-guide.html#performancetuning
  • application module에 lintOptions 블록에 checkDependencies를 true로 설정해야 한다.
    • Lint가 더 빠르게 실행되지 않지만, 많은 문제를 포착할 수 있다
    • 단일 Lint 보고서를 생성한다

Configuration cache

  • 빌드가 시작될 때 Gradle은 빌드 작업을 실행하는 데 사용되는 작업 그래프를 생성한다

  • 구성 단계를 호출할 경우 몇 초에서 수십 초까지 걸릴 수 있다
  • Configuration cache는 Build Configuration 단계의 출력을 캐싱 후 재사용하는 Gradle 기능이다
    • 모든 작업이 병렬로 실행

  • 최신 Kotlin, Gradle, AGP를 사용하는 24개의 하위 프로젝트에서는 Clean Build, public 메소드를 추가하는 증분 빌드, 메소드 본문을 수정하는 증분 빌드 모두 빌드 속도가 20% 향상되었다

  • Gradle의 모든 작업이 완전히 구성되면 Gradle은 최종 task 그래프를 계산한다
  • Configuration cache는 이 작업 그래프를 저장하고 task 상태를 직렬화하여 캐시에 저장한다

  • Configuration cache 재사용이 가능한 경우, 저장된 Configuration cache 항목을 사용하여 task 인스턴스를 생성한다

  • 빌드가 Configuration cache와 호환되는지 확인하기 위해 Arctic Fox에서 Build Analyzer에 관련 항목이 추가되었다.
  • 현재 Builde configuration으로는 9.8초가 소요되었다.

  • Try Configuration cache in a build를 클릭하면, Gradle properties 파일이 업데이트되고, Configuration cache를 활성화하는 플래그가 추가된다
  • 빌드가 Configuration cache와 호환되지 않는 경우 빌드가 실패하고 디버깅 정보를 출력한다

Configuration cache와 비호환 사례

다음 예는 Configuration cache와 호횐되지 않는 사례이다.

  • git sha를 계산하고 파일에 출력하는 task에는 2가지 Configuration cache 문제가 있다
  • 첫 번째는 파일 출력 위치를 반환하는 함수(getOutputFile)에 프로젝트 작업이 있기 때문에 발생했다.
  • 두 번째는 task에서 프로젝트의 사용이다. 이것은 Configuration cache가 활성화된 상태에서 액세스할 수 없는 전역 단계이다.

Configuration cache와 호환 사례

  • task properties에 필요한 정보를 저장할 수 있다. 이것들이 Configuration cache에 저장된다
  • 외부 프로세스를 실행할 수 있는 Gradle inject service에 의존할 수도 있다
  • task 등록 중에 configuration 속성에 출력 위치를 캡처한다. 주입된 Gradle 서비스는 Git 명령을 실행하는 데 사용된다.

  • 실제 파일의 출력 위치는 task 등록 시 설정하도록 한다
  • Docs
    • Gradle documentation : https://docs.gradle.org/current/userguide/configuration_cache.html
    • Android Developers Blog post ~ Configuration caching deep dive : https://medium.com/androiddevelopers/configuration-caching-deep-dive-bcb304698070

Extending Android Gradle Plugin

Variant와 Artifact의 의미

  • AGP는 Build Type과 Flavor를 통해 variant 객체를 만들고, 각 variant 별 task를 생성한다. 이제 중간 Artifact 중 일부가 공개된다.

AGP 7.0부터는 아래 기능을 사용할 수 있다

  • 중간 artifact를 수정
  • DSL에 사용자 정의 요소 추가
  • Variant API에 사용자 정의 속성을 추가

sample : https://github.com/android/gradle-recipes/tree/agp-7.1/BuildSrc/toyPluginAds2021

  • 다음 예제는 Artifact를 수정하여 APK에 Asset를 추가하는 Task이다
  • 단일 문자열 입력과 단일 디렉토리 속성 출력이 있으며, 디렉터리의 파일 작성에 쓰인다

  • Variant/Artifact API를 사용하여 AddAssetTask를 등록하고 Artifact에 연결한다
  • APK에 추가 Asset를 처리하는데 필요한 것은 위 코드가 전부이다
variant.artifacts
    .use(taskProvider)
    .wiredWith(AddAssetTask::outputDir)
    .toAppendTo(MultipleArtifact.ASSETS)
  • Task의 출력 디렉토리를 Asset 디렉토리에 추가하고 Task 종속성을 적절히 연결한다

  • 여러 다른 중간 Artifact와 상호 작용할 수 있으며 그중 일부는 여기에 표시된다
  • AGP는 이전 예제와 다른 방법으로도 Artifact와의 상호 작용을 지원한다

추가 자료는 New APIs in the Android Gradle Plugin(https://medium.com/androiddevelopers/new-apis-in-the-android-gradle-plugin-f5325742e614) 를 참고

Custom DSL API

  • 추가 Asset의 콘텐츠를 설정하도록 DSL을 추가할 예정이다
  • 최근 AGP에서는 기존 DSL에 사용자 정의 plugin용 DSL을 추가하는 기능을 추가했다. Build Type 별로 Asset 콘텐츠를 설정할 수 있다.

  • 먼저 AGP의 DSL을 확장하려면 인터페이스가 필요하다

  • 생성한 인터페이스를 AGP의 BuildType DSL에 추가할 수 있다. Product flavors도 가능하다
  • onVariants 블록에서 해당 값을 가져와서 task의 입력으로 설정할 수 있다

Custom Variant API

DSL을 확장하는 것과 유사하게 자체 Gradle 속성 또는 공급자를 AGP의 변형 개체에 추가하여 변형 API를 확장할 수도 있습니다.

Variant API 확장 시 DSL 대비 얻는 이점

  • Task의 출력으로 설정 가능하며, Task 종속성은 Gradle에서 자동으로 처리
  • Variant 별 고유한 값을 쉽게 설정 가능
  • 다른 plugin과 쉽게 상호 작용이 가능

  • DSL 확장과 유사하게 인터페이스 생성이 필요하며, Provider를 사용한다
  • Task의 출력을 사용하여 값을 설정할 수 있다

  • build.gradle 파일에서 Variant API를 사용하여 각 Variant 별 고유 값 설정을 더 쉽게 할 수 있다

  • Plugin에서 Variant API를 사용할 경우, beforeVariant 블록에서 사용할 수 있다
  • 사용자 지정 Variant 인스턴스를 AGP의 Variant 객체에 Provider로 등록한다
  • onVariants블록에 Variant extension를 등록할 수 없다
  • onVariants 블록에서 액세스할 수 있는 모든 plugin에서 사용하려면 beforeVariants 블록에 등록해야 한다

  • onVariants에서는 각 Variant 별로 처리해야 하는 Gradle plugin이 있는 경우에 사용자 정의 Variant 속성을 추가하는 방법이다
  • Docs
    • Extending AGP : https://developer.android.com/studio/build/extend-agp
    • AGP Cookbook : https://github.com/android/gradle-recipes

  • Configuration cache 위에서 빌드 되는 기능
  • 각 프로젝트별 개별적으로 구성되며 프로젝트 간의 참조는 없다.
  • 프로젝트별로 동기화 출력을 캐싱 가능하게 하여 빌드 파일이 변경되면 영향받는 프로젝트만 재구성하도록 한다
  • Gradle 7.2에서 org.gradle.unsafe.isolated-projects=true를 통해서 테스트해 볼 수 있다

  • Kotlin 증분 컴파일을 개선 중
  • 예를 들어 Android 리소스 편집, 외부 종속성 추가, 다른 프로젝트 수정

comments powered by Disqus

Currnte Pages Tags

Android

About

Pluu, Android Developer Blog Site

이전 블로그 링크 :네이버 블로그

Using Theme : SOLID SOLID Github

Social Links