Soong 빌드 시스템

Android 7.0 이전 버전에서는 GNU Make를 독점적으로 사용하여 빌드 규칙을 설명하고 실행했습니다. Make 빌드 시스템은 널리 지원되고 사용되지만, Android 규모에서는 느리고 오류가 발생하며 확장이 불가능하고 테스트하기 어려웠습니다. Soong 빌드 시스템은 Android 빌드에 필요한 유연성을 제공합니다.

따라서 플랫폼 개발자는 가능한 한 빨리 Make에서 Soong으로 전환하는 것이 좋습니다. Google 그룹 android-building에 질문을 보내 지원을 받으세요.

Soong이란 무엇인가요?

Soong 빌드 시스템은 Make를 대체하기 위해 Android 7.0(Nougat)에 도입되었습니다. 이 시스템은 Kati GNU Make 클론 도구와 Ninja 빌드 시스템 구성요소를 활용하여 Android의 빌드 속도를 높입니다.

Android 오픈소스 프로젝트(AOSP)의 Android Make 빌드 시스템 설명에서 일반적인 안내를 살펴보고, Android.mk 작성자를 위한 빌드 시스템 변경사항을 참고하여 Make에서 Soong으로 전환하는 데 필요한 수정사항을 알아보세요.

주요 용어의 정의는 용어집의 빌드 관련 항목에서, 전체 세부정보는 Soong 참조 파일에서 확인하세요.

Make와 Soong 비교

다음은 Make 구성과 Soong 구성(Blueprint 또는 .bp) 파일에서 동일한 작업을 하는 Soong을 비교한 것입니다.

Make 예

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)

Soong 예

cc_library_shared {
     name: “libxmlrpc++”,

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

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

테스트용 Soong 구성의 예는 간단한 빌드 구성을 참고하세요.

Android.bp 파일 형식

디자인적으로 Android.bp 파일은 간단합니다. 여기에는 조건문 또는 제어 흐름 구문이 포함되어 있지 않습니다. 모든 복잡성은 Go로 작성된 빌드 로직에 따라 처리됩니다. Android.bp 파일의 구문과 의미는 가능한 경우 Bazel BUILD 파일과 유사합니다.

모듈

Android.bp 파일의 모듈은 name: "value", 형식의 속성 모음이 뒤따르는 모듈 유형으로 시작하며, 형식은 다음과 같습니다.

cc_binary {
    name: "gzip",
    srcs: ["src/test/minigzip.c"],
    shared_libs: ["libz"],
    stl: "none",
}

모든 모듈에는 name 속성이 있어야 하며 반복될 수 있는 네임스페이스 및 사전 빌드 모듈의 name 속성 값을 제외하고 값은 전체 Android.bp 파일에 걸쳐 고유해야 합니다.

srcs 속성은 모듈을 빌드하는 데 사용된 소스 파일을 문자열 목록으로 지정합니다. 모듈 참조 구문 ":<module-name>"을 사용하여 genrule 또는 filegroup과 같은 소스 파일을 생성하는 다른 모듈의 출력을 참조할 수 있습니다.

유효한 모듈 유형과 속성의 목록은 Soong 모듈 참조를 확인하세요.

유형

변수와 속성은 강타입(strongly typed)으로, 변수는 첫 번째 할당에 따라 동적으로 입력되고 속성은 모듈 유형에 따라 정적으로 설정됩니다. 지원 유형은 다음과 같습니다.

  • 부울(true 또는 false)
  • 정수(int)
  • 문자열("string")
  • 문자열 목록(["string1", "string2"])
  • 지도({key1: "value1", key2: ["value2"]})

지도에는 중첩된 지도를 포함한 모든 유형의 값이 포함될 수 있습니다. 목록과 지도에는 마지막 값 다음에 쉼표가 뒤에 올 수 있습니다.

Glob

파일 목록을 가져오는 속성(예: srcs)에서 glob 패턴을 취할 수도 있습니다. Glob 패턴은 일반 UNIX 와일드 카드 *를 포함할 수 있습니다(예: *.java). Glob 패턴은 또한 0개 이상의 경로 요소와 일치하는 하나의 ** 와일드 카드를 경로 요소로 포함할 수 있습니다. 예를 들어 java/**/*.javajava/Main.javajava/com/android/Main.java 패턴 모두와 일치합니다.

변수

Android.bp 파일에는 최상위 수준 변수 할당이 포함될 수 있습니다.

gzip_srcs = ["src/test/minigzip.c"],
cc_binary {
    name: "gzip",
    srcs: gzip_srcs,
    shared_libs: ["libz"],
    stl: "none",
}

변수는 하위 Blueprint 파일과 마찬가지로 선언된 파일의 나머지 부분으로 범위가 지정됩니다. 변수는 하나의 예외를 제외하고는 변경할 수 없으며, 참조되기 전에만 += 할당을 사용하여 추가될 수 있습니다.

주석

Android.bp 파일은 C 스타일 다중 행 /* */ 및 C++ 스타일 단일 행 // 주석을 포함할 수 있습니다.

연산자

문자열, 문자열 목록 및 지도는 + 연산자를 사용하여 추가할 수 있습니다. + 연산자를 사용하여 정수를 더할 수 있습니다. 지도를 추가하면 두 지도에 키 조합이 생성되고 두 지도에 있는 키의 값이 추가됩니다.

조건문

Soong은 Android.bp 파일에서 조건문을 지원하지 않습니다. 대신 조건문이 필요한 빌드 규칙의 복잡성은 고급 언어 기능을 사용할 수 있고 조건문에서 발생하는 암시적 종속 항목을 추적할 수 있는 Go에서 처리됩니다. 대부분의 조건문은 지도 속성으로 변환되며 여기서 지도의 값 중 하나가 선택되어 최상위 속성에 추가됩니다.

아키텍처 전용 파일을 지원하는 예는 다음과 같습니다.

cc_library {
    ...
    srcs: ["generic.cpp"],
    arch: {
        arm: {
            srcs: ["arm.cpp"],
        },
        x86: {
            srcs: ["x86.cpp"],
        },
    },
}

형식 지정 도구

Soong에는 gofmt와 비슷한 Blueprint 파일의 표준 형식 지정 도구가 포함됩니다. 현재 디렉터리에 있는 모든 Android.bp 파일의 형식을 재귀적으로 다시 지정하려면 다음을 실행합니다.

bpfmt -w .

표준 형식에는 4칸 들여쓰기, 다중 요소 목록의 모든 요소 다음에 오는 새 행, 목록과 지도의 후행 쉼표가 포함됩니다.

특수 모듈

일부 특수 모듈 그룹에는 고유한 특성이 있습니다.

기본 모듈

기본 모듈을 사용하여 여러 모듈에서 동일한 속성을 반복할 수 있습니다. 예:

cc_defaults {
    name: "gzip_defaults",
    shared_libs: ["libz"],
    stl: "none",
}

cc_binary {
    name: "gzip",
    defaults: ["gzip_defaults"],
    srcs: ["src/test/minigzip.c"],
}

사전 빌드된 모듈

일부 사전 빌드된 모듈 유형은 소스 기반의 모듈과 동일한 이름을 가질 수 있습니다. 예를 들어 같은 이름의 cc_binary가 이미 있는 경우 foo라는 이름의 cc_prebuilt_binary가 있을 수 있습니다. 이를 통해 개발자는 최종 제품에 포함할 버전을 자유롭게 선택할 수 있습니다. 빌드 구성에 두 버전이 모두 포함되어 있는 경우 사전 빌드된 모듈 정의의 prefer 플래그 값에 따라 우선 순위 버전이 지정됩니다. 일부 사전 빌드된 모듈은 이름이 prebuilt로 시작하지 않습니다(예:android_app_import).

네임스페이스 모듈

Android가 Make에서 Soong으로 완전히 전환될 때까지는 Make 제품 구성에서 PRODUCT_SOONG_NAMESPACES 값을 지정해야 합니다. 이 값은 Soong이 m 명령어로 빌드하기 위해 Make로 내보내는, 공백으로 구분된 네임스페이스 목록이어야 합니다. Android의 Soong 전환이 완료되면 네임스페이스를 사용하는 세부사항이 변경될 수 있습니다.

Soong은 각 모듈이 별도의 네임스페이스 내에서 선언된 경우 다른 디렉터리의 모듈을 같은 이름으로 지정할 수 있는 기능을 제공합니다. 네임스페이스는 다음과 같이 선언할 수 있습니다.

soong_namespace {
    imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}

네임스페이스에는 이름 속성이 없습니다. 경로는 자동으로 이름으로 할당됩니다.

각 Soong 모듈에는 트리의 위치를 기반으로 네임스페이스가 할당됩니다. 각 Soong 모듈은 현재 디렉터리 또는 가장 가까운 상위 디렉터리의 Android.bp 파일에 있는 soong_namespace에 의해 정의된 네임스페이스에 있는 것으로 간주됩니다. 이러한 soong_namespace 모듈이 없으면 모듈은 암시적 루트 네임스페이스에 있는 것으로 간주됩니다.

예를 들면 Soong은 네임스페이스 I1, I2, I3 등을 가져오는 네임스페이스 N에서 M 모듈이 선언한 종속 항목 D를 결정하려고 시도합니다.

  1. D가 //namespace:module 형식의 정규화된 이름인 경우 지정된 모듈 이름과 관련해 지정된 네임스페이스만 검색됩니다.
  2. 그렇지 않으면 Soong은 먼저 네임스페이스 N에 선언된 D 모듈을 찾습니다.
  3. 찾는 모듈이 없으면 Soong은 네임스페이스 I1, I2, I3 등에서 D라는 모듈을 찾습니다.
  4. 마지막으로 Soong은 루트 네임스페이스에서 모듈을 찾습니다.