다른 빌드 시스템과의 차이점

 AOSP는 대부분의 make 기반 빌드 시스템과는 다르게 안드로이드 빌드 시스템은 재귀적 makefile을 사용하지

않는다는 점이다.

 대신 모든 디렉터리와 하위 디렉터리를 탐색해서 Andoird.mk 파일을 찾아내는 스크립트가 있다.

 이 파일을 찾으면 그 위치에서 멈추고 더 이상의 하위 디렉터리는 탐색하지 않는다. Andoird.mk 안에서 하위 디렉터리를 탐색하라고 명시한 경우에만 탐색을 계속 이어나간다.

 안드로이드는 Makefile이라는 이름의 makefile의존하지 않는다. 대신 Andoird.mk 파일에서 로컬 모듈들이 어떻게

빌드되어야 하는지를 명시한다.


 안드로이드 빌드 시스템의 설정 방식 역시 독특하다. 안드로이드는 셀 환경에서 envsetup.sh 와 lunch로 동적으로

생성하거나 buildspec.mk 파일로 미리 정의해둔 변수들을 활용한다.


 또한. 빌드 시스템은 소스 파일과 같은 위치에 객체 파일 등의 중간 출력을 생성하지 않는다. 모든 생성물은

out/ 디렉터리에 저장한다.




아키텍처

 위 그림에서 묘사한 대로 빌드 시스템 입장에서 타당한 진입점은  build/core/ 디렉터리의 main.mk 파일이다.

이 파일은 최상위  makefile을 호출한다. 



설정

빌드 시스템이 시작되면 build/core/config.mk 에서 빌드 설정을 가져온다. 빌드는 envsetup.sh 와 lunch 명령의 조합

또는 최상위 디렉터리에 buildspec.mk 파일을 만드는 방식 중 하나로 설정할 수 있다. 둘 중 어느 것이는 다음 변수 중

일부를 설정해야 한다.


 




envsetup.sh

 이름에서 짐작할 수 있듯이  envsetup.sh는 안드로이드의 빌드 환경을 설정하는 데 사용된다. 하지만 이 파일에서는

그중 일부만 설정하며 주로 다음과 같이 AOSP 관련하여 유용한 일련의 쉘 명령을 정의한다.


 디렉터리를 탐색하는 데는 croot와 godir 명령이 유용할 것이다. 특히 자바는 패키지명이 디렉터리 구조에 그대로 반영

되기 때문에 상당히 깊은 디렉터리 트리를 만들기도 한다.


 m과 mm도 유용하다. m은 어느 경로에 있든 전체를 빌드하며, mm은 현재 디렉터리에 있는 모듈만 빌드한다. 예를들어

Launcher를 수정했고 현재 package/apps/Launcher2에 있다면 cd 명령으로 최상위 디렉터리로 돌아가  make 를 실행

하는 대신 mm을 실행하면 해당 모듈만 다시 빌드할 수 있다. 주위할 점은 mm은 전체 트리를 다시 빌드하지 않기 때문

에 의존 모듈이 변경되어도 AOSP 이미지를 다시 생성하지 않는다. 반면 m은 전체 이미지까지 다시 생성한다.



build/envsetup.sh 실행후



함수 정의

 build/core/에만 40개가 넘는 .mk 파일들이 있다. 이처럼 빌드 시스템이 무척 크기 때문에 되도록 코드를 재사용 하는

편이 좋다. 이 때문에 빌드 시스템은 definitions.mk 파일에 많은 함수를 정의한다. 이 파일의 용량도 빌드 시스템 전체

에서 가장 크다. 170개 함수와 2,100 줄의 makefile 코드로 이루어진다.(버전 4 기준)


 이 함수들은 빌드 시스템 전반에서 핵심 라이브러리처럼 사용될 뿐만 아니라 때떄로 각 모듈의 Android.mk파일에서 

직접 사용하기도 한다.


 대부분의 함수 앞에는 동작 방식을 설명하는 주석이 달려있다.



주요 Make

 이쯤 되면 주요 산출물들이 언제 생성되는지 궁금해질 것이다. 램 디스크와 같은 이미지들은 어떻게 생성되고 SDK는

어떻게 합쳐질까?


 build/core/의 Makefile을 살펴보자 (최상위 디렉터리가 아니므로 착오 없기 바란다.)


다음 정도는 어떻게 생성되는지 살펴보기 바란다.

 


커널 이미지

 커널 빌드 규칙 같은 것은 없다. 공식 AOSP 배포판에는 커널이 포함되지 않는다.(4.0 기준)




빌드 청소

make clean을 실행 하는것은 out/ 디렉터리의 내용을 삭제하는 것과 같다. clean은 main.mk 에 정의되어 있다.

다른청소 타깃으로 cleanbuild.mk에 정의 되어 있는  installclean이 있다.


installclean은 TARGET_PRODUCT, TARGET_BUILD_VARIANT, PRODUCT_LOCALES를 변경할 때마나 자동으로 실행된다.

예를 들어 lunch를 사용하여 타겟을 변경하고 다음번 make를 실행할 때 일부 빌드 결과물은 installclean으로

자동 정리된다.



모듈 빌드 템플릿

 안드로이드 시스템은 각 모듈의 빌드 방식이 빌드 시스템에 종속되지 않도록 설계되었다. 대신 모듈용 빌드 템플릿을

제공하여 모듈 작성자가 전체 시스템과 독립적으로 모듈을 빌드할 수 있도록 하였다. 


템플릿도 다른 빌드 시스템 파일들과 같이 build/core/에 담겨 있다. Android.mk가 특정 템플릿을 가져올 때는

include 지시자를 사용한다. 

예)  include $(BUILD_PACKAGE)






LOCAL_* 변수들




결과물

 크게 보면 빌드 출력은 세 개의 단계를 거쳐 진행되며 호스트(host)와 타깃(target)이라는 두가지 모드로 동작한다.

1. 모듈 소스로부터 중간 생성물들이 생성된다. 이 중간 생성물들의 위치는 모듈의 소스코드에 따라 달라진다.

   예를 들어  C/C++ 코드는 .o파일을, 자바코드는 .jar 파일을 생성한다.


2. 중간 생성물들을 이용하여 바이너리 파일과 패키지를 생성한다. 예를 들어 .o 파일은 바이너리 파일로 링크된다. 


3. 바이너리 파일과 패키지를 합쳐 최종 결과물을 만든다. 바이너리는 파일시스템의 루트와 /system등의 디렉터리로

   복사되고, 실제 기기에서 사용될 파일시스템 이미지가 생성된다.


out/은 크게 host/ 와 target/ 두 디렉터리로 나누어지는데 어느 쪽이 되는지는 동작모드가 결정한다.

각 디렉터리의 obj/ 디렉터리에는 빌드과정에서 만들어진 여러 중간 생성물들이 들어가게 된다.


 가장 관심을 가질 만한 디렉터리는 out/target/product/PRODUCT_DEVICE/ 이다. 해당 제품설정의 .mk 파일에서

PRODUCT_DEVICE로 정의한 결과 이미지가 여기에 저장된다.

 




개별 모듈 빌드하기

 모듈을 하나씩 빌드할 수도 있다. 다음은 빌드 시스템에서 Launcher2 모듈(홈 화면) 을 빌드하는 방법이다.

$ make Launcher2


개별 모듈 빌드를 초기화할 수도 있다.

 $ make clean-Launcher2


갱신된 모듈을 포함하도록 시스템 이미지를 다시 생성하고 싶으면 명령행에  snod를 추가한다.

 




 



출처 : 임베디드 안드로이드 : 안드로이드 포팅, 확장, 커스터마이징하기 ( 한빛미디어 (카림 야크무르 지음, 이성주 옮김))

+ Recent posts