[AOSP] Ubuntu에서 안드로이드 13 빌드하기 3

들어가며

주로 안드로이드 빌드 시스템과 OEM 상품을 만들기 위해 프레임워크의 개발이 필요한데, 이에 대한 정보가 많이 없어 리서치가 어려웠다. 여기저기 파편화된 정보들이 있었고 어느 정도 정리가 된 상태여서 포스트로 작성한다.

안드로이드 빌드를 위해 코드를 다운받으면, 단일 브랜치의 소스코드 용량만 해도 100GB가 넘는데다가 빌드 과정과 내부 리소스도 복잡하게 얽혀있다. 그만큼 역사도 길고 수많은 패치와 커밋의 결과물이기 때문이다.

 

빌드 순서

Android 7.0 이전

Android 7.0 이전에는 안드로이드를 빌드할 때 GNU make 도구를 사용했다. 모든 빌드 구성 규칙은 'Makefile'이라는 파일에 작성되었으며, make 도구는 이 파일의 지침에 따라 코드를 컴파일 한다.

make는 자동화된 빌드 도구로, Makefile을 읽어서 소스 코드르 실행 프로그램과 라이브러리 파일로 자동 빌드한다. 또한 대상 프로그램의 종속성과 생성을 위해 규칙을 정의한다.

Android 7.0 이후

안드로이드 수준에서 GNU Make의 컴파일 속도, 오류 발생, 확장성 저하, 테스트의 어려움 등을 이유로 구글은 사람이 읽을 수 있는 .ninja 파일로 안드로이드 빌드 시스템을 변경하였다. Ninja 빌드 시스템은 컴파일 프레임워크로, 해당 .ninja 파일에 있는 .bp(Blueprint) 파일에 따라 컴파일된다. 일반적으로 .ninja 파일은 수동으로 수정하지 않고 .bp 파일을 .ninja 파일로 변환하여 컴파일한다.

구글은 .ninja 파일을 생성하기 위해 안드로이드 bp 파일을 .ninja 파일로 파싱하는 블루프린트라는 도구와 함께 soong 빌드 시스템을 도입했으며, 안드로이드 mk 파일을 .ninja 파일로 변환하는 'kati' 도구도 함께 도입했다.

'kati' 도구는 Go언어와 C++에 기반한 도구로, 주요 기능은 안드로이드 .mk 파일을 ninja 파일로 변환한다.

따라서 전체 흐름도는 다음과 같이 나타낼 수 있다.

2020년 구글의 릴리즈 노트에서, 빌드 도구를 'Bazel'(https://bazel.build/)로 마이그레이션 예정임을 알렸다.

 

Android.bp와 블루프린트 상세

Android.bp에서는 모듈 유형에 따라 필요한 것들을 빌드한다. 일반적으로 사용되는 유형과 메서드는 다음과 같다.

  • android_app: apk 파일 빌드에 사용되며, android.mk BUILD_PACKAGE와 동일한 기능을 한다.
  • java_library: .class 파일에서 .jar 번들을 생성한다. 생성된 jar는 디바이스에 직접 설치하기에 적합하지 않으며 static_libs 종속성으로 사용된다.
  • static_libs: 컴파일 시에 호출자에서 확인되고 컴파일러에 의해 대상 애플리케이션에 복사되는 라이브러리.
  • android_library: 안드로이드 리소스 파일과 함께 소스 코드를 빌드하고 디바이스의 .jar 파일에 링크한다.
    android_library에는 .class 파일에서 .jar 번들을 생성하는 다른 변형(variant)이 있다. 그리고 aapt2에서 생성된 package-res.apk 파일이 있다. 생성된 apk 파일은 단말에 직접 설치할 수는 없지만 android_app 모듈의 static_libs 종속 요소로 사용할 수 있다.
  • platform_apis: SDK의 숨김 API로 컴파일한다. 앱 개발자들이 앱을 개발할 때 이 위치의 api를 불러와서 사용하면, 단말의 동작을 일일이 정의할 필요 없이 api로 불러와서 사용할 수 있다. JetPack 등 운영 체제와 함께 번들로 제공되지 않는 리팩터링된 버전의 Android API.
  • 인증서: 어떤 서명을 사용할지 지정하며, 위와 같이 플랫폼 서명이 사용된다.
  • android_library_import: 안드로이드_라이브러리로 빌드한 것처럼 빌드 그래프에 '.aar' 파일을 가져온다. 이 모듈은 디바이스에 설치하는 데 적합하지 않지만 android_app 모듈의 static_libs 종속 요소로 사용할 수 있다.

더 많은 빌드 파일 정보는 문서(https://ci.android.com/builds/submitted/7967930/linux/latest/raw/java.html#android_library_import)에서 확인할 수 있다.

  이제 다시 위의 흐름도를 살펴보면 각 과정에 대한 결과 파일을 확인할 수 있다. Android.mk 및 기타 Makefile에서 out/build-aosp_bluejay.ninja 파일이 생성된다. Android.bp에서는 out/soong/build.ninja가 생성된다. 또한 이 두 파일을 실행 항목으로 연결하는 역할을 하는 더 작은 out/combined-aosp_bluejay.ninja 파일이 생성됩니다. 결국 ninja 파일은 소스 코드 컴파일을 실제로 직접 제어하는 도구이며 apk, aar 및 dex 파일을 생성하는 역할을 한다. APK의 서명도 ninja규칙을 사용하여 수행되며 이 모든 작업이 완료되면 *.imgs가 생성된다.

Dive into the build step

빌드 단계에서 다음의 세가지 명령 실행을 통해 결과 파일을 확인할 수 있다.

source build/envsetup.sh
lunch <option>
make <module-name> -j <core>

각 단계에서 진행하는 과정을 상세하게 알아본다.

1. source build/envsetup.sh

envsetup.sh 스크립트는 많은 함수를 정의한다. 이 스크립트를 실행한 후 lunch, make 등의 명령을 사용하여 현재 콘솔에서 이러한 함수를 직접 실행할 수 있다.(사용 가능한 명령어를 보려면 hmm실행)

2. lunch

lunch() 함수는 envsetup.sh 스크립트에서 이미지(*.imgs) 및 기타 아티팩트(예: apk, jar, .so 등)를 빌드하기 위한 환경을 설정한다. 이 함수는 AndroidProducts.mk.list라는 파일 목록에서 대상 기기 목록을 읽는다. COMMON_LUNCH_CHOICES 변수를 가져와서 print_lunch_menu()가 호출될 때 사용자에게 표시하고, 이 함수에서 get_build_var()가 호출되어 /build/soong/soong_ui.bash - dumpvar - mode를 차례로 호출한다.

lunch의 실행 옵션(인자)로 부여한 빌드 구성(포스트에서는 'aosp-sunfish-userdebug')에 대한 기기로 빌드하기 위한 과정이다.

3. make

m 또는 make 명령은 make- 모드인 build/soong/soong_ui.bash와 동일하며, 이는 soong_ui.bash가 안드로이드 플랫폼 빌드 시스템의 주요 핵심이라는 것을 의미한다.

source ${TOP}/build/soong/scripts/microfactory.bash

soong_build_go soong_ui android/soong/cmd/soong_ui
soong_build_go mk2rbc android/soong/mk2rbc/cmd
soong_build_go rbcrun rbcrun/cmd

cd ${TOP}
exec "$(getoutdir)/soong_ui" "$@"

 

Conclusion

AOSP와 안드로이드 이미지 빌드 시스템에 대한 이해가 조금 이해가 되는 것 같다. 빌드 시스템은 장기간에 거쳐 BAZEL로 전환되고 있고 이는 대형 프로젝트로 관리되고 있다. 그래서 빌드 시스템을 얼마나 깊이있게 연구해야 하는지 고민을 많이했던 부분이다. 이미 지금 내려받는 안드로이드 git 소스 파일 내에는 BAZEL 관련 파일들이 있다. 그래도 현재 시점으로 최소 13버전까지는 soong과 ninja를 이용한 빌드를 사용하고 있으니 병행해서 연구하면 될 것 같다.

물론 당연히 이론만으로 한번에 이해하기는 어렵고, 직접 빌드를 통해서 반복해볼 필요가 있다.

 

참고

https://proandroiddev.com/android-open-source-platform-aosp-build-systems-c98abb390d2d

반응형