본문 바로가기
SW 개발/Android

Soong 빌드 시스템을 활용한 Android.bp 작성법

by Kibua20 2020. 6. 9.

Google에서 Android 버전을 올릴 때마다 Android.mk를 Android.bp로 변경하다고 공지하고 있습니다. Android 11 (R-OS)에서는 Androdi.mk와 Android.bp를 같이 사용할 수 있지만 2~3년 후에는 Android.mk는 빌드는 지원하지 않고, Android.bp만 지원할 것으로 예상됩니다.

 

Androdi.bp는 Soong build 시스템을 사용합니다.  Androdi.mk 대신 Soong에서 사용하는 Android.bp 파일을 차이점을 이해야 하며, Android Full 빌드를 하는 경우 Andorid.mk를 Android.bp로 변환하는 과정이 있어 Android.bp를 사용하는 경우 빌드 시간이 조금이나마 단축할 수 있습니다. 

 

Android.bp파일을 처음부터 작성하는 것은 쉽지 않고, androidmk 명령어로 변환하거나 동일한 모듈의 bp 파일을 참고하서 필요한 부분만 변경하는 것이 보다 쉽게 작성할 수 있습니다.  모듈 유형은 링크에서 확인이 가능합니다.

 

참고로, Andorid Q부터는 Soong에서 모듈을 빌드하기 위해서는 Make 파일을 BP 파일로 변환하고 모듈간의 종속석 graph를 업데이트하는 과정을 사용합니다.  mm 명령어를 사용해서 이러한 과정을 거치는데, Andorid R부터는 mma 명령어와 mm은 동일하게 처리됩니다. 

 

Android.mk 파일 변환

Soong에는 Android.mk 파일을 Android.bp 파일로 변환하는 Tool 있습니다. 기존 Androd.mk 파일을 androidmk 명령어를 사용해서 변환할 수 있지만, Andorid.mk 에서만 사용하는 변수, 조건문, 코멘트 항목은 Android.bp 파일에서 지원하지 않기 때문에 변환 후 결과를 확인하는 과정을 거쳐야 하며 이들은 수동으로 변환해야 합니다. 

 

$ androidmk Android.mk > Android.bp

 

Android.mk와 Androd.bp 파일 비교

$(BUILD_SHARED_LIBRARY) 은 cc_library_shared 로 맵핑되고, LOCAL_MODULE은 name으로 1:1로 맵핑됩니다. cppflag, cincluddir, srcs위치 또한 동일하게 지정할 수 있습니다.

 

Android.mk 파일 예제  (출처)

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := libxmlrpc++
LOCAL_MODULE_HOST_OS := linux
LOCAL_RTTI_FLAG := -frtti
LOCAL_CPPFLAGS := -Wall -Werror -fexceptions
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/src
LOCAL_SRC_FILES := $(call   all-cpp-files-under,src)
include $(BUILD_SHARED_LIBRARY)

Android.bp 파일 예제 (출처)

cc_library_shared {
     name
: libxmlrpc++”,
     rtti
: true,
     cppflags
: [
           
“-Wall”,
           
“-Werror”,
           
“-fexceptions”,
     
],
     export_include_dirs
: [“src”],
     srcs
: [“src/**/*.cpp”],

     target
: {
           darwin
: {
                enabled
: false,
           
},
     
},
}

 

Android.bp 에서 변수 사용

gzip_srcs = ["src/test/minigzip.c"],      →  src 파일을 정의, 변수로 할당 가능함
cc_binary {      →  c로 작성한 elf 파일로 빌드
    name: "gzip",      →  빌드 이름은 gzip
    srcs: gzip_srcs,   →  소스 파일은  gzip_srcs 로 설정
   shared_libs: ["libz"],    → libz.so 파일을 참조
   stl: "none",
}

 

Android.bp 파일에서 조건문

 아래 예제는 arm과 x86에 따라서 사용하는 cpp파일을 분기하는 예제입니다.  arch는 Soong에 기본적으로 설정된 config 변수입니다. 

cc_library {    →  cc binary로 빌드함

     ...   
    srcs: ["generic.cpp"],  →  src 파일 리스트 정의
    arch: {  →  cpu arch에 따라서 분기함
        arm: {    cpu arch가 arm인 경우 
            srcs: ["arm.cpp"],  →  srcs 파일에 arm.cpp를 추가함
        },       
       x86: {   →  cpu arch가 x86인 경우
          srcs: ["x86.cpp"],  →  srcs 파일에 x86.cpp를 추가함
      },   
   },
}

 

모델(product)별 Soong config  variable 추가

제조사에서 Android 빌드하기 위해서는 동일한 소스로 동시에 여러 플랫폼 (e.g. 퀄컴, MTK) 또는 여러 모델에 재 사용을 통해서 효율화를 추구합니다. 이러한 경우에 모델별 Soong config를 추가가 필요합니다. 

 

soong_confg_* modules 추가를 해야 합니다.  cc_defaults module의 config 기반으로  board, feature, width 값을 추가하여 acme_cc_defaults 모듈을 확장합니다. 즉, android.bp 파일에서 board, feature, width 값을 parameter로 Soong build system에 전달할 수 있습니다. 

soong_config_module_type
{
    name: "acme_cc_defaults",
    module_type: "cc_defaults",
    config_namespace: "acme",
    variables: ["board"],
    bool_variables: ["feature"],
    value_variables: ["width"],
    properties: ["cflags", "srcs"],
}

soong_config_string_variable
{
    name: "board",
    values: ["soc_a", "soc_b"],
}

 

모델의  BoardConfig.mk에 config variable 값을 아래와 같이 설정합니다. 

SOONG_CONFIG_NAMESPACES += acme
SOONG_CONFIG_acme +=  board  feature 
SOONG_CONFIG_acme_board := soc_a
SOONG_CONFIG_acme_feature := true
SOONG_CONFIG_acme_width := 200

soong_config_module_type_import을 아래와 같이 선언합니다. 

soong_config_module_type_import
{
    from: "device/acme/Android.bp",
    module_types: ["acme_cc_defaults"],
}

 

위의 단계가 선언되었으면 다른 모듈에서는 아래와 같이 사용이 가능합니다. 

acme_cc_defaults{
    name: "acme_defaults",
   cflags: ["-DGENERIC"],
    soong_config_variables:{
        board: {              soc_a: {
                   cflags: ["-DSOC_A"],      →  board 가 soc_a 인 경우 CFlag에 SOC_A define 추가
             },
             soc_b: {
                   cflags: ["-DSOC_B"],    →  board 가 soc_b인 경우 CFlag에 SOC_B define 추가
             },
        },
       feature: {
             cflags: ["-DFEATURE"],  →  feature가 Boardconfig.mk 에 정의된 경우 CFlag에 FEATURE 추가
        },
       width: {
               cflags: ["-DWIDTH=%s"],  →  Boardconfig.mk 에 정의된 값으로 CFlag에 WIDTH=200 추가
         },
   },
}

cc_library {
    name: "libacme_foo",
    defaults: ["acme_defaults"],  →  acme_defaults 값을 사용해서 모듈을 빌드함
    srcs: ["*.cpp"],
}

 

 

관련 글:

[모바일 SW 개발/Android] - Android에서 Python 실행 (SL4A와 Termux 활용)

[모바일 SW 개발/Android] - Android 에서 리눅스 App 실행: Linux Terminal Emulator (Termux) 활용

[모바일 SW 개발/Android] - Command line 기반 Android Apk 분석 툴: apkanalyzer

[모바일 SW 개발/Android] - Android apkanalyzer 에러: java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema

[모바일 SW 개발/Android] - Repo 에러: repo sync unable to read sha1 file of xxx, cannot initialize work tree

[모바일 SW 개발/Android] - Android 소스 최적화 (100GB에서 65GB로 줄이기)

[모바일 SW 개발/Android] - Android 11 기능 소개

[모바일 SW 개발/Android] - Android 11 (R-OS) Emulator에 설치하기

[모바일 SW 개발/Android] - Ubuntu에서 Android 10 빌드하기

[블로그 관리/모바일 마케팅] - [용어 정리 #4] Android Install Referrer API




댓글