Android 8.1 및 이후 버전에서는 빌드 시스템에 VNDK 지원 기능이 내장되어 있습니다. VNDK 지원이 사용 설정되면 빌드 시스템은 모듈 간의 종속 항목을 확인하고 공급업체 모듈의 공급업체별 변형을 빌드하고 이러한 모듈을 지정된 디렉터리에 자동으로 설치합니다.
VNDK 빌드 지원 예시
이 예에서 Android.bp
모듈 정의는 libexample
이라는 라이브러리를 정의합니다. vendor_available
속성은 프레임워크 모듈과 공급업체 모듈이 libexample
에 종속될 수 있음을 나타냅니다.
프레임워크 실행 파일 /system/bin/foo
와 공급업체 실행 파일 /vendor/bin/bar
는 libexample
에 종속되며 shared_libs
속성 값으로 libexample
을 갖습니다.
프레임워크 모듈과 공급업체 모듈이 모두 libexample
을 사용한다면 libexample
은 두 가지 변형으로 빌드됩니다. libexample
이라는 핵심 변형은 프레임워크 모듈에서 사용하고 libexample.vendor
라는 공급업체 변형은 공급업체 모듈에서 사용합니다. 두 변형은 다른 디렉터리에 설치됩니다.
- 핵심 변형은
/system/lib[64]/libexample.so
에 설치됩니다. - 공급업체 변형은
vndk.enabled
가true
이므로 VNDK APEX에 설치됩니다.
자세한 내용은 모듈 정의를 참조하세요.
빌드 지원 구성
제품 기기에 전체 빌드 시스템을 지원하도록 사용 설정하려면 BoardConfig.mk
에 BOARD_VNDK_VERSION
을 추가합니다.
BOARD_VNDK_VERSION := current
이 설정은 전역적인 효과가 있으며 BoardConfig.mk
에 정의되면 모든 모듈에 적용됩니다. 문제가 있는 모듈을 목록에서 제외하거나 목록에 추가하는 메커니즘이 없으므로 BOARD_VNDK_VERSION
을 추가하기 전에 불필요한 종속 항목을 모두 삭제해야 합니다. 환경 변수에 BOARD_VNDK_VERSION
을 설정하여 모듈을 테스트하고 컴파일할 수 있습니다.
$ BOARD_VNDK_VERSION=current m module_name.vendor
BOARD_VNDK_VERSION
이 사용 설정되면 여러 기본 전역 헤더의 검색 경로가 삭제됩니다. 다음이 포함됩니다.
frameworks/av/include
frameworks/native/include
frameworks/native/opengl/include
hardware/libhardware/include
hardware/libhardware_legacy/include
hardware/ril/include
libnativehelper/include
libnativehelper/include_deprecated
system/core/include
system/media/audio/include
모듈이 이러한 디렉터리의 헤더에 종속되면 header_libs
, static_libs
또는 shared_libs
로 종속 항목을 명시적으로 지정해야 합니다.
VNDK APEX
Android 10 이하에서 vndk.enabled
가 있는 모듈은 /system/lib[64]/vndk[-sp]-${VER}
에 설치되었습니다. Android 11 이상에서 VNDK 라이브러리는 APEX 형식으로 패키징되며 VNDK APEX의 이름은 com.android.vndk.v${VER}
입니다. 기기 설정에 따라 VNDK APEX는 평면화되거나 평면화되지 않으며 표준 경로 /apex/com.android.vndk.v${VER}
에서 사용할 수 있습니다.
모듈 정의
BOARD_VNDK_VERSION
으로 Android를 빌드하려면 Android.mk
또는 Android.bp
에서 모듈 정의를 수정해야 합니다. 이 섹션에서는 다양한 종류의 모듈 정의, 여러 VNDK 관련 모듈 속성 및 빌드 시스템에 구현된 종속 항목 확인에 관해 설명합니다.
공급업체 모듈
공급업체 모듈은 공급업체 파티션에 설치해야 하는 공급업체별 실행 파일 또는 공유 라이브러리입니다. Android.bp
파일에서 공급업체 모듈은 공급업체 또는 독점 속성을 true
로 설정해야 합니다.
또한 공급업체 모듈은 Android.mk
파일의 LOCAL_VENDOR_MODULE
또는 LOCAL_PROPRIETARY_MODULE
을 true
로 설정해야 합니다.
BOARD_VNDK_VERSION
이 정의되면 빌드 시스템은 공급업체 모듈과 프레임워크 모듈 간에 종속 항목을 허용하지 않으며 다음과 같은 경우 오류를 표시합니다.
vendor:true
가 없는 모듈이vendor:true
가 있는 모듈에 종속되거나vendor:true
가 있는 모듈이vendor:true
와vendor_available:true
가 모두 없는llndk_library
가 아닌 모듈에 종속됨
종속 항목 확인은 Android.bp
의 header_libs
, static_libs
, shared_libs
및 Android.mk
의 LOCAL_HEADER_LIBRARIES
, LOCAL_STATIC_LIBRARIES
, LOCAL_SHARED_LIBRARIES
에 적용됩니다.
LL-NDK
LL-NDK 공유 라이브러리는 안정적인 ABI를 사용하는 공유 라이브러리입니다. 프레임워크와 공급업체 모듈 모두 최신의 동일한 구현을 공유합니다. 각 LL-NDK 공유 라이브러리의 경우 cc_library
에 기호 파일과 함께 llndk
속성이 포함됩니다.
cc_library { name: "libvndksupport", llndk: { symbol_file: "libvndksupport.map.txt", }, }
기호 파일은 공급업체 모듈에 표시되는 기호를 설명합니다. 예를 들면 다음과 같습니다.
LIBVNDKSUPPORT { global: android_load_sphal_library; # llndk android_unload_sphal_library; # llndk local: *; };
기호 파일을 토대로 빌드 시스템은 공급업체 모듈의 스텁 공유 라이브러리를 생성합니다. 공급업체 모듈은 BOARD_VNDK_VERSION
이 사용 설정되면 이러한 라이브러리와 연결됩니다. 기호는 다음과 같은 경우에만 스텁 공유 라이브러리에 포함됩니다.
- 섹션 끝에
_PRIVATE
또는_PLATFORM
으로 정의되지 않음 #platform-only
태그가 없음#introduce*
태그가 없거나 태그가 타겟과 일치함
VNDK
Android.bp
파일에서 cc_library
, cc_library_static
, cc_library_shared
및 cc_library_headers
모듈 정의는 vendor_available
, vndk.enabled
, vndk.support_system_process
세 가지 VNDK 관련 속성을 지원합니다.
vendor_available
또는 vndk.enabled
가 true
이면 두 가지 변형(핵심 및 공급업체)으로 빌드될 수 있습니다. 핵심 변형은 프레임워크 모듈로, 공급업체 변형은 공급업체 모듈로 취급되어야 합니다. 일부 프레임워크 모듈이 이 모듈에 종속되는 경우 핵심 변형이 빌드됩니다. 일부 공급업체 모듈이 이 모듈에 종속되는 경우 공급업체 변형이 빌드됩니다. 빌드 시스템은 다음과 같은 종속 항목 확인을 적용합니다.
- 핵심 변형은 항상 프레임워크 전용이며 공급업체 모듈에 액세스할 수 없습니다.
- 공급업체 변형은 항상 프레임워크 모듈에 액세스할 수 없습니다.
header_libs
,static_libs
또는shared_libs
에 지정된 공급업체 변형의 모든 종속 항목은llndk_library
이거나vendor_available
또는vndk.enabled
가 있는 모듈이어야 합니다.vendor_available
이true
이면 공급업체 변형은 모든 공급업체 모듈에 액세스할 수 있습니다.vendor_available
이false
이면 공급업체 변형은 다른 VNDK 또는 VNDK-SP 모듈에만 액세스할 수 있습니다(즉,vendor:true
가 있는 모듈은vendor_available:false
모듈에 연결할 수 없음).
cc_library
또는 cc_library_shared
의 기본 설치 경로는 다음 규칙에 따라 결정됩니다.
- 핵심 변형은
/system/lib[64]
에 설치됩니다. - 공급업체 변형의 설치 경로는 다를 수 있습니다.
vndk.enabled
가false
이면 공급업체 변형은/vendor/lib[64]
에 설치됩니다.vndk.enabled
가true
이면 공급업체 변형은 VNDK APEX(com.android.vndk.v${VER}
)에 설치됩니다.
아래 표에는 빌드 시스템이 공급업체 변형을 처리하는 방식이 요약되어 있습니다.
vendor_available | vndk enabled |
vndk support_same_process |
공급업체 변형 설명 |
---|---|---|---|
true |
false |
false |
공급업체 변형은 VND-ONLY입니다. 공유 라이브러리는 /vendor/lib[64] 에 설치됩니다. |
true |
Invalid(빌드 오류) | ||
true |
false |
공급업체 변형은 VNDK입니다. 공유 라이브러리는 VNDK APEX에 설치됩니다. | |
true |
공급업체 변형은 VNDK-SP입니다. 공유 라이브러리는 VNDK APEX에 설치됩니다. | ||
|
|
|
공급업체 변형이 없습니다. 이 모듈은 FWK-ONLY입니다. |
true |
Invalid(빌드 오류) | ||
true |
false |
공급업체 변형은 VNDK-Private입니다. 공유 라이브러리는 VNDK APEX에 설치됩니다. 이러한 라이브러리는 공급업체 모듈에서 직접 사용하면 안 됩니다. | |
true |
공급업체 변형은 VNDK-SP-Private입니다. 공유 라이브러리는 VNDK APEX에 설치됩니다. 이러한 라이브러리는 공급업체 모듈에서 직접 사용하면 안 됩니다. |
VNDK 확장 프로그램
VNDK 확장 프로그램은 추가 API가 있는 VNDK 공유 라이브러리입니다. 확장 프로그램은 /vendor/lib[64]/vndk[-sp]
(버전 접미사 없음)에 설치되고 런타임 시 원본 VNDK 공유 라이브러리를 재정의합니다.
VNDK 확장 프로그램 정의
Android 9 이상에서 Android.bp
는 기본적으로 VNDK 확장 프로그램을 지원합니다. VNDK 확장 프로그램을 빌드하려면 vendor:true
와 extends
속성이 있는 다른 모듈을 정의하면 됩니다.
cc_library { name: "libvndk", vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libvndk_ext", vendor: true, vndk: { enabled: true, extends: "libvndk", }, }
vendor:true
, vndk.enabled:true
및 extends
속성이 있는 모듈은 다음과 같이 VNDK 확장 프로그램을 정의합니다.
extends
속성은 기본 VNDK 공유 라이브러리 이름(또는 VNDK-SP 공유 라이브러리 이름)을 지정해야 합니다.- VNDK 확장 프로그램(또는 VNDK-SP 확장 프로그램)은 확장하려고 하는 기본 모듈의 이름으로 명명합니다. 예를 들어
libvndk_ext
의 출력 바이너리는libvndk_ext.so
가 아닌libvndk.so
입니다. - VNDK 확장 프로그램은
/vendor/lib[64]/vndk
에 설치됩니다. - VNDK-SP 확장 프로그램은
/vendor/lib[64]/vndk-sp
에 설치됩니다. - 기본 공유 라이브러리에는
vndk.enabled:true
및vendor_available:true
가 모두 있어야 합니다.
VNDK-SP 확장 프로그램은 VNDK-SP 공유 라이브러리에서 확장되어야 합니다(vndk.support_system_process
는 동일해야 함).
cc_library { name: "libvndk_sp", vendor_available: true, vndk: { enabled: true, support_system_process: true, }, } cc_library { name: "libvndk_sp_ext", vendor: true, vndk: { enabled: true, extends: "libvndk_sp", support_system_process: true, }, }
VNDK 확장 프로그램(또는 VNDK-SP 확장 프로그램)은 다른 공급업체 공유 라이브러리에 종속될 수 있습니다.
cc_library { name: "libvndk", vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libvndk_ext", vendor: true, vndk: { enabled: true, extends: "libvndk", }, shared_libs: [ "libvendor", ], } cc_library { name: "libvendor", vendor: true, }
VNDK 확장 프로그램 사용
공급업체 모듈이 VNDK 확장 프로그램에서 정의하는 추가 API에 종속되면 모듈은 shared_libs
속성에 VNDK 확장 프로그램의 이름을 지정해야 합니다.
// A vendor shared library example cc_library { name: "libvendor", vendor: true, shared_libs: [ "libvndk_ext", ], } // A vendor executable example cc_binary { name: "vendor-example", vendor: true, shared_libs: [ "libvndk_ext", ], }
공급업체 모듈이 VNDK 확장 프로그램에 종속되어 있다면 이러한 VNDK 확장 프로그램은 /vendor/lib[64]/vndk[-sp]
에 자동으로 설치됩니다. 모듈이 더 이상 VNDK 확장 프로그램에 종속되지 않으면 CleanSpec.mk
에 삭제 단계를 추가하여 공유 라이브러리를 삭제합니다. 예를 들면 다음과 같습니다.
$(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)
조건부 컴파일
이 섹션에서는 아래의 세 VNDK 공유 라이브러리 간의 미묘한 차이(예: 변형 중 하나에서 기능을 추가 또는 제거)를 처리하는 방법에 관해 설명합니다.
- 핵심 변형(예:
/system/lib[64]/libexample.so
) - 공급업체 변형(예:
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
) - VNDK 확장 프로그램(예:
/vendor/lib[64]/vndk[-sp]/libexample.so
)
조건부 컴파일 플래그
Android 빌드 시스템은 공급업체 변형 및 VNDK 확장 프로그램의 __ANDROID_VNDK__
를 기본으로 정의합니다. C 전처리기 가드로 코드를 보호할 수 있습니다.
void all() { } #if !defined(__ANDROID_VNDK__) void framework_only() { } #endif #if defined(__ANDROID_VNDK__) void vndk_only() { } #endif
__ANDROID_VNDK__
외에 다른 cflags
또는 cppflags
를 Android.bp
에 지정할 수 있습니다. target.vendor
에 지정된 cflags
또는 cppflags
는 공급업체 변형에 따라 다릅니다.
예를 들어 아래 Android.bp
는 libexample
과 libexample_ext
를 정의합니다.
cc_library { name: "libexample", srcs: ["src/example.c"], vendor_available: true, vndk: { enabled: true, }, target: { vendor: { cflags: ["-DLIBEXAMPLE_ENABLE_VNDK=1"], }, }, } cc_library { name: "libexample_ext", srcs: ["src/example.c"], vendor: true, vndk: { enabled: true, extends: "libexample", }, cflags: [ "-DLIBEXAMPLE_ENABLE_VNDK=1", "-DLIBEXAMPLE_ENABLE_VNDK_EXT=1", ], }
다음은 src/example.c
의 코드 목록입니다.
void all() { } #if !defined(LIBEXAMPLE_ENABLE_VNDK) void framework_only() { } #endif #if defined(LIBEXAMPLE_ENABLE_VNDK) void vndk() { } #endif #if defined(LIBEXAMPLE_ENABLE_VNDK_EXT) void vndk_ext() { } #endif
이러한 두 파일에 따라 빌드 시스템은 다음의 내보낸 기호를 포함하는 공유 라이브러리를 생성합니다.
설치 경로 | 내보낸 기호 |
---|---|
/system/lib[64]/libexample.so |
all , framework_only |
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so |
all , vndk |
/vendor/lib[64]/vndk/libexample.so |
all , vndk , vndk_ext |
내보낸 기호의 요구사항
VNDK ABI 검사기는 VNDK 공급업체 변형의 ABI와 VNDK 확장 프로그램을 prebuilts/abi-dumps/vndk
아래의 참조 ABI 덤프와 비교합니다.
- VNDK 공급업체 변형(예:
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so
)에서 내보낸 기호는 ABI 덤프에 정의된 기호(상위 집합 아님)와 동일해야 합니다. - VNDK 확장 프로그램(예:
/vendor/lib[64]/vndk/libexample.so
)에서 내보낸 기호는 ABI 덤프에 정의된 기호의 상위 집합이어야 합니다.
VNDK 공급업체 변형 또는 VNDK 확장 프로그램이 위 요구사항을 충족하지 못하면 VNDK ABI 검사기에서 빌드 오류가 발생하고 빌드가 중지됩니다.
공급업체 변형에서 소스 파일 또는 공유 라이브러리 제외
공급업체 변형에서 소스 파일을 제외하려면 파일을 exclude_srcs
속성에 추가합니다. 마찬가지로 공유 라이브러리가 공급업체 변형에 연결되지 않도록 하려면 이러한 라이브러리를 exclude_shared_libs
속성에 추가합니다. 예를 들면 다음과 같습니다.
cc_library { name: "libexample_cond_exclude", srcs: ["fwk.c", "both.c"], shared_libs: ["libfwk_only", "libboth"], vendor_available: true, target: { vendor: { exclude_srcs: ["fwk.c"], exclude_shared_libs: ["libfwk_only"], }, }, }
이 예에서 libexample_cond_exclude
의 핵심 변형은 fwk.c
와 both.c
의 코드를 포함하고 libfwk_only
와 libboth
공유 라이브러리에 종속됩니다. fwk.c
는 exclude_srcs
속성에 의해 제외되므로 libexample_cond_exclude
의 공급업체 변형은 both.c
의 코드만 포함합니다. 마찬가지로 공유 라이브러리 libboth
에만 종속됩니다. libfwk_only
는 exclude_shared_libs
속성에 의해 제외되기 때문입니다.
VNDK 확장 프로그램에서 헤더 내보내기
VNDK 확장 프로그램은 새 클래스나 새 함수를 VNDK 공유 라이브러리에 추가할 수 있습니다. 이러한 선언은 독립 헤더에 보관하여 기존 헤더가 변경되지 않도록 하는 것이 좋습니다.
예를 들어 새 헤더 파일 include-ext/example/ext/feature_name.h
는 VNDK 확장 프로그램 libexample_ext
를 위해 생성됩니다.
- Android.bp
- include-ext/example/ext/feature_name.h
- include/example/example.h
- src/example.c
- src/ext/feature_name.c
다음의 Android.bp
에서 libexample_ext
는 include
와 include-ext
를 모두 내보내는 반면 libexample
은 include
만 내보냅니다. 이렇게 하면 libexample
사용자로 인해 feature_name.h
가 잘못 포함되는 일은 없습니다.
cc_library { name: "libexample", srcs: ["src/example.c"], export_include_dirs: ["include"], vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libexample_ext", srcs: [ "src/example.c", "src/ext/feature_name.c", ], export_include_dirs: [ "include", "include-ext", ], vendor: true, vndk: { enabled: true, extends: "libexample", }, }
확장 프로그램을 독립적인 헤더 파일로 분리할 수 없다면 #ifdef
가드를 추가할 수 있습니다. 하지만 VNDK 확장 프로그램의 모든 사용자가 정의 플래그를 추가해야 합니다. cc_defaults
를 정의하여 정의 플래그를 cflags
에 추가하고 shared_libs
로 공유 라이브러리를 연결할 수 있습니다.
예를 들어 새 멤버 함수인 Example2::get_b()
를 VNDK 확장 프로그램 libexample2_ext
에 추가하려면 기존 헤더 파일을 수정하고 #ifdef
가드를 추가해야 합니다.
#ifndef LIBEXAMPLE2_EXAMPLE_H_ #define LIBEXAMPLE2_EXAMPLE_H_ class Example2 { public: Example2(); void get_a(); #ifdef LIBEXAMPLE2_ENABLE_VNDK_EXT void get_b(); #endif private: void *impl_; }; #endif // LIBEXAMPLE2_EXAMPLE_H_
libexample2_ext
의 사용자를 위해 libexample2_ext_defaults
라는 cc_defaults
를 다음과 같이 정의합니다.
cc_library { name: "libexample2", srcs: ["src/example2.cpp"], export_include_dirs: ["include"], vendor_available: true, vndk: { enabled: true, }, } cc_library { name: "libexample2_ext", srcs: ["src/example2.cpp"], export_include_dirs: ["include"], vendor: true, vndk: { enabled: true, extends: "libexample2", }, cflags: [ "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1", ], } cc_defaults { name: "libexample2_ext_defaults", shared_libs: [ "libexample2_ext", ], cflags: [ "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1", ], }
libexample2_ext
의 사용자는 defaults
속성에 libexample2_ext_defaults
를 간단히 포함할 수 있습니다.
cc_binary { name: "example2_user_executable", defaults: ["libexample2_ext_defaults"], vendor: true, }
제품 패키지
Android 빌드 시스템에서는 변수 PRODUCT_PACKAGES
가 기기에 설치되어야 하는 실행 프로그램, 공유 라이브러리 또는 패키지를 지정합니다. 지정된 모듈의 전이 종속 항목은 기기에도 암시적으로 설치됩니다.
BOARD_VNDK_VERSION
이 사용 설정되면 vendor_available
또는 vndk.enabled
가 있는 모듈은 특별하게 취급됩니다. 프레임워크 모듈이 vendor_available
또는 vndk.enabled
가 있는 모듈에 종속되면 핵심 변형은 전이 설치 집합에 포함됩니다. 공급업체 모듈이 vendor_available
이 있는 모듈에 종속되면 공급업체 변형은 전이 설치 집합에 포함됩니다. 그러나 vndk.enabled
가 있는 모듈의 공급업체 변형은 공급업체 모듈에서 사용되는지 여부와 관계없이 설치됩니다.
종속 항목이 빌드 시스템에 표시되면(예: 런타임에 dlopen()
으로 열 수 있는 공유 라이브러리) PRODUCT_PACKAGES
에 모듈 이름을 지정하여 이러한 모듈을 명시적으로 설치해야 합니다.
모듈에 vendor_available
또는 vndk.enabled
가 있다면 모듈 이름은 핵심 변형을 나타냅니다. PRODUCT_PACKAGES
에 공급업체 변형을 명시적으로 지정하려면 .vendor
접미사를 모듈 이름에 추가합니다. 예를 들면 다음과 같습니다.
cc_library { name: "libexample", srcs: ["example.c"], vendor_available: true, }
이 예에서 libexample
은 /system/lib[64]/libexample.so
를, libexample.vendor
는 /vendor/lib[64]/libexample.so
를 의미합니다. /vendor/lib[64]/libexample.so
를 설치하려면 PRODUCT_PACKAGES
에 libexample.vendor
를 추가합니다.
PRODUCT_PACKAGES += libexample.vendor